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

📄 mpeg4.cpp

📁 完整的RTP RTSP代码库
💻 CPP
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000-2004.  All Rights Reserved. *  * Contributor(s):  *		Dave Mackie		dmackie@cisco.com *//*  * Notes: *  - file formatted with tabstops == 4 spaces  */#include <mp4av_common.h>extern "C" int32_t MP4AV_Mpeg4FindHeader (const uint8_t *pStart, 					  uint32_t buflen,					  bool do_header_type, 					  uint8_t header_type){  const uint8_t *pBuf = pStart;  while (buflen > 4) {    if (pBuf[0] == 0x0 &&	pBuf[1] == 0x0 &&	pBuf[2] == 0x1 &&	(do_header_type == false || pBuf[3] == header_type)) {      return pBuf - pStart;    }    pBuf++;    buflen--;  }  return -1;}extern "C" uint8_t *MP4AV_Mpeg4FindVosh (uint8_t *pBuf, uint32_t buflen){  int32_t ret =     MP4AV_Mpeg4FindHeader(pBuf, buflen, true, MP4AV_MPEG4_VOSH_START);  if (ret < 0) return NULL;    return pBuf + ret;}extern "C" bool MP4AV_Mpeg4ParseVosh(				     u_int8_t* pVoshBuf, 				     u_int32_t voshSize,				     u_int8_t* pProfileLevel){	CMemoryBitstream vosh;	uint32_t read;	vosh.SetBytes(pVoshBuf, voshSize);	try {	  read = vosh.GetBits(32);				// start code		*pProfileLevel = vosh.GetBits(8);	}	catch (int e) {		return false;	}	return true;}extern "C" bool MP4AV_Mpeg4CreateVosh(	u_int8_t** ppBytes,	u_int32_t* pNumBytes,	u_int8_t profileLevel){	CMemoryBitstream vosh;	try {		if (*ppBytes) {			// caller must guarantee buffer against overrun			memset((*ppBytes) + (*pNumBytes), 0, 5);			vosh.SetBytes(*ppBytes, (*pNumBytes) + 5);			vosh.SetBitPosition((*pNumBytes) << 3);		} else {			vosh.AllocBytes(5);		}		vosh.PutBits(MP4AV_MPEG4_SYNC, 24);		vosh.PutBits(MP4AV_MPEG4_VOSH_START, 8);		vosh.PutBits(profileLevel, 8);		*ppBytes = vosh.GetBuffer();		*pNumBytes = vosh.GetNumberOfBytes();	}	catch (int e) {		return false;	}	return true;}extern "C" bool MP4AV_Mpeg4CreateVo(	u_int8_t** ppBytes,	u_int32_t* pNumBytes,	u_int8_t objectId){	CMemoryBitstream vo;	try {		if (*ppBytes) {			// caller must guarantee buffer against overrun			memset((*ppBytes) + (*pNumBytes), 0, 9);			vo.SetBytes(*ppBytes, *pNumBytes + 9);			vo.SetBitPosition((*pNumBytes) << 3);		} else {			vo.AllocBytes(9);		}		vo.PutBits(MP4AV_MPEG4_SYNC, 24);		vo.PutBits(MP4AV_MPEG4_VO_START, 8);		vo.PutBits(0x08, 8);	// no verid, priority, or signal type		vo.PutBits(MP4AV_MPEG4_SYNC, 24);		vo.PutBits(objectId - 1, 8);		*ppBytes = vo.GetBuffer();		*pNumBytes = vo.GetNumberOfBytes();	}	catch (int e) {		return false;	}	return true;}extern "C" uint8_t *MP4AV_Mpeg4FindVol (uint8_t *pBuf, uint32_t buflen){  int32_t ret =     MP4AV_Mpeg4FindHeader(pBuf, buflen, true, MP4AV_MPEG4_VOL_START);  if (ret < 0) return NULL;    return pBuf + ret;}extern "C" uint8_t *MP4AV_Mpeg4FindVop (uint8_t *pBuf, uint32_t buflen){  int32_t ret =     MP4AV_Mpeg4FindHeader(pBuf, buflen, true, MP4AV_MPEG4_VOP_START);  if (ret < 0) return NULL;    return pBuf + ret;}extern "C" bool MP4AV_Mpeg4ParseVol(	u_int8_t* pVolBuf, 	u_int32_t volSize,	u_int8_t* pTimeBits, 	u_int16_t* pTimeTicks, 	u_int16_t* pFrameDuration, 	u_int16_t* pFrameWidth, 	u_int16_t* pFrameHeight,	u_int8_t * aspectRatioDefine,	u_int8_t * aspectRatioWidth,	u_int8_t * aspectRatioHeight){	CMemoryBitstream vol;	uint8_t aspect;	vol.SetBytes(pVolBuf, volSize);	try {		vol.SkipBits(32);				// start code		vol.SkipBits(1);				// random accessible vol		vol.SkipBits(8);				// object type id		u_int8_t verid = 1;		if (vol.GetBits(1)) {			// is object layer id			verid = vol.GetBits(4);			// object layer verid			vol.SkipBits(3);				// object layer priority		}		aspect = vol.GetBits(4);		if (aspectRatioDefine != NULL)		  *aspectRatioDefine = aspect;		if (aspect == 0xF) { 	// aspect ratio info		  if (aspectRatioWidth != NULL) 		    *aspectRatioWidth = vol.GetBits(8);		  else		    vol.SkipBits(8);				// par width		  if (aspectRatioHeight != NULL) 		    *aspectRatioHeight = vol.GetBits(8);		  else		    vol.SkipBits(8);				// par height		}		if (vol.GetBits(1)) {			// vol control parameters			vol.SkipBits(2);				// chroma format			vol.SkipBits(1);				// low delay			if (vol.GetBits(1)) {			// vbv parameters				vol.SkipBits(15);				// first half bit rate				vol.SkipBits(1);				// marker bit				vol.SkipBits(15);				// latter half bit rate				vol.SkipBits(1);				// marker bit				vol.SkipBits(15);				// first half vbv buffer size				vol.SkipBits(1);				// marker bit				vol.SkipBits(3);				// latter half vbv buffer size				vol.SkipBits(11);				// first half vbv occupancy				vol.SkipBits(1);				// marker bit				vol.SkipBits(15);				// latter half vbv occupancy				vol.SkipBits(1);				// marker bit			}		}		u_int8_t shape = vol.GetBits(2); // object layer shape		if (shape == 3 /* GRAYSCALE */ && verid != 1) {			vol.SkipBits(4);				// object layer shape extension		}		vol.SkipBits(1);				// marker bit		*pTimeTicks = vol.GetBits(16);		// vop time increment resolution 		u_int8_t i;		u_int32_t powerOf2 = 1;		for (i = 0; i < 16; i++) {			if (*pTimeTicks < powerOf2) {				break;			}			powerOf2 <<= 1;		}		*pTimeBits = i;		vol.SkipBits(1);				// marker bit		if (vol.GetBits(1)) {			// fixed vop rate			// fixed vop time increment			*pFrameDuration = vol.GetBits(*pTimeBits); 		} else {			*pFrameDuration = 0;		}		if (shape == 0 /* RECTANGULAR */) {			vol.SkipBits(1);				// marker bit			*pFrameWidth = vol.GetBits(13);	// object layer width			vol.SkipBits(1);				// marker bit			*pFrameHeight = vol.GetBits(13);// object layer height			vol.SkipBits(1);				// marker bit		} else {			*pFrameWidth = 0;			*pFrameHeight = 0;		}		// there's more, but we don't need it	}	catch (int e) {		return false;	}	return true;}extern "C" bool MP4AV_Mpeg4CreateVol(	u_int8_t** ppBytes,	u_int32_t* pNumBytes,	u_int8_t profile,	double frameRate,	bool shortTime,	bool variableRate,	u_int16_t width,	u_int16_t height,	u_int8_t quantType,	u_int8_t* pTimeBits){	CMemoryBitstream vol;	try {		if (*ppBytes) {			// caller must guarantee buffer against overrun			memset((*ppBytes) + (*pNumBytes), 0, 20);			vol.SetBytes(*ppBytes, *pNumBytes + 20);			vol.SetBitPosition((*pNumBytes) << 3);		} else {			vol.AllocBytes(20);		}		/* VOL - Video Object Layer */		vol.PutBits(MP4AV_MPEG4_SYNC, 24);		vol.PutBits(MP4AV_MPEG4_VOL_START, 8);		/* 1 bit - random access = 0 (1 only if every VOP is an I frame) */		vol.PutBits(0, 1);		/*		 * 8 bits - type indication 		 * 		= 1 (simple profile)		 * 		= 4 (main profile)		 */		vol.PutBits(profile, 8);		/* 1 bit - is object layer id = 1 */		vol.PutBits(1, 1);		/* 4 bits - visual object layer ver id = 1 */		vol.PutBits(1, 4); 		/* 3 bits - visual object layer priority = 1 */		vol.PutBits(1, 3); 		/* 4 bits - aspect ratio info = 1 (square pixels) */		vol.PutBits(1, 4);		/* 1 bit - VOL control params = 0 */		vol.PutBits(0, 1);		/* 2 bits - VOL shape = 0 (rectangular) */		vol.PutBits(0, 2);		/* 1 bit - marker = 1 */		vol.PutBits(1, 1);		u_int16_t ticks;		if (shortTime /* && frameRate == (float)((int)frameRate) */) {			ticks = (u_int16_t)(frameRate + 0.5);		} else {			ticks = 30000;		}		/* 16 bits - VOP time increment resolution */		vol.PutBits(ticks, 16);		/* 1 bit - marker = 1 */		vol.PutBits(1, 1);		u_int8_t rangeBits = 1;		while (ticks > (1 << rangeBits)) {			rangeBits++;		}		if (pTimeBits) {			*pTimeBits = rangeBits;		}		/* 1 bit - fixed vop rate = 0 or 1 */		if (variableRate) {			vol.PutBits(0, 1);		} else {			vol.PutBits(1, 1);			u_int16_t frameDuration = 				(u_int16_t)((double)ticks / frameRate);			/* 1-16 bits - fixed vop time increment in ticks */			vol.PutBits(frameDuration, rangeBits);		}		/* 1 bit - marker = 1 */		vol.PutBits(1, 1);		/* 13 bits - VOL width */		vol.PutBits(width, 13);		/* 1 bit - marker = 1 */		vol.PutBits(1, 1);		/* 13 bits - VOL height */		vol.PutBits(height, 13);		/* 1 bit - marker = 1 */		vol.PutBits(1, 1);		/* 1 bit - interlaced = 0 */		vol.PutBits(0, 1);		/* 1 bit - overlapped block motion compensation disable = 1 */		vol.PutBits(1, 1);#if 0		/* 2 bits - sprite usage = 0 */		vol.PutBits(0, 2);#else		vol.PutBits(0, 1);#endif		/* 1 bit - not 8 bit pixels = 0 */		vol.PutBits(0, 1);		/* 1 bit - quant type = 0 */		vol.PutBits(quantType, 1);		if (quantType) {			/* 1 bit - load intra quant mat = 0 */			vol.PutBits(0, 1);			/* 1 bit - load inter quant mat = 0 */			vol.PutBits(0, 1);		}#if 0		/* 1 bit - quarter pixel = 0 */		vol.PutBits(0, 1);#endif		/* 1 bit - complexity estimation disable = 1 */		vol.PutBits(1, 1);		/* 1 bit - resync marker disable = 1 */		vol.PutBits(1, 1);		/* 1 bit - data partitioned = 0 */		vol.PutBits(0, 1);#if 0		/* 1 bit - newpred = 0 */		vol.PutBits(0, 1);		/* 1 bit - reduced resolution vop = 0 */		vol.PutBits(0, 1);#endif		/* 1 bit - scalability = 0 */		vol.PutBits(0, 1);		/* pad to byte boundary with 0 then as many 1's as needed */		vol.PutBits(0, 1);		if ((vol.GetBitPosition() & 7) != 0) {			vol.PutBits(0xFF, 8 - (vol.GetBitPosition() & 7));		}		*ppBytes = vol.GetBuffer();		*pNumBytes = vol.GetBitPosition() >> 3;	}	catch (int e) {		return false;	}	return true;}extern "C" bool MP4AV_Mpeg4ParseGov(	u_int8_t* pGovBuf, 	u_int32_t govSize,	u_int8_t* pHours, 	u_int8_t* pMinutes, 	u_int8_t* pSeconds){	CMemoryBitstream gov;	gov.SetBytes(pGovBuf, govSize);	try {		gov.SkipBits(32);	// start code		*pHours = gov.GetBits(5);		*pMinutes = gov.GetBits(6);		gov.SkipBits(1);		// marker bit		*pSeconds = gov.GetBits(6);	}	catch (int e) {		return false;	}	return true;}static bool Mpeg4ParseShortHeaderVop(	u_int8_t* pVopBuf, 	u_int32_t vopSize,	int* pVopType){	CMemoryBitstream vop;	vop.SetBytes(pVopBuf, vopSize);	try {		// skip start code, temporal ref, and into type		vop.SkipBits(22 + 8 + 5 + 3);			if (vop.GetBits(1) == 0) {			*pVopType = VOP_TYPE_I;		} else {			*pVopType = VOP_TYPE_P;		}	}	catch (int e) {		return false;	}	return true;}extern "C" bool MP4AV_Mpeg4ParseVop(	u_int8_t* pVopBuf, 	u_int32_t vopSize,	int* pVopType, 	u_int8_t timeBits, 	u_int16_t timeTicks, 	u_int32_t* pVopTimeIncrement){	CMemoryBitstream vop;	vop.SetBytes(pVopBuf, vopSize);	try {		vop.SkipBits(32);	// skip start code		switch (vop.GetBits(2)) {		case 0:			/* Intra */			*pVopType = VOP_TYPE_I;			break;		case 1:			/* Predictive */			*pVopType = VOP_TYPE_P;			break;		case 2:			/* Bidirectional Predictive */			*pVopType = VOP_TYPE_B;			break;		case 3:			/* Sprite */			*pVopType = VOP_TYPE_S;			break;		}		if (!pVopTimeIncrement) {			return true;		}		u_int8_t numSecs = 0;		while (vop.GetBits(1) != 0) {			numSecs++;		}		vop.SkipBits(1);		// skip marker		u_int16_t numTicks = vop.GetBits(timeBits);		*pVopTimeIncrement = (numSecs * timeTicks) + numTicks; 	}	catch (int e) {		return false;	}	return true;}extern "C" int MP4AV_Mpeg4GetVopType(u_int8_t* pVopBuf, u_int32_t vopSize){	int vopType = 0;	if (vopSize <= 4) {		return vopType;	}	if (pVopBuf[0] == 0 && pVopBuf[1] == 0 	  && (pVopBuf[2] & 0xFC) == 0x08 && (pVopBuf[3] & 0x03) == 0x02) {		// H.263, (MPEG-4 short header mode)	  if (Mpeg4ParseShortHeaderVop(pVopBuf, vopSize, &vopType) == false)	    return 0;			} else {		// MPEG-4 (normal mode)	  if (MP4AV_Mpeg4ParseVop(pVopBuf, vopSize, &vopType, 0, 0, NULL)	      == false) return 0;	}	return vopType;}// MP4AV_calculate_dts_from_pts// a crude method of determining the decode timestamp from the // presentation timestamp.// the player needs the decode timestamp - it uses that coupled with// if the decoder returns a decoded frame for timingextern "C" int MP4AV_calculate_dts_from_pts (mp4av_pts_to_dts_t *ptr,					     uint64_t pts,					     int type,					     uint64_t *dts){  if (type == VOP_TYPE_B) {    // If we have a B type, the dts is always the pts.    ptr->last_type = type;    ptr->last_dts = *dts = pts;    return 0;  }   // We have a I or P type.  if (ptr->have_last_pts && ptr->last_pts >= ptr->last_dts) {    // if we have a PTS stored, and the PTS is greater than the last    // dts we stored (from a b frame, most likely), we will return    // that pts as the dts.    // we also need to record this frames pts    ptr->have_last_pts = 1;    *dts = ptr->last_dts = ptr->last_pts;    ptr->last_pts = pts;    ptr->last_type = type;    return 0;  }   // we don't have a pts stored, or we have a situation where the last  // stored pts is less that dts we've gotten from B frames - this is  // when lost I or P frames occur  ptr->have_last_pts = 1;  ptr->last_pts = pts;  if (ptr->last_type == 0) {    // we can't do anything with the timing here - we just store,    // and return an error    ptr->last_dts = pts;    ptr->last_type = type;    return -1;  }  // we have a last type, so we'll use the dts from that frame, add  // a small amount, then hit it up the next time - we'll have a pts  // stored.  ptr->last_dts = *dts = ptr->last_dts + (uint64_t)(1000.0 / 29.97);  ptr->last_type = type;  return 0;}extern "C" void MP4AV_clear_dts_from_pts (mp4av_pts_to_dts_t *ptr){  ptr->last_type = 0;  ptr->have_last_pts = 0;}

⌨️ 快捷键说明

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