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

📄 video_xvid10.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. 2004.  All Rights Reserved. *  * Contributor(s):  *		Bill May wmay@cisco.com *              Peter Maersk-Moller peter@maersk-moller.net (interlace) */#include "mp4live.h"#include <mp4av.h>#include "video_encoder.h"#include "video_xvid10.h"static config_index_t CFG_XVID10_VIDEO_QUALITY;static config_index_t CFG_XVID10_USE_GMC;static config_index_t CFG_XVID10_USE_QPEL;static config_index_t CFG_XVID10_USE_LUMIMASK;static config_index_t CFG_XVID10_USE_INTERLACING;static SConfigVariable XvidEncoderVariables[] = {  CONFIG_INT(CFG_XVID10_VIDEO_QUALITY, "xvid10VideoQuality", 6),  CONFIG_BOOL(CFG_XVID10_USE_GMC, "xvid10UseGmc", false),  CONFIG_BOOL(CFG_XVID10_USE_QPEL, "xvid10UseQpel", false),  CONFIG_BOOL(CFG_XVID10_USE_LUMIMASK, "xvid10UseLumimask", false),  CONFIG_BOOL(CFG_XVID10_USE_INTERLACING, "xvid10UseInterlacing", false),};GUI_BOOL(gui_gmc, CFG_XVID10_USE_GMC, "Use GMC");GUI_BOOL(gui_qpel, CFG_XVID10_USE_QPEL, "Use QPel");GUI_BOOL(gui_lumimask, CFG_XVID10_USE_LUMIMASK, "Use Lumimask");GUI_BOOL(gui_interlace, CFG_XVID10_USE_INTERLACING, "Use Interlacing");GUI_INT_RANGE(gui_vq, CFG_XVID10_VIDEO_QUALITY, "Video Quality", 0, 6);DECLARE_TABLE(xvid_gui_options) = {  TABLE_GUI(gui_gmc),  TABLE_GUI(gui_qpel),  TABLE_GUI(gui_lumimask),  TABLE_GUI(gui_interlace),  TABLE_GUI(gui_vq),};DECLARE_TABLE_FUNC(xvid_gui_options);void AddXvid10ConfigVariables(CVideoProfile *pConfig) {  pConfig->AddConfigVariables(XvidEncoderVariables,			      NUM_ELEMENTS_IN_ARRAY(XvidEncoderVariables));}CXvid10VideoEncoder::CXvid10VideoEncoder(CVideoProfile *vp, 					 uint16_t mtu,					 CVideoEncoder *next, 					 bool realTime) :  CVideoEncoder(vp, mtu, next, realTime){	m_xvidHandle = NULL;	m_vopBuffer = NULL;	m_vopBufferLength = 0;#ifdef WRITE_RAW	m_outfile = fopen("raw.m4v", FOPEN_WRITE_BINARY);#endif	m_video_quality = 6;	m_use_gmc = false;	m_use_qpel = true;	m_use_lumimask_plugin = false;}bool CXvid10VideoEncoder::Init(void){	xvid_gbl_init_t xvid_gbl_init;	m_video_quality = Profile()->GetIntegerValue(CFG_XVID10_VIDEO_QUALITY);	if (m_video_quality > 6) m_video_quality = 6;	m_use_gmc = Profile()->GetBoolValue(CFG_XVID10_USE_GMC);	m_use_qpel = Profile()->GetBoolValue(CFG_XVID10_USE_QPEL);	m_use_interlacing = Profile()->GetBoolValue(CFG_XVID10_USE_INTERLACING);	m_use_lumimask_plugin = 	  Profile()->GetBoolValue(CFG_XVID10_USE_LUMIMASK);	m_use_par = 	  Profile()->GetIntegerValue(CFG_VIDEO_MPEG4_PAR_WIDTH) != 0 &&	  Profile()->GetIntegerValue(CFG_VIDEO_MPEG4_PAR_HEIGHT) != 0;	if (m_use_par) {	  int par_w = Profile()->GetIntegerValue(CFG_VIDEO_MPEG4_PAR_WIDTH);	  int par_h = Profile()->GetIntegerValue(CFG_VIDEO_MPEG4_PAR_HEIGHT);	  if (par_w > 255 || par_h > 255) {	    error_message("PAR parameters are > 255 - not used");	    m_use_par = false;	  } else {	    m_par = XVID_PAR_11_VGA;	    m_par_height = m_par_width = 0;	    if (par_w == 12 && par_h == 11) m_par = XVID_PAR_43_PAL;	    else if (par_w == 10 && par_h == 11) m_par = XVID_PAR_43_NTSC;	    else if (par_w == 16 && par_h == 9) m_par = XVID_PAR_169_PAL;	    else if (par_w == 40 && par_h == 33) m_par = XVID_PAR_169_NTSC;	    else {	      m_par = XVID_PAR_EXT;	      m_par_width = par_w;	      m_par_height = par_h;	    }	  }	}	memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init));	xvid_gbl_init.version = XVID_VERSION;	xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);	xvid_gbl_info_t xvid_info;	memset(&xvid_info, 0, sizeof(xvid_info));	xvid_info.version = XVID_VERSION;	xvid_global(NULL, XVID_GBL_INFO, &xvid_info, NULL);	debug_message("xvid info - vers %x build %s flags %x threads %d", 		      xvid_info.actual_version,		      xvid_info.build,		      xvid_info.cpu_flags, 		      xvid_info.num_threads);	xvid_enc_create_t enc_create;	memset(&enc_create, 0, sizeof(enc_create));	enc_create.version = XVID_VERSION;	enc_create.width = Profile()->m_videoWidth;	enc_create.height = Profile()->m_videoHeight;	enc_create.profile = Profile()->m_videoMpeg4ProfileId;       	xvid_enc_zone_t zones;	enc_create.zones = &zones;	enc_create.num_zones = 0;	// We might want to create our own plugin to get the	// reconstructed image pointer.	//	// We might also consider using a 2 pass system, as well.	xvid_enc_plugin_t plugins[2];	xvid_plugin_single_t single;	memset(&single, 0, sizeof(single));	single.version = XVID_VERSION;	single.bitrate = 	  Profile()->GetIntegerValue(CFG_VIDEO_BIT_RATE) * 1000;	plugins[0].func = xvid_plugin_single;	plugins[0].param = &single;	if (m_use_lumimask_plugin) {	  plugins[1].func = xvid_plugin_lumimasking;	  plugins[1].param = NULL;	  enc_create.num_plugins = 2;	} else {	  enc_create.num_plugins = 1;	}	enc_create.plugins = plugins;		if (Profile()->GetIntegerValue(CFG_VIDEO_TIMEBITS) == 0) {	  enc_create.fincr = 1;	  enc_create.fbase = 	    (int)(Profile()->GetFloatValue(CFG_VIDEO_FRAME_RATE) + 0.5);	} else {	  enc_create.fincr = 	    (int)(((double)Profile()->GetIntegerValue(CFG_VIDEO_TIMEBITS)) /		  Profile()->GetFloatValue(CFG_VIDEO_FRAME_RATE));	  enc_create.fbase = 	    Profile()->GetIntegerValue(CFG_VIDEO_TIMEBITS);	}	enc_create.max_key_interval = (int)		(Profile()->GetFloatValue(CFG_VIDEO_FRAME_RATE) 		 * Profile()->GetFloatValue(CFG_VIDEO_KEY_FRAME_INTERVAL));		// We may be able to do b-frames at some point - this means	// work in the rtp transmitter, as well as recording the pts	// and changing the file recorder as well (see mpeg2 work)	enc_create.max_bframes = 0;	enc_create.bquant_ratio = 150;	enc_create.bquant_offset = 100;	// There are also a number of options for quality that we	// may or may not want to deal with.  See the examples for that.	int xerr = xvid_encore(NULL, XVID_ENC_CREATE, &enc_create, NULL);	if (xerr) {		error_message("Failed to initialize Xvid encoder %d", xerr);		return false;	}	m_xvidHandle = enc_create.handle; 	return true;}static struct {  int vop;  int motion;} xvid10_quality[] = {  { 0, 0, },  { 0, XVID_ME_ADVANCEDDIAMOND16, },  { XVID_VOP_HALFPEL, (XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16),},  { (XVID_VOP_HALFPEL | XVID_VOP_INTER4V),    (XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |     XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8), },  { (XVID_VOP_HALFPEL | XVID_VOP_INTER4V),    (XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |     XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 |     XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP), },  { (XVID_VOP_HALFPEL | XVID_VOP_INTER4V |     XVID_VOP_TRELLISQUANT),    (XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |     XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 |     XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP), },  {(XVID_VOP_HALFPEL | XVID_VOP_INTER4V |    XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED),   (XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 |    XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 |    XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP),},};bool CXvid10VideoEncoder::EncodeImage(	const u_int8_t* pY, 	const u_int8_t* pU, 	const u_int8_t* pV, 	u_int32_t yStride,	u_int32_t uvStride,	bool wantKeyFrame,	Duration Elapsed,	Timestamp srcFrameTimestamp){  m_srcFrameTimestamp = srcFrameTimestamp;	xvid_enc_frame_t 		xvidFrame;	CHECK_AND_FREE(m_vopBuffer);	m_vopBuffer = (u_int8_t*)malloc(Profile()->m_videoMaxVopSize);	if (m_vopBuffer == NULL) {		return false;	}	memset(&xvidFrame, 0, sizeof(xvidFrame));	memset(&m_xvidResult, 0, sizeof(m_xvidResult));	xvidFrame.version = XVID_VERSION;	xvidFrame.vop_flags = xvid10_quality[m_video_quality].vop;	xvidFrame.motion = xvid10_quality[m_video_quality].motion;	if (m_use_gmc) {	  xvidFrame.vol_flags |= XVID_VOL_GMC;	  xvidFrame.motion |= XVID_ME_GME_REFINE;	}	if (m_use_qpel) {	  xvidFrame.vol_flags |= XVID_VOL_QUARTERPEL;	  xvidFrame.motion |= XVID_ME_QUARTERPELREFINE16;	  if (xvidFrame.vop_flags & XVID_VOP_INTER4V) {	    xvidFrame.motion |= XVID_ME_QUARTERPELREFINE8;	  }	}	if (m_use_interlacing) {	  xvidFrame.vol_flags |= XVID_VOL_INTERLACING;	}	  	xvidFrame.bitstream = m_vopBuffer;	xvidFrame.length = Profile()->m_videoMaxVopSize;	xvidFrame.input.csp = XVID_CSP_PLANAR;	xvidFrame.input.plane[0] = (void *)pY;	xvidFrame.input.stride[0] = yStride;	xvidFrame.input.plane[1] = (void *)pU;	xvidFrame.input.stride[1] = uvStride;	xvidFrame.input.plane[2] = (void *)pV;	xvidFrame.input.stride[2] = uvStride;	if (m_use_par) {	  xvidFrame.par = m_par;	  xvidFrame.par_width = m_par_width;	  xvidFrame.par_height = m_par_height;	}	// if we do quality work, we will need to set the motion 	// variable accordingly.	m_xvidResult.version = XVID_VERSION;	if (wantKeyFrame) {	  xvidFrame.type = XVID_TYPE_IVOP;	} else {	  xvidFrame.type = XVID_TYPE_AUTO;	}	m_vopBufferLength = xvid_encore(m_xvidHandle, XVID_ENC_ENCODE, &xvidFrame, 					&m_xvidResult);#ifdef WRITE_RAW	fwrite(m_vopBuffer, 1, m_vopBufferLength, m_outfile);#endif	//	message(LOG_DEBUG, "xvid", "return from encore %d %d", m_vopBufferLength, m_xvidResult.type);	if (m_vopBufferLength <= 0) {		debug_message("Xvid can't encode frame!");		CHECK_AND_FREE(m_vopBuffer);		return false;	}	return true;}bool CXvid10VideoEncoder::GetEncodedImage(	u_int8_t** ppBuffer, u_int32_t* pBufferLength,	Timestamp *dts, Timestamp *pts){  // will have to change this if we do b frames  *dts = *pts = m_srcFrameTimestamp; 	*ppBuffer = m_vopBuffer;	*pBufferLength = m_vopBufferLength;	m_vopBuffer = NULL;	m_vopBufferLength = 0;	return *pBufferLength != 0;}bool CXvid10VideoEncoder::GetReconstructedImage(	u_int8_t* pY, u_int8_t* pU, u_int8_t* pV){  // we may be able to do this with a plugin  return false;#if 0	imgcpy(pY, (u_int8_t*)m_m_xvidResult.image_y,		Profile()->m_videoWidth, 		Profile()->m_videoHeight,		m_m_xvidResult.stride_y);	imgcpy(pU, (u_int8_t*)m_m_xvidResult.image_u,		Profile()->m_videoWidth / 2, 		Profile()->m_videoHeight / 2,		m_m_xvidResult.stride_u);	imgcpy(pV, (u_int8_t*)m_m_xvidResult.image_v,		Profile()->m_videoWidth / 2, 		Profile()->m_videoHeight / 2,		m_m_xvidResult.stride_u);	return true;#endif}void CXvid10VideoEncoder::StopEncoder (void){  CHECK_AND_FREE(m_vopBuffer);  xvid_encore(m_xvidHandle, XVID_ENC_DESTROY, NULL, NULL);  m_xvidHandle = NULL;#ifdef WRITE_RAW  if (m_outfile) {    fclose(m_outfile);    m_outfile = NULL;  }#endif}/* * Ah - fun - pull the vol out of the encoder - hope it doesn't * change... */bool CXvid10VideoEncoder::GetEsConfig(uint8_t **ppEsConfig,				      uint32_t *pEsConfigLen){  uint8_t *yuvbuf = (uint8_t *)malloc(Profile()->m_yuvSize);  if (yuvbuf == NULL) {    error_message("xvid - Can't malloc memory for YUV for VOL");    StopEncoder();    return false;  }  // Create a dummy frame, and encode it, requesting an I frame  // this should give us a VOL  memset(yuvbuf, 0, Profile()->m_yuvSize);  if (EncodeImage(yuvbuf,		  yuvbuf + Profile()->m_ySize,		  yuvbuf + Profile()->m_ySize + Profile()->m_uvSize,		  Profile()->m_videoWidth,		  Profile()->m_videoWidth / 2,		  true,		  0, 		  0) == false &&      m_vopBufferLength > 0) {    error_message("xvid - encode image for VOL didn't work");    free(yuvbuf);    StopEncoder();    return false;  }  free(yuvbuf);  uint8_t *volptr, *vopptr;  volptr = MP4AV_Mpeg4FindVol(m_vopBuffer, m_vopBufferLength);  if (volptr == NULL) {    error_message("xvid - didn't put vol in header");    StopEncoder();    return false;  }  int32_t offset;  // I know, I'm using a mpeg1/2 routine, but it works  if ((offset =        MP4AV_Mpeg4FindHeader(volptr + 1,			     m_vopBufferLength - 1 - (volptr - m_vopBuffer)))       < 0) {    error_message("xvid - can't find vop after vol");    StopEncoder();    return false;  }  // not really a vop pointer, but pointer to next frame  vopptr = volptr + 1 + offset;  *ppEsConfig = m_vopBuffer;  *pEsConfigLen = (vopptr - m_vopBuffer);  RemoveUserdataFromVol(ppEsConfig, pEsConfigLen);  m_vopBuffer = NULL;  StopEncoder();  return true;}  

⌨️ 快捷键说明

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