MPEG-4解码

1 源码下载

源码下载路径基于github开源库最新的release版本:1.3.7

https://github.com/ShiftMediaProject/xvid

2 交叉编译

2.1 解压

tar -xvf xvid-release-1_3_7.tar.gz
cd xvid-release-1_3_7

2.2 首次编译

进入Linux编译目录,直接执行make这时候会生成一个configure文件,这时候会编译生成对应平台的目标文件,但是不是平台交叉编译的文件。

cd build/generic/
make

2.3 交叉编译

编写一个简单sh脚本用于交叉编译:

#! /bin/sh

PWD=`pwd`
XBUILD=$PWD/../xinstall
XINCLUDE=$PWD/../include
XINLIB=$PWD/../lib

export COMPILE=arm-linux
cd ./build/generic/
./configure --target=$COMPILE --host=$COMPILE --prefix=$XBUILD \
                          --libdir=$XINLIB --includedir=$XINCLUDE \
                          && make clean && make && make install
cd -

编译过程很顺利,没有出啥错误,这个release还是比较靠谱的。编译完成会得到几个文件:一个是头文件:include/xvid.h;另一个是库文件:libxvidcore.a libxvidcore.so libxvidcore.so.4 libxvidcore.so.4.3

include/xvid.h
libxvidcore.a libxvidcore.so libxvidcore.so.4 libxvidcore.so.4.3

3 解码实现

解码部分主要是参考里面的demo写的:examples/xvid_decraw.c;整体比较简单分为三个部分,一是初始化;另一是解码;还有一个就是释放。
下面开始lu代码:

//初始化,调用demo的decinit
int video_mpeg4_start(int width, int height)
{
	int status = 0;
	status = dec_init(0, XVID_DEBUG_DEBUG);
	if (status) {
		fprintf(stderr,
				"Decore INIT problem, return value %d\n", status);
		goto video_mpeg4_init_fail;
		
	}
video_mpeg4_init_fail:
	if(status < 0)
		video_mpeg4_stop();
		
	return status;
}

static int dec_init(int use_assembler, int debug_level)
{
	int ret = 0;

	xvid_gbl_init_t   xvid_gbl_init;
	xvid_dec_create_t xvid_dec_create;
	xvid_gbl_info_t   xvid_gbl_info;

	/* Reset the structure with zeros */
	memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init_t));
	memset(&xvid_dec_create, 0, sizeof(xvid_dec_create_t));
	memset(&xvid_gbl_info, 0, sizeof(xvid_gbl_info));

	/*------------------------------------------------------------------------
	 * Xvid core initialization
	 *----------------------------------------------------------------------*/

	xvid_gbl_info.version = XVID_VERSION;
	xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info, NULL);

	if (xvid_gbl_info.build != NULL) {
		fprintf(stderr, "xvidcore build version: %s\n", xvid_gbl_info.build);
	}
	fprintf(stderr, "Bitstream version: %d.%d.%d\n", XVID_VERSION_MAJOR(xvid_gbl_info.actual_version), XVID_VERSION_MINOR(xvid_gbl_info.actual_version), XVID_VERSION_PATCH(xvid_gbl_info.actual_version));
	fprintf(stderr, "Detected CPU flags: ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_ASM)
		fprintf(stderr, "ASM ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_MMX)
		fprintf(stderr, "MMX ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_MMXEXT)
		fprintf(stderr, "MMXEXT ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_SSE)
		fprintf(stderr, "SSE ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_SSE2)
		fprintf(stderr, "SSE2 ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_SSE3)
		fprintf(stderr, "SSE3 ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_SSE41)
		fprintf(stderr, "SSE41 ");
    if (xvid_gbl_info.cpu_flags & XVID_CPU_3DNOW)
		fprintf(stderr, "3DNOW ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_3DNOWEXT)
		fprintf(stderr, "3DNOWEXT ");
	if (xvid_gbl_info.cpu_flags & XVID_CPU_TSC)
		fprintf(stderr, "TSC ");
	fprintf(stderr, "\n");
	fprintf(stderr, "Detected %d cpus,", xvid_gbl_info.num_threads);
	if (!ARG_THREADS) ARG_THREADS = xvid_gbl_info.num_threads;
	fprintf(stderr, " using %d threads.\n", ARG_THREADS);

	/* Version */
	xvid_gbl_init.version = XVID_VERSION;

	/* Assembly setting */
	if(use_assembler)
#ifdef ARCH_IS_IA64
		xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
#else
	xvid_gbl_init.cpu_flags = 0;
#endif
	else
		xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;

	xvid_gbl_init.debug = debug_level;

	xvid_global(NULL, 0, &xvid_gbl_init, NULL);

	/*------------------------------------------------------------------------
	 * Xvid decoder initialization
	 *----------------------------------------------------------------------*/

	/* Version */
	xvid_dec_create.version = XVID_VERSION;

	/*
	 * Image dimensions -- set to 0, xvidcore will resize when ever it is
	 * needed
	 */
	xvid_dec_create.width = 0;
	xvid_dec_create.height = 0;

	xvid_dec_create.num_threads = ARG_THREADS;

	ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvid_dec_create, NULL);

	g_cxt.dec_handle = xvid_dec_create.handle;

	return(ret);
}

3.2 释放操作

//释放更简单就是调用接口释放
int video_mpeg4_stop()
{
	int status = 0;

	if (g_cxt.dec_handle) {
	  	status = dec_stop();
		if (status)    
			fprintf(stderr, "decore RELEASE problem return value %d\n", status);
	}
	
	return status;
}


static int dec_stop()
{
	int ret;
	ret = xvid_decore(g_cxt.dec_handle, XVID_DEC_DESTROY, NULL, NULL);

	return(ret);
}

3.3 解码过程

解码过程对demo进行了一些变化,主要是为了将流的申请释放都放到内部实现,外部负责启动停止即可;这里面默认使用了YUV420解码后数据格式,以便于后面平台的渲染显示。

//解码一帧数据
void* video_mpeg4_decode(unsigned char *istream,
		 unsigned char **ostream,
		 int istream_size,
		 int *ostream_size,
		 xvid_dec_stats_t *xvid_dec_stats)
{
	int ret = 0;
	xvid_dec_frame_t xvid_dec_frame;

	/* Reset all structures */
	memset(&xvid_dec_frame, 0, sizeof(xvid_dec_frame_t));
	memset(xvid_dec_stats, 0, sizeof(xvid_dec_stats_t));

	/* Set version */
	xvid_dec_frame.version = XVID_VERSION;
	xvid_dec_stats->version = XVID_VERSION;

	/* No general flags to set */
	if (POSTPROC == 1)
		xvid_dec_frame.general          = XVID_DEBLOCKY | XVID_DEBLOCKUV;
	else if (POSTPROC==2)
		xvid_dec_frame.general          = XVID_DEBLOCKY | XVID_DEBLOCKUV | XVID_DERINGY | XVID_DERINGUV;
	else
		xvid_dec_frame.general          = 0;

	/* Input stream */
	xvid_dec_frame.bitstream        = istream;
	xvid_dec_frame.length           = istream_size;

	/* Output frame structure */
	xvid_dec_frame.output.plane[0]  = g_cxt.mem_vir;
	xvid_dec_frame.output.stride[0] = (g_cxt.width)*BPP;
	xvid_dec_frame.output.csp = XVID_CSP_I420;

	ret = xvid_decore(g_cxt.dec_handle, XVID_DEC_DECODE, &xvid_dec_frame, xvid_dec_stats);
	if(xvid_dec_stats->type == XVID_TYPE_VOL) {
		printf("[%s %d]:general(%d)\n", __FUNCTION__, __LINE__, xvid_dec_stats->data.vol.general);
		printf("[%s %d]:w:h(%d:%d)\n", __FUNCTION__, __LINE__, xvid_dec_stats->data.vol.width, xvid_dec_stats->data.vol.height);
		printf("[%s %d]:parw:h(%d:%d)\n", __FUNCTION__, __LINE__, xvid_dec_stats->data.vol.par_width, xvid_dec_stats->data.vol.par_height);
	
	}
	if(ret < 0)
	{
		return NULL;
	}
	*ostream = g_cxt.mem_vir;//获取解码后buf
	*ostream_size = ret;//获取解码后长度
	//printf("[%s %d]:ret(%d)\n", __FUNCTION__, __LINE__, ret);
	
	return(g_cxt.mem_phy);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值