liveMedia/H264VideoMatroskaFileServerMediaSubsession.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-2012 Live Networks, Inc.  All rights reserved.
00018 // A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
00019 // on demand, from an H264 video track within a Matroska file.
00020 // Implementation
00021 
00022 #include "H264VideoMatroskaFileServerMediaSubsession.hh"
00023 #include "H264VideoStreamDiscreteFramer.hh"
00024 #include "MatroskaDemuxedTrack.hh"
00025 
00026 H264VideoMatroskaFileServerMediaSubsession* H264VideoMatroskaFileServerMediaSubsession
00027 ::createNew(MatroskaFileServerDemux& demux, unsigned trackNumber) {
00028   return new H264VideoMatroskaFileServerMediaSubsession(demux, trackNumber);
00029 }
00030 
00031 #define checkPtr if (ptr >= limit) return;
00032 #define numBytesRemaining (unsigned)(limit - ptr)
00033 
00034 H264VideoMatroskaFileServerMediaSubsession
00035 ::H264VideoMatroskaFileServerMediaSubsession(MatroskaFileServerDemux& demux, unsigned trackNumber)
00036   : H264VideoFileServerMediaSubsession(demux.envir(), demux.fileName(), False),
00037     fOurDemux(demux), fTrackNumber(trackNumber),
00038     fSPSSize(0), fSPS(NULL), fPPSSize(0), fPPS(NULL) {
00039   // Use our track's 'Codec Private' data: Byte 4 contains the size of NAL unit lengths,
00040   // and bytes 5 and beyond contain SPS and PPSs:
00041   MatroskaTrack* track = fOurDemux.lookup(fTrackNumber);
00042   if (track->codecPrivateSize >= 5) track->subframeSizeSize = (track->codecPrivate[4])&0x3 + 1;
00043 
00044   unsigned numSPSandPPSBytes;
00045   u_int8_t* SPSandPPSBytes;
00046   if (track->codecPrivateSize >= 6) {
00047     numSPSandPPSBytes = track->codecPrivateSize - 5;
00048     track->codecPrivate[5] &=~ 0xE0; // mask out the top 3 (reserved) bits from the 'numSPSs' byte
00049     SPSandPPSBytes = &track->codecPrivate[5];
00050   } else {
00051     numSPSandPPSBytes = 0;
00052     SPSandPPSBytes = NULL;
00053   }
00054 
00055   // Extract, from "SPSandPPSBytes", one SPS NAL unit, and one PPS NAL unit.  (I hope one is all we need of each.)
00056   do {
00057     if (numSPSandPPSBytes == 0 || SPSandPPSBytes == NULL) break; // sanity check
00058     u_int8_t* ptr = SPSandPPSBytes;
00059     u_int8_t* limit = &SPSandPPSBytes[numSPSandPPSBytes];
00060 
00061     unsigned numSPSs = *ptr++; checkPtr;
00062     unsigned i;
00063     for (i = 0; i < numSPSs; ++i) {
00064       unsigned spsSize = (*ptr++)<<8; checkPtr;
00065       spsSize |= *ptr++; checkPtr;
00066 
00067       if (spsSize > numBytesRemaining) return;
00068       if (i == 0) { // save the first one
00069         fSPSSize = spsSize;
00070         fSPS = new u_int8_t[spsSize];
00071         memmove(fSPS, ptr, spsSize);
00072       }
00073       ptr += spsSize;
00074     }
00075 
00076     unsigned numPPSs = *ptr++; checkPtr;
00077     for (i = 0; i < numPPSs; ++i) {
00078       unsigned ppsSize = (*ptr++)<<8; checkPtr;
00079       ppsSize |= *ptr++; checkPtr;
00080 
00081       if (ppsSize > numBytesRemaining) return;
00082       if (i == 0) { // save the first one
00083         fPPSSize = ppsSize;
00084         fPPS = new u_int8_t[ppsSize];
00085         memmove(fPPS, ptr, ppsSize);
00086       }
00087       ptr += ppsSize;
00088     }
00089   } while (0);
00090 }
00091 
00092 H264VideoMatroskaFileServerMediaSubsession
00093 ::~H264VideoMatroskaFileServerMediaSubsession() {
00094   delete[] fSPS;
00095   delete[] fPPS;
00096 }
00097 
00098 float H264VideoMatroskaFileServerMediaSubsession::duration() const { return fOurDemux.fileDuration(); }
00099 
00100 void H264VideoMatroskaFileServerMediaSubsession
00101 ::seekStreamSource(FramedSource* inputSource, double& seekNPT, double /*streamDuration*/, u_int64_t& /*numBytes*/) {
00102   // "inputSource" is a framer. *Its* source is the demuxed track that we seek on:
00103   H264VideoStreamFramer* framer = (H264VideoStreamFramer*)inputSource;
00104 
00105   MatroskaDemuxedTrack* demuxedTrack = (MatroskaDemuxedTrack*)(framer->inputSource());
00106   demuxedTrack->seekToTime(seekNPT);
00107 }
00108 
00109 FramedSource* H264VideoMatroskaFileServerMediaSubsession
00110 ::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) {
00111   // Allow for the possibility of very large NAL units being fed to our "RTPSink" objects:
00112   OutPacketBuffer::maxSize = 300000; // bytes
00113   estBitrate = 500; // kbps, estimate
00114 
00115   // Create the video source:
00116   FramedSource* baseH264VideoSource = fOurDemux.newDemuxedTrack(clientSessionId, fTrackNumber);
00117   if (baseH264VideoSource == NULL) return NULL;
00118   
00119   // Create a framer for the Video stream:
00120   H264VideoStreamFramer* framer = H264VideoStreamDiscreteFramer::createNew(envir(), baseH264VideoSource);
00121   framer->setSPSandPPS(fSPS, fSPSSize, fPPS, fPPSSize);
00122 
00123   return framer;
00124 }

Generated on Thu May 10 20:25:11 2012 for live by  doxygen 1.5.2