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 "MPEG2TransportStreamTrickModeFilter.hh"
00025 #include <ByteStreamFileSource.hh>
00026
00027
00028
00029
00030
00031
00032
00033 #define KEEP_ORIGINAL_FRAME_RATE False
00034
00035 MPEG2TransportStreamTrickModeFilter* MPEG2TransportStreamTrickModeFilter
00036 ::createNew(UsageEnvironment& env, FramedSource* inputSource,
00037 MPEG2TransportStreamIndexFile* indexFile, int scale) {
00038 return new MPEG2TransportStreamTrickModeFilter(env, inputSource, indexFile, scale);
00039 }
00040
00041 MPEG2TransportStreamTrickModeFilter
00042 ::MPEG2TransportStreamTrickModeFilter(UsageEnvironment& env, FramedSource* inputSource,
00043 MPEG2TransportStreamIndexFile* indexFile, int scale)
00044 : FramedFilter(env, inputSource),
00045 fHaveStarted(False), fIndexFile(indexFile), fScale(scale), fDirection(1),
00046 fState(SKIPPING_FRAME), fFrameCount(0),
00047 fNextIndexRecordNum(0), fNextTSPacketNum(0),
00048 fCurrentTSPacketNum((unsigned long)(-1)), fUseSavedFrameNextTime(False) {
00049 if (fScale < 0) {
00050 fScale = -fScale;
00051 fDirection = -1;
00052 }
00053 }
00054
00055 MPEG2TransportStreamTrickModeFilter::~MPEG2TransportStreamTrickModeFilter() {
00056 }
00057
00058 Boolean MPEG2TransportStreamTrickModeFilter::seekTo(unsigned long tsPacketNumber,
00059 unsigned long indexRecordNumber) {
00060 seekToTransportPacket(tsPacketNumber);
00061 fNextIndexRecordNum = indexRecordNumber;
00062 return True;
00063 }
00064
00065 #define isIFrameStart(type) ((type) == 0x81 || (type) == 0x85)
00066
00067 #define isNonIFrameStart(type) ((type) == 0x83 || (type) == 0x88)
00068
00069 void MPEG2TransportStreamTrickModeFilter::doGetNextFrame() {
00070
00071
00072
00073
00074 if (fMaxSize < TRANSPORT_PACKET_SIZE) {
00075 fFrameSize = 0;
00076 afterGetting(this);
00077 return;
00078 }
00079
00080 while (1) {
00081
00082
00083
00084
00085 u_int8_t recordType;
00086 float recordPCR;
00087 Boolean endOfIndexFile = False;
00088 if (!fIndexFile->readIndexRecordValues(fNextIndexRecordNum,
00089 fDesiredTSPacketNum, fDesiredDataOffset,
00090 fDesiredDataSize, recordPCR,
00091 recordType)) {
00092
00093
00094
00095 if (fState != DELIVERING_SAVED_FRAME) {
00096 onSourceClosure1();
00097 return;
00098 }
00099 endOfIndexFile = True;
00100 } else if (!fHaveStarted) {
00101 fFirstPCR = recordPCR;
00102 fHaveStarted = True;
00103 }
00104
00105 fNextIndexRecordNum
00106 += (fState == DELIVERING_SAVED_FRAME) ? 1 : fDirection;
00107
00108
00109 switch (fState) {
00110 case SKIPPING_FRAME:
00111 case SAVING_AND_DELIVERING_FRAME: {
00112
00113 if (isIFrameStart(recordType)) {
00114
00115 fSavedFrameIndexRecordStart = fNextIndexRecordNum - fDirection;
00116 fUseSavedFrameNextTime = True;
00117
00118 if ((fFrameCount++)%fScale == 0 && fUseSavedFrameNextTime) {
00119
00120 fFrameCount = 1;
00121 if (fDirection > 0) {
00122
00123 fState = SAVING_AND_DELIVERING_FRAME;
00124
00125 fDesiredDataPCR = recordPCR;
00126 attemptDeliveryToClient();
00127 return;
00128 } else {
00129
00130
00131 fState = DELIVERING_SAVED_FRAME;
00132 fSavedSequentialIndexRecordNum = fNextIndexRecordNum;
00133 fDesiredDataPCR = recordPCR;
00134
00135 fNextIndexRecordNum = fSavedFrameIndexRecordStart;
00136
00137 }
00138 } else {
00139
00140 fState = SKIPPING_FRAME;
00141 }
00142 } else if (isNonIFrameStart(recordType)) {
00143 if ((fFrameCount++)%fScale == 0 && fUseSavedFrameNextTime) {
00144
00145
00146 fFrameCount = 1;
00147 fState = DELIVERING_SAVED_FRAME;
00148 fSavedSequentialIndexRecordNum = fNextIndexRecordNum;
00149 fDesiredDataPCR = recordPCR;
00150
00151 fNextIndexRecordNum = fSavedFrameIndexRecordStart;
00152
00153 } else {
00154
00155 fState = SKIPPING_FRAME;
00156 }
00157 } else {
00158
00159 if (fState == SAVING_AND_DELIVERING_FRAME) {
00160
00161 fDesiredDataPCR = recordPCR;
00162 attemptDeliveryToClient();
00163 return;
00164 }
00165 }
00166 break;
00167 }
00168 case DELIVERING_SAVED_FRAME: {
00169
00170 if (endOfIndexFile
00171 || (isIFrameStart(recordType)
00172 && fNextIndexRecordNum-1 != fSavedFrameIndexRecordStart)
00173 || isNonIFrameStart(recordType)) {
00174
00175
00176
00177 fNextIndexRecordNum = fSavedSequentialIndexRecordNum;
00178 fUseSavedFrameNextTime = KEEP_ORIGINAL_FRAME_RATE;
00179 fState = SKIPPING_FRAME;
00180 } else {
00181
00182
00183 attemptDeliveryToClient();
00184 return;
00185 }
00186 break;
00187 }
00188 }
00189 }
00190 }
00191
00192 void MPEG2TransportStreamTrickModeFilter::doStopGettingFrames() {
00193 FramedFilter::doStopGettingFrames();
00194 fIndexFile->stopReading();
00195 }
00196
00197 void MPEG2TransportStreamTrickModeFilter::attemptDeliveryToClient() {
00198 if (fCurrentTSPacketNum == fDesiredTSPacketNum) {
00199
00200
00201 memmove(fTo, &fInputBuffer[fDesiredDataOffset], fDesiredDataSize);
00202 fFrameSize = fDesiredDataSize;
00203 float deliveryPCR = fDirection*(fDesiredDataPCR - fFirstPCR)/fScale;
00204 if (deliveryPCR < 0.0) deliveryPCR = 0.0;
00205 fPresentationTime.tv_sec = (unsigned long)deliveryPCR;
00206 fPresentationTime.tv_usec
00207 = (unsigned long)((deliveryPCR - fPresentationTime.tv_sec)*1000000.0f);
00208
00209
00210 afterGetting(this);
00211 } else {
00212
00213 readTransportPacket(fDesiredTSPacketNum);
00214 }
00215 }
00216
00217 void MPEG2TransportStreamTrickModeFilter::seekToTransportPacket(unsigned long tsPacketNum) {
00218 if (tsPacketNum == fNextTSPacketNum) return;
00219
00220 ByteStreamFileSource* tsFile = (ByteStreamFileSource*)fInputSource;
00221 u_int64_t tsPacketNum64 = (u_int64_t)tsPacketNum;
00222 tsFile->seekToByteAbsolute(tsPacketNum64*TRANSPORT_PACKET_SIZE);
00223
00224 fNextTSPacketNum = tsPacketNum;
00225 }
00226
00227 void MPEG2TransportStreamTrickModeFilter::readTransportPacket(unsigned long tsPacketNum) {
00228 seekToTransportPacket(tsPacketNum);
00229 fInputSource->getNextFrame(fInputBuffer, TRANSPORT_PACKET_SIZE,
00230 afterGettingFrame, this,
00231 onSourceClosure, this);
00232 }
00233
00234 void MPEG2TransportStreamTrickModeFilter
00235 ::afterGettingFrame(void* clientData, unsigned frameSize,
00236 unsigned ,
00237 struct timeval presentationTime,
00238 unsigned ) {
00239 MPEG2TransportStreamTrickModeFilter* filter = (MPEG2TransportStreamTrickModeFilter*)clientData;
00240 filter->afterGettingFrame1(frameSize);
00241 }
00242
00243 void MPEG2TransportStreamTrickModeFilter::afterGettingFrame1(unsigned frameSize) {
00244 if (frameSize != TRANSPORT_PACKET_SIZE) {
00245
00246 onSourceClosure1();
00247 return;
00248 }
00249
00250 fCurrentTSPacketNum = fNextTSPacketNum;
00251 ++fNextTSPacketNum;
00252
00253
00254 attemptDeliveryToClient();
00255 }
00256
00257 void MPEG2TransportStreamTrickModeFilter::onSourceClosure(void* clientData) {
00258 MPEG2TransportStreamTrickModeFilter* filter = (MPEG2TransportStreamTrickModeFilter*)clientData;
00259 filter->onSourceClosure1();
00260 }
00261
00262 void MPEG2TransportStreamTrickModeFilter::onSourceClosure1() {
00263 fIndexFile->stopReading();
00264 FramedSource::handleClosure(this);
00265 }