liveMedia/MPEG1or2DemuxedServerMediaSubsession.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-1 or 2 demuxer.
00020 // Implementation
00021 
00022 #include "MPEG1or2DemuxedServerMediaSubsession.hh"
00023 #include "MPEG1or2AudioStreamFramer.hh"
00024 #include "MPEG1or2AudioRTPSink.hh"
00025 #include "MPEG1or2VideoStreamFramer.hh"
00026 #include "MPEG1or2VideoRTPSink.hh"
00027 #include "AC3AudioStreamFramer.hh"
00028 #include "AC3AudioRTPSink.hh"
00029 #include "ByteStreamFileSource.hh"
00030 
00031 MPEG1or2DemuxedServerMediaSubsession* MPEG1or2DemuxedServerMediaSubsession
00032 ::createNew(MPEG1or2FileServerDemux& demux, u_int8_t streamIdTag,
00033             Boolean reuseFirstSource, Boolean iFramesOnly, double vshPeriod) {
00034   return new MPEG1or2DemuxedServerMediaSubsession(demux, streamIdTag,
00035                                                   reuseFirstSource,
00036                                                   iFramesOnly, vshPeriod);
00037 }
00038 
00039 MPEG1or2DemuxedServerMediaSubsession
00040 ::MPEG1or2DemuxedServerMediaSubsession(MPEG1or2FileServerDemux& demux,
00041                                        u_int8_t streamIdTag, Boolean reuseFirstSource,
00042                                        Boolean iFramesOnly, double vshPeriod)
00043   : OnDemandServerMediaSubsession(demux.envir(), reuseFirstSource),
00044     fOurDemux(demux), fStreamIdTag(streamIdTag),
00045     fIFramesOnly(iFramesOnly), fVSHPeriod(vshPeriod) {
00046 }
00047 
00048 MPEG1or2DemuxedServerMediaSubsession::~MPEG1or2DemuxedServerMediaSubsession() {
00049 }
00050 
00051 FramedSource* MPEG1or2DemuxedServerMediaSubsession
00052 ::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) {
00053   FramedSource* es = NULL;
00054   do {
00055     es = fOurDemux.newElementaryStream(clientSessionId, fStreamIdTag);
00056     if (es == NULL) break;
00057 
00058     if ((fStreamIdTag&0xF0) == 0xC0 /*MPEG audio*/) {
00059       estBitrate = 128; // kbps, estimate
00060       return MPEG1or2AudioStreamFramer::createNew(envir(), es);
00061     } else if ((fStreamIdTag&0xF0) == 0xE0 /*video*/) {
00062       estBitrate = 500; // kbps, estimate
00063       return MPEG1or2VideoStreamFramer::createNew(envir(), es,
00064                                                   fIFramesOnly, fVSHPeriod);
00065     } else if (fStreamIdTag == 0xBD /*AC-3 audio*/) {
00066       estBitrate = 192; // kbps, estimate
00067       return AC3AudioStreamFramer::createNew(envir(), es, 0x80);
00068     } else { // unknown stream type
00069       break;
00070     }
00071   } while (0);
00072 
00073   // An error occurred:
00074   Medium::close(es);
00075   return NULL;
00076 }
00077 
00078 RTPSink* MPEG1or2DemuxedServerMediaSubsession
00079 ::createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic,
00080                    FramedSource* inputSource) {
00081   if ((fStreamIdTag&0xF0) == 0xC0 /*MPEG audio*/) {
00082     return MPEG1or2AudioRTPSink::createNew(envir(), rtpGroupsock);
00083   } else if ((fStreamIdTag&0xF0) == 0xE0 /*video*/) {
00084     return MPEG1or2VideoRTPSink::createNew(envir(), rtpGroupsock);
00085   } else if (fStreamIdTag == 0xBD /*AC-3 audio*/) {
00086     // Get the sampling frequency from the audio source; use it for the RTP frequency:
00087     AC3AudioStreamFramer* audioSource
00088       = (AC3AudioStreamFramer*)inputSource;
00089     return AC3AudioRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
00090                                       audioSource->samplingRate());
00091   } else {
00092     return NULL;
00093   }
00094 }
00095 
00096 void MPEG1or2DemuxedServerMediaSubsession
00097 ::seekStreamSource(FramedSource* inputSource, double& seekNPT, double /*streamDuration*/, u_int64_t& /*numBytes*/) {
00098   float const dur = duration();
00099   unsigned const size = fOurDemux.fileSize();
00100   unsigned absBytePosition = dur == 0.0 ? 0 : (unsigned)((seekNPT/dur)*size);
00101 
00102   // "inputSource" is a 'framer'
00103   // Flush its data, to account for the seek that we're about to do:
00104   if ((fStreamIdTag&0xF0) == 0xC0 /*MPEG audio*/) {
00105     MPEG1or2AudioStreamFramer* framer = (MPEG1or2AudioStreamFramer*)inputSource;
00106     framer->flushInput();
00107   } else if ((fStreamIdTag&0xF0) == 0xE0 /*video*/) {
00108     MPEG1or2VideoStreamFramer* framer = (MPEG1or2VideoStreamFramer*)inputSource;
00109     framer->flushInput();
00110   }
00111 
00112   // "inputSource" is a filter; its input source is the original elem stream source:
00113   MPEG1or2DemuxedElementaryStream* elemStreamSource
00114     = (MPEG1or2DemuxedElementaryStream*)(((FramedFilter*)inputSource)->inputSource());
00115 
00116   // Next, get the original source demux:
00117   MPEG1or2Demux& sourceDemux = elemStreamSource->sourceDemux();
00118 
00119   // and flush its input buffers:
00120   sourceDemux.flushInput();
00121 
00122   // Then, get the original input file stream from the source demux:
00123   ByteStreamFileSource* inputFileSource
00124     = (ByteStreamFileSource*)(sourceDemux.inputSource());
00125   // Note: We can make that cast, because we know that the demux was originally
00126   // created from a "ByteStreamFileSource".
00127 
00128   // Do the appropriate seek within the input file stream:
00129   inputFileSource->seekToByteAbsolute(absBytePosition);
00130 }
00131 
00132 float MPEG1or2DemuxedServerMediaSubsession::duration() const {
00133   return fOurDemux.fileDuration();
00134 }

Generated on Tue Jun 18 13:16:51 2013 for live by  doxygen 1.5.2