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