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

📄 mpeg1or2videostreamdiscreteframer.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 "MPEG1or2VideoStreamFramer" 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// "MPEG1or2VideoStreamFramer".// Implementation#include "MPEG1or2VideoStreamDiscreteFramer.hh"MPEG1or2VideoStreamDiscreteFramer*MPEG1or2VideoStreamDiscreteFramer::createNew(UsageEnvironment& env,                                             FramedSource* inputSource,                                             Boolean iFramesOnly,                                             double vshPeriod) {  // Need to add source type checking here???  #####  return new MPEG1or2VideoStreamDiscreteFramer(env, inputSource,                                               iFramesOnly, vshPeriod);}                                                                                MPEG1or2VideoStreamDiscreteFramer::MPEG1or2VideoStreamDiscreteFramer(UsageEnvironment& env,                                    FramedSource* inputSource,                                    Boolean iFramesOnly, double vshPeriod)  : MPEG1or2VideoStreamFramer(env, inputSource, iFramesOnly, vshPeriod,                              False/*don't create a parser*/),    fLastNonBFrameTemporal_reference(0),    fSavedVSHSize(0), fSavedVSHTimestamp(0.0),    fIFramesOnly(iFramesOnly), fVSHPeriod(vshPeriod) {  fLastNonBFramePresentationTime.tv_sec = 0;  fLastNonBFramePresentationTime.tv_usec = 0;}                                                                                MPEG1or2VideoStreamDiscreteFramer::~MPEG1or2VideoStreamDiscreteFramer() {}                                                                                void MPEG1or2VideoStreamDiscreteFramer::doGetNextFrame() {  // Arrange to read data (which should be a complete MPEG-1 or 2 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 MPEG1or2VideoStreamDiscreteFramer::afterGettingFrame(void* clientData, unsigned frameSize,                    unsigned numTruncatedBytes,                    struct timeval presentationTime,                    unsigned durationInMicroseconds) {  MPEG1or2VideoStreamDiscreteFramer* source    = (MPEG1or2VideoStreamDiscreteFramer*)clientData;  source->afterGettingFrame1(frameSize, numTruncatedBytes,                             presentationTime, durationInMicroseconds);}static double const frameRateFromCode[] = {  0.0,          // forbidden  24000/1001.0, // approx 23.976  24.0,  25.0,  30000/1001.0, // approx 29.97  30.0,  50.0,  60000/1001.0, // approx 59.94  60.0,  0.0,          // reserved  0.0,          // reserved  0.0,          // reserved  0.0,          // reserved  0.0,          // reserved  0.0,          // reserved  0.0           // reserved};#define MILLION 1000000void MPEG1or2VideoStreamDiscreteFramer::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    u_int8_t nextCode = fTo[3];    if (nextCode == 0xB3) { // VIDEO_SEQUENCE_HEADER_START_CODE      // Note the following 'frame rate' code:      if (frameSize >= 8) {	u_int8_t frame_rate_code = fTo[7]&0x0F;	fFrameRate = frameRateFromCode[frame_rate_code];      }      // Also, save away this Video Sequence Header, in case we need it later:      // First, figure out how big it is:      unsigned vshSize;      for (vshSize = 4; vshSize < frameSize-3; ++vshSize) {	if (fTo[vshSize] == 0 && fTo[vshSize+1] == 0 && fTo[vshSize+2] == 1 &&	    (fTo[vshSize+3] == 0xB8 || fTo[vshSize+3] == 0x00)) break;      }      if (vshSize == frameSize-3) vshSize = frameSize; // There was nothing else following it      if (vshSize <= sizeof fSavedVSHBuffer) {	memmove(fSavedVSHBuffer, fTo, vshSize);	fSavedVSHSize = vshSize;	fSavedVSHTimestamp	  = presentationTime.tv_sec + presentationTime.tv_usec/(double)MILLION;      }    } else if (nextCode == 0xB8) { // GROUP_START_CODE      // If necessary, insert a saved Video Sequence Header in front of this:      double pts = presentationTime.tv_sec + presentationTime.tv_usec/(double)MILLION;      if (pts > fSavedVSHTimestamp + fVSHPeriod &&	  fSavedVSHSize + frameSize <= fMaxSize) {	memmove(&fTo[fSavedVSHSize], &fTo[0], frameSize); // make room for the header	memmove(&fTo[0], fSavedVSHBuffer, fSavedVSHSize); // insert it	frameSize += fSavedVSHSize;	fSavedVSHTimestamp = pts;      }    }    unsigned i = 3;    if (nextCode == 0xB3 /*VIDEO_SEQUENCE_HEADER_START_CODE*/ ||	nextCode == 0xB8 /*GROUP_START_CODE*/) {      // Skip to the following PICTURE_START_CODE (if any):      for (i += 4; i < frameSize; ++i) {	if (fTo[i] == 0x00 /*PICTURE_START_CODE*/	    && fTo[i-1] == 1 && fTo[i-2] == 0 && fTo[i-3] == 0) {	  nextCode = fTo[i];	  break;	}      }    }    if (nextCode == 0x00 /*PICTURE_START_CODE*/ && i+2 < frameSize) {       // Get the 'temporal_reference' and 'picture_coding_type' from the      // following 2 bytes:      ++i;      unsigned short temporal_reference = (fTo[i]<<2)|(fTo[i+1]>>6);      unsigned char picture_coding_type = (fTo[i+1]&0x38)>>3;      // If this is not an "I" frame, but we were asked for "I" frames only, then try again:      if (fIFramesOnly && picture_coding_type != 1) {	doGetNextFrame();	return;      }      // If this is a "B" frame, then we have to tweak "presentationTime":      if (picture_coding_type == 3/*B*/	  && (fLastNonBFramePresentationTime.tv_usec > 0 ||	      fLastNonBFramePresentationTime.tv_sec > 0)) {	int trIncrement            = fLastNonBFrameTemporal_reference - temporal_reference;	if (trIncrement < 0) trIncrement += 1024; // field is 10 bits in size	unsigned usIncrement = fFrameRate == 0.0 ? 0	  : (unsigned)((trIncrement*MILLION)/fFrameRate);	unsigned secondsToSubtract = usIncrement/MILLION;	unsigned uSecondsToSubtract = 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;	fLastNonBFrameTemporal_reference = temporal_reference;      }    }  }  // ##### Later:  // - do "iFramesOnly" if requested   // Complete delivery to the client:  fFrameSize = frameSize;  fNumTruncatedBytes = numTruncatedBytes;  fPresentationTime = presentationTime;  fDurationInMicroseconds = durationInMicroseconds;  afterGetting(this);}

⌨️ 快捷键说明

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