liveMedia/H264VideoStreamDiscreteFramer.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 simplified version of "H264VideoStreamFramer" that takes only complete,
00019 // discrete frames (rather than an arbitrary byte stream) as input.
00020 // This avoids the parsing and data copying overhead of the full
00021 // "H264VideoStreamFramer".
00022 // Implementation
00023 
00024 #include "H264VideoStreamDiscreteFramer.hh"
00025 
00026 H264VideoStreamDiscreteFramer*
00027 H264VideoStreamDiscreteFramer::createNew(UsageEnvironment& env, FramedSource* inputSource) {
00028   // Need to add source type checking here???  #####
00029   return new H264VideoStreamDiscreteFramer(env, inputSource);
00030 }
00031 
00032 H264VideoStreamDiscreteFramer
00033 ::H264VideoStreamDiscreteFramer(UsageEnvironment& env, FramedSource* inputSource)
00034   : H264VideoStreamFramer(env, inputSource, False/*don't create a parser*/, False) {
00035 }
00036 
00037 H264VideoStreamDiscreteFramer::~H264VideoStreamDiscreteFramer() {
00038 }
00039 
00040 void H264VideoStreamDiscreteFramer::doGetNextFrame() {
00041   // Arrange to read data (which should be a complete H.264 NAL unit)
00042   // from our data source, directly into the client's input buffer.
00043   // After reading this, we'll do some parsing on the frame.
00044   fInputSource->getNextFrame(fTo, fMaxSize,
00045                              afterGettingFrame, this,
00046                              FramedSource::handleClosure, this);
00047 }
00048 
00049 void H264VideoStreamDiscreteFramer
00050 ::afterGettingFrame(void* clientData, unsigned frameSize,
00051                     unsigned numTruncatedBytes,
00052                     struct timeval presentationTime,
00053                     unsigned durationInMicroseconds) {
00054   H264VideoStreamDiscreteFramer* source = (H264VideoStreamDiscreteFramer*)clientData;
00055   source->afterGettingFrame1(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds);
00056 }
00057 
00058 void H264VideoStreamDiscreteFramer
00059 ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00060                      struct timeval presentationTime,
00061                      unsigned durationInMicroseconds) {
00062   // Get the "nal_unit_type", to see if this NAL unit is one that we want to save a copy of:
00063   u_int8_t nal_unit_type = frameSize == 0 ? 0xFF : fTo[0]&0x1F;
00064 
00065   // Check for a (likely) common error: NAL units that (erroneously) begin with a 0x00000001 or 0x000001 'start code'
00066   //     (Those start codes should only be in byte-stream data; *not* data that consists of discrete NAL units.)
00067   //     Once again, to be clear: The NAL units that you feed to a "H264VideoStreamDiscreteFramer" MUST NOT include start codes.
00068   if (nal_unit_type == 0) {
00069     if (frameSize >= 4 && fTo[0] == 0 && fTo[1] == 0 && ((fTo[2] == 0 && fTo[3] == 1) || fTo[2] == 1)) {
00070       envir() << "H264VideoStreamDiscreteFramer error: MPEG 'start code' seen in the input\n";
00071     } else {
00072       envir() << "Warning: Invalid 'nal_unit_type': 0\n";
00073     }
00074   } else if (nal_unit_type == 7) { // Sequence parameter set (SPS)
00075     saveCopyOfSPS(fTo, frameSize);
00076   } else if (nal_unit_type == 8) { // Picture parameter set (PPS)
00077     saveCopyOfPPS(fTo, frameSize);
00078   }
00079 
00080   // Next, check whether this NAL unit ends the current 'access unit' (basically, a video frame).  Unfortunately, we can't do this
00081   // reliably, because we don't yet know anything about the *next* NAL unit that we'll see.  So, we guess this as best as we can,
00082   // by assuming that if this NAL unit is a VCL NAL unit, then it ends the current 'access unit'.
00083   Boolean const isVCL = nal_unit_type <= 5 && nal_unit_type > 0; // Would need to include type 20 for SVC and MVC #####
00084   if (isVCL) fPictureEndMarker = True;
00085 
00086   // Finally, complete delivery to the client:
00087   fFrameSize = frameSize;
00088   fNumTruncatedBytes = numTruncatedBytes;
00089   fPresentationTime = presentationTime;
00090   fDurationInMicroseconds = durationInMicroseconds;
00091   afterGetting(this);
00092 }

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