Пример #1
0
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) {
}