⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg4videostreamdiscreteframer.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA  02111-1307  USA**********/// "liveMedia"// Copyright (c) 1996-2004 Live Networks, Inc.  All rights reserved.// A simplified version of "MPEG4VideoStreamFramer" that takes only complete,// discrete frames (rather than an arbitrary byte stream) as input.// This avoids the parsing and data copying overhead of the full// "MPEG4VideoStreamFramer".// Implementation#include "MPEG4VideoStreamDiscreteFramer.hh"MPEG4VideoStreamDiscreteFramer*MPEG4VideoStreamDiscreteFramer::createNew(UsageEnvironment& env,				  FramedSource* inputSource) {  // Need to add source type checking here???  #####  return new MPEG4VideoStreamDiscreteFramer(env, inputSource);}MPEG4VideoStreamDiscreteFramer::MPEG4VideoStreamDiscreteFramer(UsageEnvironment& env,				 FramedSource* inputSource)  : MPEG4VideoStreamFramer(env, inputSource, False/*don't create a parser*/),    vop_time_increment_resolution(0), fNumVTIRBits(0),    fLastNonBFrameVop_time_increment(0) {  fLastNonBFramePresentationTime.tv_sec = 0;  fLastNonBFramePresentationTime.tv_usec = 0;}MPEG4VideoStreamDiscreteFramer::~MPEG4VideoStreamDiscreteFramer() {}void MPEG4VideoStreamDiscreteFramer::doGetNextFrame() {  // Arrange to read data (which should be a complete MPEG-4 video frame)  // from our data source, directly into the client's input buffer.  // After reading this, we'll do some parsing on the frame.  fInputSource->getNextFrame(fTo, fMaxSize,                             afterGettingFrame, this,                             FramedSource::handleClosure, this);}void MPEG4VideoStreamDiscreteFramer::afterGettingFrame(void* clientData, unsigned frameSize,                    unsigned numTruncatedBytes,                    struct timeval presentationTime,                    unsigned durationInMicroseconds) {  MPEG4VideoStreamDiscreteFramer* source = (MPEG4VideoStreamDiscreteFramer*)clientData;  source->afterGettingFrame1(frameSize, numTruncatedBytes,                             presentationTime, durationInMicroseconds);}void MPEG4VideoStreamDiscreteFramer::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,                     struct timeval presentationTime,                     unsigned durationInMicroseconds) {  // Check that the first 4 bytes are a system code:  if (frameSize >= 4 && fTo[0] == 0 && fTo[1] == 0 && fTo[2] == 1) {    fPictureEndMarker = True; // Assume that we have a complete 'picture' here    unsigned i = 3;    if (fTo[i] == 0xB0) { // VISUAL_OBJECT_SEQUENCE_START_CODE      // The next byte is the "profile_and_level_indication":      if (frameSize >= 5) fProfileAndLevelIndication = fTo[4];      // The start of this frame - up to the first GROUP_VOP_START_CODE      // or VOP_START_CODE - is stream configuration information.  Save this:      for (i = 7; i < frameSize; ++i) {	if ((fTo[i] == 0xB3 /*GROUP_VOP_START_CODE*/ ||	     fTo[i] == 0xB6 /*VOP_START_CODE*/)	    && fTo[i-1] == 1 && fTo[i-2] == 0 && fTo[i-3] == 0) {	  break; // The configuration information ends here	}      }      fNumConfigBytes = i-3;      delete[] fConfigBytes; fConfigBytes = new unsigned char[fNumConfigBytes];      for (unsigned j = 0; j < fNumConfigBytes; ++j) fConfigBytes[j] = fTo[j];      // This information (should) also contain a VOL header, which we need      // to analyze, to get "vop_time_increment_resolution" (which we need      // - along with "vop_time_increment" - in order to generate accurate      // presentation times for "B" frames).      analyzeVOLHeader();    }    if (i < frameSize) {      u_int8_t nextCode = fTo[i];      if (nextCode == 0xB3 /*GROUP_VOP_START_CODE*/) {	// Skip to the following VOP_START_CODE (if any):	for (i += 4; i < frameSize; ++i) {	  if (fTo[i] == 0xB6 /*VOP_START_CODE*/	      && fTo[i-1] == 1 && fTo[i-2] == 0 && fTo[i-3] == 0) {	    nextCode = fTo[i];	    break;	  }	}      }      if (nextCode == 0xB6 /*VOP_START_CODE*/ && i+5 < frameSize) {	++i;	// Get the "vop_coding_type" from the next byte:	u_int8_t nextByte = fTo[i++];	u_int8_t vop_coding_type = nextByte>>6;	// Next, get the "modulo_time_base" by counting the '1' bits that	// follow.  We look at the next 32-bits only.	// This should be enough in most cases.	u_int32_t next4Bytes	  = (fTo[i]<<24)|(fTo[i+1]<<16)|(fTo[i+2]<<8)|fTo[i+3];	i += 4;	u_int32_t timeInfo = (nextByte<<(32-6))|(next4Bytes>>6);	unsigned modulo_time_base = 0;	u_int32_t mask = 0x80000000;	while ((timeInfo&mask) != 0) {	  ++modulo_time_base;	  mask >>= 1;	}	mask >>= 2;	// Then, get the "vop_time_increment".	unsigned vop_time_increment = 0;	// First, make sure we have enough bits left for this:	if ((mask>>(fNumVTIRBits-1)) != 0) {	  for (unsigned i = 0; i < fNumVTIRBits; ++i) {	    vop_time_increment |= timeInfo&mask;	    mask >>= 1;	  }	  while (mask != 0) {	    vop_time_increment >>= 1;	    mask >>= 1;	  }	}		// If this is a "B" frame, then we have to tweak "presentationTime":	if (vop_coding_type == 2/*B*/	    && (fLastNonBFramePresentationTime.tv_usec > 0 ||		fLastNonBFramePresentationTime.tv_sec > 0)) {	  int timeIncrement	    = fLastNonBFrameVop_time_increment - vop_time_increment;	  if (timeIncrement<0) timeIncrement += vop_time_increment_resolution;	  unsigned const MILLION = 1000000;	  double usIncrement = vop_time_increment_resolution == 0 ? 0.0	    : ((double)timeIncrement*MILLION)/vop_time_increment_resolution;	  unsigned secondsToSubtract = (unsigned)(usIncrement/MILLION);	  unsigned uSecondsToSubtract = ((unsigned)usIncrement)%MILLION;	  presentationTime = fLastNonBFramePresentationTime;	  if ((unsigned)presentationTime.tv_usec < uSecondsToSubtract) {	    presentationTime.tv_usec += MILLION;	    if (presentationTime.tv_sec > 0) --presentationTime.tv_sec;	  }	  presentationTime.tv_usec -= uSecondsToSubtract;	  if ((unsigned)presentationTime.tv_sec > secondsToSubtract) {	    presentationTime.tv_sec -= secondsToSubtract;	  } else {	    presentationTime.tv_sec = presentationTime.tv_usec = 0;	  }	} else {	  fLastNonBFramePresentationTime = presentationTime;	  fLastNonBFrameVop_time_increment = vop_time_increment;	}      }    }  }  // Complete delivery to the client:  fFrameSize = frameSize;  fNumTruncatedBytes = numTruncatedBytes;  fPresentationTime = presentationTime;  fDurationInMicroseconds = durationInMicroseconds;  afterGetting(this);}Boolean MPEG4VideoStreamDiscreteFramer::getNextFrameBit(u_int8_t& result) {  if (fNumBitsSeenSoFar/8 >= fNumConfigBytes) return False;  u_int8_t nextByte = fConfigBytes[fNumBitsSeenSoFar/8];  result = (nextByte>>(7-fNumBitsSeenSoFar%8))&1;  ++fNumBitsSeenSoFar;  return True;}Boolean MPEG4VideoStreamDiscreteFramer::getNextFrameBits(unsigned numBits,							 u_int32_t& result) {  result = 0;  for (unsigned i = 0; i < numBits; ++i) {    u_int8_t nextBit;    if (!getNextFrameBit(nextBit)) return False;    result = (result<<1)|nextBit;  }  return True;}void MPEG4VideoStreamDiscreteFramer::analyzeVOLHeader() {  // Begin by moving to the VOL header:  unsigned i;  for (i = 3; i < fNumConfigBytes; ++i) {    if (fConfigBytes[i] >= 0x20 && fConfigBytes[i] <= 0x2F	&& fConfigBytes[i-1] == 1	&& fConfigBytes[i-2] == 0 && fConfigBytes[i-3] == 0) {      ++i;      break;    }  }  fNumBitsSeenSoFar = 8*i + 9;  do {    u_int8_t is_object_layer_identifier;    if (!getNextFrameBit(is_object_layer_identifier)) break;    if (is_object_layer_identifier) fNumBitsSeenSoFar += 7;    u_int32_t aspect_ratio_info;    if (!getNextFrameBits(4, aspect_ratio_info)) break;    if (aspect_ratio_info == 15 /*extended_PAR*/) fNumBitsSeenSoFar += 16;    u_int8_t vol_control_parameters;    if (!getNextFrameBit(vol_control_parameters)) break;    if (vol_control_parameters) {      fNumBitsSeenSoFar += 3; // chroma_format; low_delay      u_int8_t vbw_parameters;      if (!getNextFrameBit(vbw_parameters)) break;      if (vbw_parameters) fNumBitsSeenSoFar += 79;    }    fNumBitsSeenSoFar += 2; // video_object_layer_shape    u_int8_t marker_bit;    if (!getNextFrameBit(marker_bit)) break;    if (marker_bit != 1) break; // sanity check    if (!getNextFrameBits(16, vop_time_increment_resolution)) break;    if (vop_time_increment_resolution == 0) break; // shouldn't happen    // Compute how many bits are necessary to represent this:    fNumVTIRBits = 0;    for (unsigned test = vop_time_increment_resolution; test>0; test /= 2) {      ++fNumVTIRBits;    }  } while (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -