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);
}