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 #define MFSD_DUMMY_SINK_BUFFER_SIZE (6+65535)
00167
00168 class MFSD_DummySink: public MediaSink {
00169 public:
00170 MFSD_DummySink(MPEG1or2Demux& demux, Boolean returnFirstSeenCode);
00171 virtual ~MFSD_DummySink();
00172
00173 char watchVariable;
00174
00175 private:
00176
00177 virtual Boolean continuePlaying();
00178
00179 private:
00180 static void afterGettingFrame(void* clientData, unsigned frameSize,
00181 unsigned numTruncatedBytes,
00182 struct timeval presentationTime,
00183 unsigned durationInMicroseconds);
00184 void afterGettingFrame1();
00185
00186 private:
00187 MPEG1or2Demux& fOurDemux;
00188 Boolean fReturnFirstSeenCode;
00189 unsigned char fBuf[MFSD_DUMMY_SINK_BUFFER_SIZE];
00190 };
00191
00192 static void afterPlayingMFSD_DummySink(MFSD_DummySink* sink);
00193 static float computeSCRTimeCode(MPEG1or2Demux::SCR const& scr);
00194
00195 static Boolean getMPEG1or2TimeCode(FramedSource* dataSource,
00196 MPEG1or2Demux& parentDemux,
00197 Boolean returnFirstSeenCode,
00198 float& timeCode) {
00199
00200 parentDemux.lastSeenSCR().isValid = False;
00201 UsageEnvironment& env = dataSource->envir();
00202 MFSD_DummySink sink(parentDemux, returnFirstSeenCode);
00203 sink.startPlaying(*dataSource,
00204 (MediaSink::afterPlayingFunc*)afterPlayingMFSD_DummySink, &sink);
00205 env.taskScheduler().doEventLoop(&sink.watchVariable);
00206
00207 timeCode = computeSCRTimeCode(parentDemux.lastSeenSCR());
00208 return parentDemux.lastSeenSCR().isValid;
00209 }
00210
00211
00213
00214 MFSD_DummySink::MFSD_DummySink(MPEG1or2Demux& demux, Boolean returnFirstSeenCode)
00215 : MediaSink(demux.envir()),
00216 watchVariable(0), fOurDemux(demux), fReturnFirstSeenCode(returnFirstSeenCode) {
00217 }
00218
00219 MFSD_DummySink::~MFSD_DummySink() {
00220 }
00221
00222 Boolean MFSD_DummySink::continuePlaying() {
00223 if (fSource == NULL) return False;
00224
00225 fSource->getNextFrame(fBuf, sizeof fBuf,
00226 afterGettingFrame, this,
00227 onSourceClosure, this);
00228 return True;
00229 }
00230
00231 void MFSD_DummySink::afterGettingFrame(void* clientData, unsigned ,
00232 unsigned ,
00233 struct timeval ,
00234 unsigned ) {
00235 MFSD_DummySink* sink = (MFSD_DummySink*)clientData;
00236 sink->afterGettingFrame1();
00237 }
00238
00239 void MFSD_DummySink::afterGettingFrame1() {
00240 if (fReturnFirstSeenCode && fOurDemux.lastSeenSCR().isValid) {
00241
00242
00243 onSourceClosure(this);
00244 return;
00245 }
00246
00247 continuePlaying();
00248 }
00249
00250 static void afterPlayingMFSD_DummySink(MFSD_DummySink* sink) {
00251
00252 sink->watchVariable = ~0;
00253 }
00254
00255 static float computeSCRTimeCode(MPEG1or2Demux::SCR const& scr) {
00256 double result = scr.remainingBits/90000.0 + scr.extension/300.0;
00257 if (scr.highBit) {
00258
00259 double const highBitValue = (256*1024*1024)/5625.0;
00260 result += highBitValue;
00261 }
00262
00263 return (float)result;
00264 }