void MPEG1or2Demux ::continueReadProcessing(void* clientData, unsigned char* /*ptr*/, unsigned /*size*/, struct timeval /*presentationTime*/) { MPEG1or2Demux* demux = (MPEG1or2Demux*)clientData; demux->continueReadProcessing(); }
static Boolean getMPEG1or2TimeCode(FramedSource* dataSource, MPEG1or2Demux& parentDemux, Boolean returnFirstSeenCode, float& timeCode) { // Start reading through "dataSource", until we see a SCR time code: parentDemux.lastSeenSCR().isValid = False; UsageEnvironment& env = dataSource->envir(); // alias MFSD_DummySink sink(parentDemux, returnFirstSeenCode); sink.startPlaying(*dataSource, (MediaSink::afterPlayingFunc*)afterPlayingMFSD_DummySink, &sink); env.taskScheduler().doEventLoop(&sink.watchVariable); timeCode = computeSCRTimeCode(parentDemux.lastSeenSCR()); return parentDemux.lastSeenSCR().isValid; }
static float MPEG1or2ProgramStreamFileDuration(UsageEnvironment& env, char const* fileName, unsigned& fileSize) { FramedSource* dataSource = NULL; float duration = 0.0; // until we learn otherwise fileSize = 0; // ditto do { // Open the input file as a 'byte-stream file source': ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(env, fileName); if (fileSource == NULL) break; dataSource = fileSource; fileSize = (unsigned)(fileSource->fileSize()); if (fileSize == 0) break; // Create a MPEG demultiplexor that reads from that source. MPEG1or2Demux* baseDemux = MPEG1or2Demux::createNew(env, dataSource, True); if (baseDemux == NULL) break; // Create, from this, a source that returns raw PES packets: dataSource = baseDemux->newRawPESStream(); // Read the first time code from the file: float firstTimeCode; if (!getMPEG1or2TimeCode(dataSource, *baseDemux, True, firstTimeCode)) break; // Then, read the last time code from the file. // (Before doing this, flush the demux's input buffers, // and seek towards the end of the file, for efficiency.) baseDemux->flushInput(); unsigned const startByteFromEnd = 100000; unsigned newFilePosition = fileSize < startByteFromEnd ? 0 : fileSize - startByteFromEnd; if (newFilePosition > 0) fileSource->seekToByteAbsolute(newFilePosition); float lastTimeCode; if (!getMPEG1or2TimeCode(dataSource, *baseDemux, False, lastTimeCode)) break; // Take the difference between these time codes as being the file duration: float timeCodeDiff = lastTimeCode - firstTimeCode; if (timeCodeDiff < 0) break; duration = timeCodeDiff; } while (0); Medium::close(dataSource); return duration; }
MPEG1or2DemuxedElementaryStream* MPEG1or2FileServerDemux::newElementaryStream(unsigned clientSessionId, u_int8_t streamIdTag) { MPEG1or2Demux* demuxToUse; if (clientSessionId == 0) { // 'Session 0' is treated especially, because its audio & video streams // are created and destroyed one-at-a-time, rather than both streams being // created, and then (later) both streams being destroyed (as is the case // for other ('real') session ids). Because of this, a separate demux is // used for session 0, and its deletion is managed by us, rather than // happening automatically. if (fSession0Demux == NULL) { // Open our input file as a 'byte-stream file source': ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName); if (fileSource == NULL) return NULL; fSession0Demux = MPEG1or2Demux::createNew(envir(), fileSource, False/*note!*/); } demuxToUse = fSession0Demux; } else { // First, check whether this is a new client session. If so, create a new // demux for it: if (clientSessionId != fLastClientSessionId) { // Open our input file as a 'byte-stream file source': ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName); if (fileSource == NULL) return NULL; fLastCreatedDemux = MPEG1or2Demux::createNew(envir(), fileSource, True); // Note: We tell the demux to delete itself when its last // elementary stream is deleted. fLastClientSessionId = clientSessionId; // Note: This code relies upon the fact that the creation of streams for // different client sessions do not overlap - so one "MPEG1or2Demux" is used // at a time. } demuxToUse = fLastCreatedDemux; } if (demuxToUse == NULL) return NULL; // shouldn't happen return demuxToUse->newElementaryStream(streamIdTag); }
int main(int argc, char **argv) { // Begin by setting up our usage environment: TaskScheduler *scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); // Open the input file as a 'byte-stream file source': FramedSource *inputSource = ByteStreamFileSource::createNew(*env, inputFileName); if (inputSource == NULL) { *env << "Unable to open file \"" << inputFileName << "\" as a byte-stream file source\n"; exit(1); } // Create a MPEG demultiplexor that reads from that source. MPEG1or2Demux *baseDemultiplexor = MPEG1or2Demux::createNew(*env, inputSource); // Create, from this, a source that returns raw PES packets: MPEG1or2DemuxedElementaryStream *pesSource = baseDemultiplexor->newRawPESStream(); // And, from this, a filter that converts to MPEG-2 Transport Stream frames: FramedSource *tsFrames = MPEG2TransportStreamFromPESSource::createNew(*env, pesSource); // Open the output file as a 'file sink': MediaSink *outputSink = FileSink::createNew(*env, outputFileName); if (outputSink == NULL) { *env << "Unable to open file \"" << outputFileName << "\" as a file sink\n"; exit(1); } // Finally, start playing: *env << "Beginning to read...\n"; outputSink->startPlaying(*tsFrames, afterPlaying, NULL); env->taskScheduler().doEventLoop(); // does not return return 0; // only to prevent compiler warning }
void CProgramToTransportStreamRecorder::Initialize(wchar_t* fileNameOut) { LogDebug(L"CProgramToTransportStreamRecorder::Initialize %s", fileNameOut); m_BufferThreadActive=false; m_buffer.Clear(); m_inputSource = CMemoryStreamSource::createNew(*m_env, "",m_buffer); if (m_inputSource == NULL) { *m_env << "Unable to open memorystream as a byte-stream source\n"; return; } // Create a MPEG demultiplexor that reads from that source. MPEG1or2Demux* baseDemultiplexor = MPEG1or2Demux::createNew(*m_env, m_inputSource); // Create, from this, a source that returns raw PES packets: MPEG1or2DemuxedElementaryStream* pesSource = baseDemultiplexor->newRawPESStream(); // And, from this, a filter that converts to MPEG-2 Transport Stream frames: m_tsFrames = MPEG2TransportStreamFromPESSource::createNew(*m_env, pesSource); ((MPEG2TransportStreamFromPESSource*) m_tsFrames)->SetSourceType(m_iProgramType); m_outputSink = CFileSinkRecorder::createNew(*m_env, fileNameOut); if (m_outputSink == NULL) { *m_env << "Unable to open file \"" << fileNameOut << "\" as a file sink\n"; return; } m_buffer.Clear(); m_iPacketsToSkip=100; //StartBufferThread(); m_bSendVideoAudioObserverEvents = true; m_bStarting=true; m_bRunning=true; }
MFSD_DummySink::MFSD_DummySink(MPEG1or2Demux& demux, Boolean returnFirstSeenCode) : MediaSink(demux.envir()), watchVariable(0), fOurDemux(demux), fReturnFirstSeenCode(returnFirstSeenCode) { }