当前位置: 代码迷 >> 综合 >> MPEG-4解码
  详细解决方案

MPEG-4解码

热度:86   发布时间:2023-12-26 07:25:10.0

MPEG-4解码实现

  • 1 源码下载
  • 2 交叉编译
    • 2.1 解压
    • 2.2 首次编译
    • 2.3 交叉编译
  • 3 解码实现
    • 3.2 释放操作
    • 3.3 解码过程

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/shPWD=`pwd`
XBUILD=$PWD/../xinstall
XINCLUDE=$PWD/../include
XINLIB=$PWD/../libexport 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_IA64xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
#elsexvid_gbl_init.cpu_flags = 0;
#endifelsexvid_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;elsexvid_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);
}