00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "DVVideoStreamFramer.hh"
00023 #include "GroupsockHelper.hh"
00024
00026
00027 DVVideoStreamFramer::DVVideoStreamFramer(UsageEnvironment& env, FramedSource* inputSource,
00028 Boolean sourceIsSeekable, Boolean leavePresentationTimesUnmodified)
00029 : FramedFilter(env, inputSource),
00030 fLeavePresentationTimesUnmodified(leavePresentationTimesUnmodified),
00031 fOurProfile(NULL), fInitialBlocksPresent(False), fSourceIsSeekable(sourceIsSeekable) {
00032 fTo = NULL;
00033
00034 gettimeofday(&fNextFramePresentationTime, NULL);
00035 }
00036
00037 DVVideoStreamFramer::~DVVideoStreamFramer() {
00038 }
00039
00040 DVVideoStreamFramer*
00041 DVVideoStreamFramer::createNew(UsageEnvironment& env, FramedSource* inputSource,
00042 Boolean sourceIsSeekable, Boolean leavePresentationTimesUnmodified) {
00043 return new DVVideoStreamFramer(env, inputSource, sourceIsSeekable, leavePresentationTimesUnmodified);
00044 }
00045
00046
00047 struct DVVideoProfile {
00048 char const* name;
00049 unsigned apt;
00050 unsigned sType;
00051 unsigned sequenceCount;
00052 unsigned channelCount;
00053 unsigned dvFrameSize;
00054 double frameDuration;
00055 };
00056
00057 static DVVideoProfile const profiles[] = {
00058 { "SD-VCR/525-60", 0, 0x00, 10, 1, 120000, (1000000*1001)/30000.0 },
00059 { "SD-VCR/625-50", 0, 0x00, 12, 1, 144000, 1000000/25.0 },
00060 { "314M-25/525-60", 1, 0x00, 10, 1, 120000, (1000000*1001)/30000.0 },
00061 { "314M-25/625-50", 1, 0x00, 12, 1, 144000, 1000000/25.0 },
00062 { "314M-50/525-60", 1, 0x04, 10, 2, 240000, (1000000*1001)/30000.0 },
00063 { "314M-50/625-50", 1, 0x04, 12, 2, 288000, 1000000/25.0 },
00064 { "370M/1080-60i", 1, 0x14, 10, 4, 480000, (1000000*1001)/30000.0 },
00065 { "370M/1080-50i", 1, 0x14, 12, 4, 576000, 1000000/25.0 },
00066 { "370M/720-60p", 1, 0x18, 10, 2, 240000, (1000000*1001)/60000.0 },
00067 { "370M/720-50p", 1, 0x18, 12, 2, 288000, 1000000/50.0 },
00068 { NULL, 0, 0, 0, 0, 0, 0.0 }
00069 };
00070
00071
00072 char const* DVVideoStreamFramer::profileName() {
00073 if (fOurProfile == NULL) getProfile();
00074
00075 return fOurProfile != NULL ? ((DVVideoProfile const*)fOurProfile)->name : NULL;
00076 }
00077
00078 Boolean DVVideoStreamFramer::getFrameParameters(unsigned& frameSize, double& frameDuration) {
00079 if (fOurProfile == NULL) getProfile();
00080 if (fOurProfile == NULL) return False;
00081
00082 frameSize = ((DVVideoProfile const*)fOurProfile)->dvFrameSize;
00083 frameDuration = ((DVVideoProfile const*)fOurProfile)->frameDuration;
00084 return True;
00085 }
00086
00087 void DVVideoStreamFramer::getProfile() {
00088
00089 fInputSource->getNextFrame(fSavedInitialBlocks, DV_SAVED_INITIAL_BLOCKS_SIZE,
00090 afterGettingFrame, this, FramedSource::handleClosure, this);
00091
00092
00093 envir().taskScheduler().doEventLoop(&fInitialBlocksPresent);
00094 }
00095
00096 Boolean DVVideoStreamFramer::isDVVideoStreamFramer() const {
00097 return True;
00098 }
00099
00100 void DVVideoStreamFramer::doGetNextFrame() {
00101 fFrameSize = 0;
00102
00103
00104 if (fInitialBlocksPresent && !fSourceIsSeekable) {
00105
00106 if (fMaxSize < DV_SAVED_INITIAL_BLOCKS_SIZE) {
00107 fNumTruncatedBytes = fMaxSize;
00108 afterGetting(this);
00109 return;
00110 }
00111
00112 memmove(fTo, fSavedInitialBlocks, DV_SAVED_INITIAL_BLOCKS_SIZE);
00113 fFrameSize = DV_SAVED_INITIAL_BLOCKS_SIZE;
00114 fTo += DV_SAVED_INITIAL_BLOCKS_SIZE;
00115 fInitialBlocksPresent = False;
00116 }
00117
00118
00119
00120 fMaxSize -= fMaxSize%DV_DIF_BLOCK_SIZE;
00121 getAndDeliverData();
00122 }
00123
00124 #define DV_SMALLEST_POSSIBLE_FRAME_SIZE 120000
00125
00126 void DVVideoStreamFramer::getAndDeliverData() {
00127 unsigned const totFrameSize
00128 = fOurProfile != NULL ? ((DVVideoProfile const*)fOurProfile)->dvFrameSize : DV_SMALLEST_POSSIBLE_FRAME_SIZE;
00129 unsigned totBytesToDeliver = totFrameSize < fMaxSize ? totFrameSize : fMaxSize;
00130 unsigned numBytesToRead = totBytesToDeliver - fFrameSize;
00131
00132 fInputSource->getNextFrame(fTo, numBytesToRead, afterGettingFrame, this, FramedSource::handleClosure, this);
00133 }
00134
00135 void DVVideoStreamFramer::afterGettingFrame(void* clientData, unsigned frameSize,
00136 unsigned numTruncatedBytes,
00137 struct timeval presentationTime, unsigned ) {
00138 DVVideoStreamFramer* source = (DVVideoStreamFramer*)clientData;
00139 source->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime);
00140 }
00141
00142 #define DVSectionId(n) ptr[(n)*DV_DIF_BLOCK_SIZE + 0]
00143 #define DVData(n,i) ptr[(n)*DV_DIF_BLOCK_SIZE + 3+(i)]
00144
00145 #define DV_SECTION_HEADER 0x1F
00146 #define DV_PACK_HEADER_10 0x3F
00147 #define DV_PACK_HEADER_12 0xBF
00148 #define DV_SECTION_VAUX_MIN 0x50
00149 #define DV_SECTION_VAUX_MAX 0x5F
00150 #define DV_PACK_VIDEO_SOURCE 60
00151 #ifndef MILLION
00152 #define MILLION 1000000
00153 #endif
00154
00155 void DVVideoStreamFramer::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime) {
00156 if (fOurProfile == NULL && frameSize >= DV_SAVED_INITIAL_BLOCKS_SIZE) {
00157
00158
00159
00160 u_int8_t const* data = (fTo == NULL) ? fSavedInitialBlocks : fTo;
00161 for (u_int8_t const* ptr = data; ptr + 6*DV_DIF_BLOCK_SIZE <= &data[DV_SAVED_INITIAL_BLOCKS_SIZE]; ptr += DV_DIF_BLOCK_SIZE) {
00162
00163 u_int8_t const sectionHeader = DVSectionId(0);
00164 u_int8_t const sectionVAUX = DVSectionId(5);
00165 u_int8_t const packHeaderNum = DVData(0,0);
00166
00167 if (sectionHeader == DV_SECTION_HEADER
00168 && (packHeaderNum == DV_PACK_HEADER_10 || packHeaderNum == DV_PACK_HEADER_12)
00169 && (sectionVAUX >= DV_SECTION_VAUX_MIN && sectionVAUX <= DV_SECTION_VAUX_MAX)) {
00170
00171 u_int8_t const apt = DVData(0,1)&0x07;
00172 u_int8_t const sType = DVData(5,48)&0x1F;
00173 u_int8_t const sequenceCount = (packHeaderNum == DV_PACK_HEADER_10) ? 10 : 12;
00174
00175
00176 for (DVVideoProfile const* profile = profiles; profile->name != NULL; ++profile) {
00177 if (profile->apt == apt && profile->sType == sType && profile->sequenceCount == sequenceCount) {
00178 fOurProfile = profile;
00179 break;
00180 }
00181 }
00182 break;
00183 }
00184 }
00185 }
00186
00187 if (fTo != NULL) {
00188 unsigned const totFrameSize
00189 = fOurProfile != NULL ? ((DVVideoProfile const*)fOurProfile)->dvFrameSize : DV_SMALLEST_POSSIBLE_FRAME_SIZE;
00190 fFrameSize += frameSize;
00191 fTo += frameSize;
00192 fPresentationTime = presentationTime;
00193
00194 if (fFrameSize < totFrameSize && fFrameSize < fMaxSize && numTruncatedBytes == 0) {
00195
00196 getAndDeliverData();
00197 } else {
00198
00199 fNumTruncatedBytes = totFrameSize - fFrameSize;
00200
00201 if (fOurProfile != NULL) {
00202
00203
00204 if (!fLeavePresentationTimesUnmodified) fPresentationTime = fNextFramePresentationTime;
00205
00206 DVVideoProfile const* ourProfile =(DVVideoProfile const*)fOurProfile;
00207 double durationInMicroseconds = (fFrameSize*ourProfile->frameDuration)/ourProfile->dvFrameSize;
00208 fDurationInMicroseconds = (unsigned)durationInMicroseconds;
00209 fNextFramePresentationTime.tv_usec += fDurationInMicroseconds;
00210 fNextFramePresentationTime.tv_sec += fNextFramePresentationTime.tv_usec/MILLION;
00211 fNextFramePresentationTime.tv_usec %= MILLION;
00212 }
00213
00214 afterGetting(this);
00215 }
00216 } else {
00217
00218 fInitialBlocksPresent = True;
00219 }
00220 }