00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "MPEG1or2FileServerDemux.hh"
00022 #include "MPEG1or2DemuxedServerMediaSubsession.hh"
00023 #include "ByteStreamFileSource.hh"
00024
00025 MPEG1or2FileServerDemux*
00026 MPEG1or2FileServerDemux::createNew(UsageEnvironment& env, char const* fileName,
00027 Boolean reuseFirstSource) {
00028 return new MPEG1or2FileServerDemux(env, fileName, reuseFirstSource);
00029 }
00030
00031 static float MPEG1or2ProgramStreamFileDuration(UsageEnvironment& env,
00032 char const* fileName,
00033 unsigned& fileSize);
00034 MPEG1or2FileServerDemux
00035 ::MPEG1or2FileServerDemux(UsageEnvironment& env, char const* fileName,
00036 Boolean reuseFirstSource)
00037 : Medium(env),
00038 fReuseFirstSource(reuseFirstSource),
00039 fSession0Demux(NULL), fLastCreatedDemux(NULL), fLastClientSessionId(~0) {
00040 fFileName = strDup(fileName);
00041 fFileDuration = MPEG1or2ProgramStreamFileDuration(env, fileName, fFileSize);
00042 }
00043
00044 MPEG1or2FileServerDemux::~MPEG1or2FileServerDemux() {
00045 Medium::close(fSession0Demux);
00046 delete[] (char*)fFileName;
00047 }
00048
00049 ServerMediaSubsession*
00050 MPEG1or2FileServerDemux::newAudioServerMediaSubsession() {
00051 return MPEG1or2DemuxedServerMediaSubsession::createNew(*this, 0xC0, fReuseFirstSource);
00052 }
00053
00054 ServerMediaSubsession*
00055 MPEG1or2FileServerDemux::newVideoServerMediaSubsession(Boolean iFramesOnly,
00056 double vshPeriod) {
00057 return MPEG1or2DemuxedServerMediaSubsession::createNew(*this, 0xE0, fReuseFirstSource,
00058 iFramesOnly, vshPeriod);
00059 }
00060
00061 ServerMediaSubsession*
00062 MPEG1or2FileServerDemux::newAC3AudioServerMediaSubsession() {
00063 return MPEG1or2DemuxedServerMediaSubsession::createNew(*this, 0xBD, fReuseFirstSource);
00064
00065 }
00066
00067 MPEG1or2DemuxedElementaryStream*
00068 MPEG1or2FileServerDemux::newElementaryStream(unsigned clientSessionId,
00069 u_int8_t streamIdTag) {
00070 MPEG1or2Demux* demuxToUse;
00071 if (clientSessionId == 0) {
00072
00073
00074
00075
00076
00077
00078 if (fSession0Demux == NULL) {
00079
00080 ByteStreamFileSource* fileSource
00081 = ByteStreamFileSource::createNew(envir(), fFileName);
00082 if (fileSource == NULL) return NULL;
00083 fSession0Demux = MPEG1or2Demux::createNew(envir(), fileSource, False);
00084 }
00085 demuxToUse = fSession0Demux;
00086 } else {
00087
00088
00089 if (clientSessionId != fLastClientSessionId) {
00090
00091 ByteStreamFileSource* fileSource
00092 = ByteStreamFileSource::createNew(envir(), fFileName);
00093 if (fileSource == NULL) return NULL;
00094
00095 fLastCreatedDemux = MPEG1or2Demux::createNew(envir(), fileSource, True);
00096
00097
00098 fLastClientSessionId = clientSessionId;
00099
00100
00101
00102 }
00103 demuxToUse = fLastCreatedDemux;
00104 }
00105
00106 if (demuxToUse == NULL) return NULL;
00107
00108 return demuxToUse->newElementaryStream(streamIdTag);
00109 }
00110
00111
00112 static Boolean getMPEG1or2TimeCode(FramedSource* dataSource,
00113 MPEG1or2Demux& parentDemux,
00114 Boolean returnFirstSeenCode,
00115 float& timeCode);
00116
00117 static float MPEG1or2ProgramStreamFileDuration(UsageEnvironment& env,
00118 char const* fileName,
00119 unsigned& fileSize) {
00120 FramedSource* dataSource = NULL;
00121 float duration = 0.0;
00122 fileSize = 0;
00123
00124 do {
00125
00126 ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(env, fileName);
00127 if (fileSource == NULL) break;
00128 dataSource = fileSource;
00129
00130 fileSize = (unsigned)(fileSource->fileSize());
00131 if (fileSize == 0) break;
00132
00133
00134 MPEG1or2Demux* baseDemux = MPEG1or2Demux::createNew(env, dataSource, True);
00135 if (baseDemux == NULL) break;
00136
00137
00138 dataSource = baseDemux->newRawPESStream();
00139
00140
00141 float firstTimeCode;
00142 if (!getMPEG1or2TimeCode(dataSource, *baseDemux, True, firstTimeCode)) break;
00143
00144
00145
00146
00147 baseDemux->flushInput();
00148 unsigned const startByteFromEnd = 100000;
00149 unsigned newFilePosition
00150 = fileSize < startByteFromEnd ? 0 : fileSize - startByteFromEnd;
00151 if (newFilePosition > 0) fileSource->seekToByteAbsolute(newFilePosition);
00152
00153 float lastTimeCode;
00154 if (!getMPEG1or2TimeCode(dataSource, *baseDemux, False, lastTimeCode)) break;
00155
00156
00157 float timeCodeDiff = lastTimeCode - firstTimeCode;
00158 if (timeCodeDiff < 0) break;
00159 duration = timeCodeDiff;
00160 } while (0);
00161
00162 Medium::close(dataSource);
00163 return duration;
00164 }
00165
00166 class DummySink: public MediaSink {
00167 public:
00168 DummySink(MPEG1or2Demux& demux, Boolean returnFirstSeenCode);
00169 virtual ~DummySink();
00170
00171 char watchVariable;
00172
00173 private:
00174
00175 virtual Boolean continuePlaying();
00176
00177 private:
00178 static void afterGettingFrame(void* clientData, unsigned frameSize,
00179 unsigned numTruncatedBytes,
00180 struct timeval presentationTime,
00181 unsigned durationInMicroseconds);
00182 void afterGettingFrame1();
00183
00184 private:
00185 MPEG1or2Demux& fOurDemux;
00186 Boolean fReturnFirstSeenCode;
00187 unsigned char fBuf[10000];
00188 };
00189
00190 static void afterPlayingDummySink(DummySink* sink);
00191 static float computeSCRTimeCode(MPEG1or2Demux::SCR const& scr);
00192
00193 static Boolean getMPEG1or2TimeCode(FramedSource* dataSource,
00194 MPEG1or2Demux& parentDemux,
00195 Boolean returnFirstSeenCode,
00196 float& timeCode) {
00197
00198 parentDemux.lastSeenSCR().isValid = False;
00199 UsageEnvironment& env = dataSource->envir();
00200 DummySink sink(parentDemux, returnFirstSeenCode);
00201 sink.startPlaying(*dataSource,
00202 (MediaSink::afterPlayingFunc*)afterPlayingDummySink, &sink);
00203 env.taskScheduler().doEventLoop(&sink.watchVariable);
00204
00205 timeCode = computeSCRTimeCode(parentDemux.lastSeenSCR());
00206 return parentDemux.lastSeenSCR().isValid;
00207 }
00208
00209
00211
00212 DummySink::DummySink(MPEG1or2Demux& demux, Boolean returnFirstSeenCode)
00213 : MediaSink(demux.envir()),
00214 watchVariable(0), fOurDemux(demux), fReturnFirstSeenCode(returnFirstSeenCode) {
00215 }
00216
00217 DummySink::~DummySink() {
00218 }
00219
00220 Boolean DummySink::continuePlaying() {
00221 if (fSource == NULL) return False;
00222
00223 fSource->getNextFrame(fBuf, sizeof fBuf,
00224 afterGettingFrame, this,
00225 onSourceClosure, this);
00226 return True;
00227 }
00228
00229 void DummySink::afterGettingFrame(void* clientData, unsigned ,
00230 unsigned ,
00231 struct timeval ,
00232 unsigned ) {
00233 DummySink* sink = (DummySink*)clientData;
00234 sink->afterGettingFrame1();
00235 }
00236
00237 void DummySink::afterGettingFrame1() {
00238 if (fReturnFirstSeenCode && fOurDemux.lastSeenSCR().isValid) {
00239
00240
00241 onSourceClosure(this);
00242 return;
00243 }
00244
00245 continuePlaying();
00246 }
00247
00248 static void afterPlayingDummySink(DummySink* sink) {
00249
00250 sink->watchVariable = ~0;
00251 }
00252
00253 static float computeSCRTimeCode(MPEG1or2Demux::SCR const& scr) {
00254 double result = scr.remainingBits/90000.0 + scr.extension/300.0;
00255 if (scr.highBit) {
00256
00257 double const highBitValue = (256*1024*1024)/5625.0;
00258 result += highBitValue;
00259 }
00260
00261 return (float)result;
00262 }