liveMedia/MPEG4VideoFileServerMediaSubsession.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2013 Live Networks, Inc.  All rights reserved.
00018 // A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
00019 // on demand, from a MPEG-4 video file.
00020 // Implementation
00021 
00022 #include "MPEG4VideoFileServerMediaSubsession.hh"
00023 #include "MPEG4ESVideoRTPSink.hh"
00024 #include "ByteStreamFileSource.hh"
00025 #include "MPEG4VideoStreamFramer.hh"
00026 
00027 MPEG4VideoFileServerMediaSubsession*
00028 MPEG4VideoFileServerMediaSubsession::createNew(UsageEnvironment& env,
00029                                                char const* fileName,
00030                                                Boolean reuseFirstSource) {
00031   return new MPEG4VideoFileServerMediaSubsession(env, fileName, reuseFirstSource);
00032 }
00033 
00034 MPEG4VideoFileServerMediaSubsession
00035 ::MPEG4VideoFileServerMediaSubsession(UsageEnvironment& env,
00036                                       char const* fileName, Boolean reuseFirstSource)
00037   : FileServerMediaSubsession(env, fileName, reuseFirstSource),
00038     fAuxSDPLine(NULL), fDoneFlag(0), fDummyRTPSink(NULL) {
00039 }
00040 
00041 MPEG4VideoFileServerMediaSubsession::~MPEG4VideoFileServerMediaSubsession() {
00042   delete[] fAuxSDPLine;
00043 }
00044 
00045 static void afterPlayingDummy(void* clientData) {
00046   MPEG4VideoFileServerMediaSubsession* subsess
00047     = (MPEG4VideoFileServerMediaSubsession*)clientData;
00048   subsess->afterPlayingDummy1();
00049 }
00050 
00051 void MPEG4VideoFileServerMediaSubsession::afterPlayingDummy1() {
00052   // Unschedule any pending 'checking' task:
00053   envir().taskScheduler().unscheduleDelayedTask(nextTask());
00054   // Signal the event loop that we're done:
00055   setDoneFlag();
00056 }
00057 
00058 static void checkForAuxSDPLine(void* clientData) {
00059   MPEG4VideoFileServerMediaSubsession* subsess
00060     = (MPEG4VideoFileServerMediaSubsession*)clientData;
00061   subsess->checkForAuxSDPLine1();
00062 }
00063 
00064 void MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1() {
00065   char const* dasl;
00066 
00067   if (fAuxSDPLine != NULL) {
00068     // Signal the event loop that we're done:
00069     setDoneFlag();
00070   } else if (fDummyRTPSink != NULL && (dasl = fDummyRTPSink->auxSDPLine()) != NULL) {
00071     fAuxSDPLine= strDup(dasl);
00072     fDummyRTPSink = NULL;
00073 
00074     // Signal the event loop that we're done:
00075     setDoneFlag();
00076   } else {
00077     // try again after a brief delay:
00078     int uSecsToDelay = 100000; // 100 ms
00079     nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,
00080                               (TaskFunc*)checkForAuxSDPLine, this);
00081   }
00082 }
00083 
00084 char const* MPEG4VideoFileServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {
00085   if (fAuxSDPLine != NULL) return fAuxSDPLine; // it's already been set up (for a previous client)
00086 
00087   if (fDummyRTPSink == NULL) { // we're not already setting it up for another, concurrent stream
00088     // Note: For MPEG-4 video files, the 'config' information isn't known
00089     // until we start reading the file.  This means that "rtpSink"s
00090     // "auxSDPLine()" will be NULL initially, and we need to start reading data from our file until this changes.
00091     fDummyRTPSink = rtpSink;
00092 
00093     // Start reading the file:
00094     fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);
00095 
00096     // Check whether the sink's 'auxSDPLine()' is ready:
00097     checkForAuxSDPLine(this);
00098   }
00099 
00100   envir().taskScheduler().doEventLoop(&fDoneFlag);
00101 
00102   return fAuxSDPLine;
00103 }
00104 
00105 FramedSource* MPEG4VideoFileServerMediaSubsession
00106 ::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {
00107   estBitrate = 500; // kbps, estimate
00108 
00109   // Create the video source:
00110   ByteStreamFileSource* fileSource
00111     = ByteStreamFileSource::createNew(envir(), fFileName);
00112   if (fileSource == NULL) return NULL;
00113   fFileSize = fileSource->fileSize();
00114 
00115   // Create a framer for the Video Elementary Stream:
00116   return MPEG4VideoStreamFramer::createNew(envir(), fileSource);
00117 }
00118 
00119 RTPSink* MPEG4VideoFileServerMediaSubsession
00120 ::createNewRTPSink(Groupsock* rtpGroupsock,
00121                    unsigned char rtpPayloadTypeIfDynamic,
00122                    FramedSource* /*inputSource*/) {
00123   return MPEG4ESVideoRTPSink::createNew(envir(), rtpGroupsock,
00124                                         rtpPayloadTypeIfDynamic);
00125 }

Generated on Mon Apr 29 13:28:03 2013 for live by  doxygen 1.5.2