00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "MPEG2TransportFileServerMediaSubsession.hh"
00023 #include "SimpleRTPSink.hh"
00024
00025 MPEG2TransportFileServerMediaSubsession*
00026 MPEG2TransportFileServerMediaSubsession::createNew(UsageEnvironment& env,
00027 char const* fileName,
00028 char const* indexFileName,
00029 Boolean reuseFirstSource) {
00030 MPEG2TransportStreamIndexFile* indexFile;
00031 if (indexFileName != NULL && reuseFirstSource) {
00032
00033 env << "MPEG2TransportFileServerMediaSubsession::createNew(): ignoring the index file name, because \"reuseFirstSource\" is set\n";
00034 indexFile = NULL;
00035 } else {
00036 indexFile = MPEG2TransportStreamIndexFile::createNew(env, indexFileName);
00037 }
00038 return new MPEG2TransportFileServerMediaSubsession(env, fileName, indexFile,
00039 reuseFirstSource);
00040 }
00041
00042 MPEG2TransportFileServerMediaSubsession
00043 ::MPEG2TransportFileServerMediaSubsession(UsageEnvironment& env,
00044 char const* fileName,
00045 MPEG2TransportStreamIndexFile* indexFile,
00046 Boolean reuseFirstSource)
00047 : FileServerMediaSubsession(env, fileName, reuseFirstSource),
00048 fIndexFile(indexFile), fDuration(0.0), fClientSessionHashTable(NULL) {
00049 if (fIndexFile != NULL) {
00050 fDuration = fIndexFile->getPlayingDuration();
00051 fClientSessionHashTable = HashTable::create(ONE_WORD_HASH_KEYS);
00052 }
00053 }
00054
00055 MPEG2TransportFileServerMediaSubsession
00056 ::~MPEG2TransportFileServerMediaSubsession() {
00057 if (fIndexFile != NULL) {
00058 Medium::close(fIndexFile);
00059
00060
00061 while (1) {
00062 ClientTrickPlayState* client
00063 = (ClientTrickPlayState*)(fClientSessionHashTable->RemoveNext());
00064 if (client == NULL) break;
00065 delete client;
00066 }
00067 delete fClientSessionHashTable;
00068 }
00069 }
00070
00071 #define TRANSPORT_PACKET_SIZE 188
00072 #define TRANSPORT_PACKETS_PER_NETWORK_PACKET 7
00073
00074
00075 void MPEG2TransportFileServerMediaSubsession
00076 ::startStream(unsigned clientSessionId, void* streamToken, TaskFunc* rtcpRRHandler,
00077 void* rtcpRRHandlerClientData, unsigned short& rtpSeqNum,
00078 unsigned& rtpTimestamp,
00079 ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
00080 void* serverRequestAlternativeByteHandlerClientData) {
00081 if (fIndexFile != NULL) {
00082 ClientTrickPlayState* client = lookupClient(clientSessionId);
00083 if (client != NULL && client->areChangingScale()) {
00084
00085 client->updateStateOnPlayChange(True);
00086 OnDemandServerMediaSubsession::pauseStream(clientSessionId, streamToken);
00087
00088
00089 client->updateStateOnScaleChange();
00090 }
00091 }
00092
00093
00094 OnDemandServerMediaSubsession::startStream(clientSessionId, streamToken,
00095 rtcpRRHandler, rtcpRRHandlerClientData,
00096 rtpSeqNum, rtpTimestamp,
00097 serverRequestAlternativeByteHandler, serverRequestAlternativeByteHandlerClientData);
00098 }
00099
00100 void MPEG2TransportFileServerMediaSubsession
00101 ::pauseStream(unsigned clientSessionId, void* streamToken) {
00102 if (fIndexFile != NULL) {
00103 ClientTrickPlayState* client = lookupClient(clientSessionId);
00104 if (client != NULL) {
00105 client->updateStateOnPlayChange(False);
00106 }
00107 }
00108
00109
00110 OnDemandServerMediaSubsession::pauseStream(clientSessionId, streamToken);
00111 }
00112
00113 void MPEG2TransportFileServerMediaSubsession
00114 ::seekStream(unsigned clientSessionId, void* streamToken, double& seekNPT, double streamDuration, u_int64_t& numBytes) {
00115
00116 OnDemandServerMediaSubsession::seekStream(clientSessionId, streamToken, seekNPT, streamDuration, numBytes);
00117
00118
00119 if (fIndexFile != NULL) {
00120 ClientTrickPlayState* client = lookupClient(clientSessionId);
00121 if (client != NULL) {
00122 unsigned long numTSPacketsToStream = client->updateStateFromNPT(seekNPT, streamDuration);
00123 numBytes = numTSPacketsToStream*TRANSPORT_PACKET_SIZE;
00124 }
00125 }
00126 }
00127
00128 void MPEG2TransportFileServerMediaSubsession
00129 ::setStreamScale(unsigned clientSessionId, void* streamToken, float scale) {
00130 if (fIndexFile != NULL) {
00131 ClientTrickPlayState* client = lookupClient(clientSessionId);
00132 if (client != NULL) {
00133 client->setNextScale(scale);
00134 }
00135 }
00136
00137
00138 OnDemandServerMediaSubsession::setStreamScale(clientSessionId, streamToken, scale);
00139 }
00140
00141 void MPEG2TransportFileServerMediaSubsession
00142 ::deleteStream(unsigned clientSessionId, void*& streamToken) {
00143 if (fIndexFile != NULL) {
00144 ClientTrickPlayState* client = lookupClient(clientSessionId);
00145 if (client != NULL) {
00146 client->updateStateOnPlayChange(False);
00147 }
00148 }
00149
00150
00151 OnDemandServerMediaSubsession::deleteStream(clientSessionId, streamToken);
00152 }
00153
00154 ClientTrickPlayState* MPEG2TransportFileServerMediaSubsession::newClientTrickPlayState() {
00155 return new ClientTrickPlayState(fIndexFile);
00156 }
00157
00158 FramedSource* MPEG2TransportFileServerMediaSubsession
00159 ::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) {
00160
00161 unsigned const inputDataChunkSize
00162 = TRANSPORT_PACKETS_PER_NETWORK_PACKET*TRANSPORT_PACKET_SIZE;
00163 ByteStreamFileSource* fileSource
00164 = ByteStreamFileSource::createNew(envir(), fFileName, inputDataChunkSize);
00165 if (fileSource == NULL) return NULL;
00166 fFileSize = fileSource->fileSize();
00167
00168
00169 if (fFileSize > 0 && fDuration > 0.0) {
00170 estBitrate = (unsigned)((int64_t)fFileSize/(125*fDuration) + 0.5);
00171 } else {
00172 estBitrate = 5000;
00173 }
00174
00175
00176
00177 MPEG2TransportStreamFramer* framer
00178 = MPEG2TransportStreamFramer::createNew(envir(), fileSource);
00179
00180 if (fIndexFile != NULL) {
00181
00182 ClientTrickPlayState* client = lookupClient(clientSessionId);
00183 if (client == NULL) {
00184 client = newClientTrickPlayState();
00185 fClientSessionHashTable->Add((char const*)clientSessionId, client);
00186 }
00187 client->setSource(framer);
00188 }
00189
00190 return framer;
00191 }
00192
00193 RTPSink* MPEG2TransportFileServerMediaSubsession
00194 ::createNewRTPSink(Groupsock* rtpGroupsock,
00195 unsigned char ,
00196 FramedSource* ) {
00197 return SimpleRTPSink::createNew(envir(), rtpGroupsock,
00198 33, 90000, "video", "MP2T",
00199 1, True, False );
00200 }
00201
00202 void MPEG2TransportFileServerMediaSubsession::testScaleFactor(float& scale) {
00203 if (fIndexFile != NULL && fDuration > 0.0) {
00204
00205 int iScale = scale < 0.0 ? (int)(scale - 0.5f) : (int)(scale + 0.5f);
00206 if (iScale == 0) iScale = 1;
00207 scale = (float)iScale;
00208 } else {
00209 scale = 1.0f;
00210 }
00211 }
00212
00213 float MPEG2TransportFileServerMediaSubsession::duration() const {
00214 return fDuration;
00215 }
00216
00217 ClientTrickPlayState* MPEG2TransportFileServerMediaSubsession
00218 ::lookupClient(unsigned clientSessionId) {
00219 return (ClientTrickPlayState*)(fClientSessionHashTable->Lookup((char const*)clientSessionId));
00220 }
00221
00222
00224
00225 ClientTrickPlayState::ClientTrickPlayState(MPEG2TransportStreamIndexFile* indexFile)
00226 : fIndexFile(indexFile),
00227 fOriginalTransportStreamSource(NULL),
00228 fTrickModeFilter(NULL), fTrickPlaySource(NULL),
00229 fFramer(NULL),
00230 fScale(1.0f), fNextScale(1.0f), fNPT(0.0f),
00231 fTSRecordNum(0), fIxRecordNum(0) {
00232 }
00233
00234 unsigned long ClientTrickPlayState::updateStateFromNPT(double npt, double streamDuration) {
00235 fNPT = (float)npt;
00236
00237 unsigned long tsRecordNum, ixRecordNum;
00238 fIndexFile->lookupTSPacketNumFromNPT(fNPT, tsRecordNum, ixRecordNum);
00239
00240 updateTSRecordNum();
00241 if (tsRecordNum != fTSRecordNum) {
00242 fTSRecordNum = tsRecordNum;
00243 fIxRecordNum = ixRecordNum;
00244
00245
00246 reseekOriginalTransportStreamSource();
00247
00248
00249
00250
00251 fFramer->clearPIDStatusTable();
00252 }
00253
00254 unsigned long numTSRecordsToStream = 0;
00255 float pcrLimit = 0.0;
00256 if (streamDuration > 0.0) {
00257
00258 streamDuration += npt - (double)fNPT;
00259
00260 if (streamDuration > 0.0) {
00261
00262
00263 if (fNextScale == 1.0f) {
00264
00265
00266 unsigned long toTSRecordNum, toIxRecordNum;
00267 float toNPT = (float)(fNPT + streamDuration);
00268 fIndexFile->lookupTSPacketNumFromNPT(toNPT, toTSRecordNum, toIxRecordNum);
00269 if (toTSRecordNum > tsRecordNum) {
00270 numTSRecordsToStream = toTSRecordNum - tsRecordNum;
00271 }
00272 } else {
00273
00274
00275
00276 int direction = fNextScale < 0.0 ? -1 : 1;
00277 pcrLimit = (float)(streamDuration/(fNextScale*direction));
00278 }
00279 }
00280 }
00281 fFramer->setNumTSPacketsToStream(numTSRecordsToStream);
00282 fFramer->setPCRLimit(pcrLimit);
00283
00284 return numTSRecordsToStream;
00285 }
00286
00287 void ClientTrickPlayState::updateStateOnScaleChange() {
00288 fScale = fNextScale;
00289
00290
00291
00292 if (fTrickPlaySource != NULL) {
00293 fTrickModeFilter->forgetInputSource();
00294
00295 Medium::close(fTrickPlaySource);
00296 fTrickPlaySource = NULL;
00297 fTrickModeFilter = NULL;
00298 }
00299 if (fNextScale != 1.0f) {
00300
00301 UsageEnvironment& env = fIndexFile->envir();
00302 fTrickModeFilter = MPEG2TransportStreamTrickModeFilter
00303 ::createNew(env, fOriginalTransportStreamSource, fIndexFile, int(fNextScale));
00304 fTrickModeFilter->seekTo(fTSRecordNum, fIxRecordNum);
00305
00306
00307 fTrickPlaySource = MPEG2TransportStreamFromESSource::createNew(env);
00308 fTrickPlaySource->addNewVideoSource(fTrickModeFilter, fIndexFile->mpegVersion());
00309
00310 fFramer->changeInputSource(fTrickPlaySource);
00311 } else {
00312
00313 reseekOriginalTransportStreamSource();
00314 fFramer->changeInputSource(fOriginalTransportStreamSource);
00315 }
00316 }
00317
00318 void ClientTrickPlayState::updateStateOnPlayChange(Boolean reverseToPreviousVSH) {
00319 updateTSRecordNum();
00320 if (fTrickPlaySource == NULL) {
00321
00322
00323 fIndexFile->lookupPCRFromTSPacketNum(fTSRecordNum, reverseToPreviousVSH, fNPT, fIxRecordNum);
00324 } else {
00325
00326
00327 fIxRecordNum = fTrickModeFilter->nextIndexRecordNum();
00328 if ((long)fIxRecordNum < 0) fIxRecordNum = 0;
00329 unsigned long transportRecordNum;
00330 float pcr;
00331 u_int8_t offset, size, recordType;
00332 if (fIndexFile->readIndexRecordValues(fIxRecordNum, transportRecordNum,
00333 offset, size, pcr, recordType)) {
00334 fTSRecordNum = transportRecordNum;
00335 fNPT = pcr;
00336 }
00337 }
00338 }
00339
00340 void ClientTrickPlayState::setSource(MPEG2TransportStreamFramer* framer) {
00341 fFramer = framer;
00342 fOriginalTransportStreamSource = (ByteStreamFileSource*)(framer->inputSource());
00343 }
00344
00345 void ClientTrickPlayState::updateTSRecordNum(){
00346 if (fFramer != NULL) fTSRecordNum += (unsigned long)(fFramer->tsPacketCount());
00347 }
00348
00349 void ClientTrickPlayState::reseekOriginalTransportStreamSource() {
00350 u_int64_t tsRecordNum64 = (u_int64_t)fTSRecordNum;
00351 fOriginalTransportStreamSource->seekToByteAbsolute(tsRecordNum64*TRANSPORT_PACKET_SIZE);
00352 }