00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "MPEG1or2VideoStreamDiscreteFramer.hh"
00025
00026 MPEG1or2VideoStreamDiscreteFramer*
00027 MPEG1or2VideoStreamDiscreteFramer::createNew(UsageEnvironment& env,
00028 FramedSource* inputSource,
00029 Boolean iFramesOnly,
00030 double vshPeriod) {
00031
00032 return new MPEG1or2VideoStreamDiscreteFramer(env, inputSource,
00033 iFramesOnly, vshPeriod);
00034 }
00035
00036 MPEG1or2VideoStreamDiscreteFramer
00037 ::MPEG1or2VideoStreamDiscreteFramer(UsageEnvironment& env,
00038 FramedSource* inputSource,
00039 Boolean iFramesOnly, double vshPeriod)
00040 : MPEG1or2VideoStreamFramer(env, inputSource, iFramesOnly, vshPeriod,
00041 False),
00042 fLastNonBFrameTemporal_reference(0),
00043 fSavedVSHSize(0), fSavedVSHTimestamp(0.0),
00044 fIFramesOnly(iFramesOnly), fVSHPeriod(vshPeriod) {
00045 fLastNonBFramePresentationTime.tv_sec = 0;
00046 fLastNonBFramePresentationTime.tv_usec = 0;
00047 }
00048
00049 MPEG1or2VideoStreamDiscreteFramer::~MPEG1or2VideoStreamDiscreteFramer() {
00050 }
00051
00052 void MPEG1or2VideoStreamDiscreteFramer::doGetNextFrame() {
00053
00054
00055
00056 fInputSource->getNextFrame(fTo, fMaxSize,
00057 afterGettingFrame, this,
00058 FramedSource::handleClosure, this);
00059 }
00060
00061 void MPEG1or2VideoStreamDiscreteFramer
00062 ::afterGettingFrame(void* clientData, unsigned frameSize,
00063 unsigned numTruncatedBytes,
00064 struct timeval presentationTime,
00065 unsigned durationInMicroseconds) {
00066 MPEG1or2VideoStreamDiscreteFramer* source
00067 = (MPEG1or2VideoStreamDiscreteFramer*)clientData;
00068 source->afterGettingFrame1(frameSize, numTruncatedBytes,
00069 presentationTime, durationInMicroseconds);
00070 }
00071
00072 static double const frameRateFromCode[] = {
00073 0.0,
00074 24000/1001.0,
00075 24.0,
00076 25.0,
00077 30000/1001.0,
00078 30.0,
00079 50.0,
00080 60000/1001.0,
00081 60.0,
00082 0.0,
00083 0.0,
00084 0.0,
00085 0.0,
00086 0.0,
00087 0.0,
00088 0.0
00089 };
00090
00091 #define MILLION 1000000
00092
00093 void MPEG1or2VideoStreamDiscreteFramer
00094 ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00095 struct timeval presentationTime,
00096 unsigned durationInMicroseconds) {
00097
00098 if (frameSize >= 4 && fTo[0] == 0 && fTo[1] == 0 && fTo[2] == 1) {
00099 fPictureEndMarker = True;
00100
00101 u_int8_t nextCode = fTo[3];
00102 if (nextCode == 0xB3) {
00103
00104 if (frameSize >= 8) {
00105 u_int8_t frame_rate_code = fTo[7]&0x0F;
00106 fFrameRate = frameRateFromCode[frame_rate_code];
00107 }
00108
00109
00110
00111 unsigned vshSize;
00112 for (vshSize = 4; vshSize < frameSize-3; ++vshSize) {
00113 if (fTo[vshSize] == 0 && fTo[vshSize+1] == 0 && fTo[vshSize+2] == 1 &&
00114 (fTo[vshSize+3] == 0xB8 || fTo[vshSize+3] == 0x00)) break;
00115 }
00116 if (vshSize == frameSize-3) vshSize = frameSize;
00117 if (vshSize <= sizeof fSavedVSHBuffer) {
00118 memmove(fSavedVSHBuffer, fTo, vshSize);
00119 fSavedVSHSize = vshSize;
00120 fSavedVSHTimestamp
00121 = presentationTime.tv_sec + presentationTime.tv_usec/(double)MILLION;
00122 }
00123 } else if (nextCode == 0xB8) {
00124
00125 double pts = presentationTime.tv_sec + presentationTime.tv_usec/(double)MILLION;
00126 if (pts > fSavedVSHTimestamp + fVSHPeriod &&
00127 fSavedVSHSize + frameSize <= fMaxSize) {
00128 memmove(&fTo[fSavedVSHSize], &fTo[0], frameSize);
00129 memmove(&fTo[0], fSavedVSHBuffer, fSavedVSHSize);
00130 frameSize += fSavedVSHSize;
00131 fSavedVSHTimestamp = pts;
00132 }
00133 }
00134
00135 unsigned i = 3;
00136 if (nextCode == 0xB3 ||
00137 nextCode == 0xB8 ) {
00138
00139 for (i += 4; i < frameSize; ++i) {
00140 if (fTo[i] == 0x00
00141 && fTo[i-1] == 1 && fTo[i-2] == 0 && fTo[i-3] == 0) {
00142 nextCode = fTo[i];
00143 break;
00144 }
00145 }
00146 }
00147
00148 if (nextCode == 0x00 && i+2 < frameSize) {
00149
00150
00151 ++i;
00152 unsigned short temporal_reference = (fTo[i]<<2)|(fTo[i+1]>>6);
00153 unsigned char picture_coding_type = (fTo[i+1]&0x38)>>3;
00154
00155
00156 if (fIFramesOnly && picture_coding_type != 1) {
00157 doGetNextFrame();
00158 return;
00159 }
00160
00161
00162 if (picture_coding_type == 3
00163 && (fLastNonBFramePresentationTime.tv_usec > 0 ||
00164 fLastNonBFramePresentationTime.tv_sec > 0)) {
00165 int trIncrement
00166 = fLastNonBFrameTemporal_reference - temporal_reference;
00167 if (trIncrement < 0) trIncrement += 1024;
00168
00169 unsigned usIncrement = fFrameRate == 0.0 ? 0
00170 : (unsigned)((trIncrement*MILLION)/fFrameRate);
00171 unsigned secondsToSubtract = usIncrement/MILLION;
00172 unsigned uSecondsToSubtract = usIncrement%MILLION;
00173
00174 presentationTime = fLastNonBFramePresentationTime;
00175 if ((unsigned)presentationTime.tv_usec < uSecondsToSubtract) {
00176 presentationTime.tv_usec += MILLION;
00177 if (presentationTime.tv_sec > 0) --presentationTime.tv_sec;
00178 }
00179 presentationTime.tv_usec -= uSecondsToSubtract;
00180 if ((unsigned)presentationTime.tv_sec > secondsToSubtract) {
00181 presentationTime.tv_sec -= secondsToSubtract;
00182 } else {
00183 presentationTime.tv_sec = presentationTime.tv_usec = 0;
00184 }
00185 } else {
00186 fLastNonBFramePresentationTime = presentationTime;
00187 fLastNonBFrameTemporal_reference = temporal_reference;
00188 }
00189 }
00190 }
00191
00192
00193
00194
00195
00196 fFrameSize = frameSize;
00197 fNumTruncatedBytes = numTruncatedBytes;
00198 fPresentationTime = presentationTime;
00199 fDurationInMicroseconds = durationInMicroseconds;
00200 afterGetting(this);
00201 }