xvid的中文简介 肖申克的救赎中文简介

xvid的中文简介


XviD是一款开源的MPEG-4视频编解码器。XviD的API接口定义得非常清晰,其三个核心接口函数(xvid_global(),xvid_decore()和xvid_encore())和插件函数都具有统一的形式,大大简化了程序员的工作。本文将简单介绍XviD的三个核心API接口函数,对于Xvid的插件函数未做说明,计划在本文下一版中增加。
1 版本
XviD的版本号定义为$major.$minor.$patch的形式。当版本更新时:
􀁺 如果API接口没有发生改变,则增加$patch;
􀁺 如果API接口发生了改变,但仍然向后兼容,则增加$minor;
􀁺 如果API接口发生了重大变化,则增加$major。
很多XviD结构体都包含一个version成员,用于指定所采用的XviD的版本。正确的初始化方法是:先将结构体全部清空为0,然后再设置version成员。如下所示:
memset(&struct,0,sizeof(struct));
struct.version = XVID_VERSION;
与XviD版本有关的宏定义为:
#define XVID_MAKE_VERSION(a,b,c)((((a)&0xff)<<16) |(((b)&0xff)<<8) |((c)&0xff))
#define XVID_VERSION_MAJOR(a)((char)(((a)>>16) &0xff))
#define XVID_VERSION_MINOR(a)((char)(((a)>> 8) &0xff))
#define XVID_VERSION_PATCH(a)((char)(((a)>> 0) &0xff))
#define XVID_MAKE_API(a,b)((((a)&0xff)<<16) |(((b)&0xff)<<0))
#define XVID_API_MAJOR(a) (((a)>>16)& 0xff)
#define XVID_API_MINOR(a) (((a)>> 0)& 0xff)
#define XVID_VERSION XVID_MAKE_VERSION(1,1,2)
#define XVID_API XVID_MAKE_API(4, 1)
XviD中存在两个版本,一个是XviD库本身的版本,即XVID_VERSION;另一个是
XviD应用编程接口(API)简介(v0.1) - 2 -
XviD的API接口的版本,即XVID_API。XVID_VERSION定义为一个24位的无符号整数;XVID_API定义为一个16位的无符号整数。
XVID_MAKE_VERSION(a,b,c)宏的作用是生成XVID_VERSION,其中a、b、c分别是XviD版本号中的$major、$minor和$patch。
XVID_VERSION_MAJOR(a)用于从XVID_VERSION中抽取出$major;XVID_VERSION_MINOR(a)用于从XVID_VERSION中抽取出$minor;XVID_VERSION_PATCH(a)用于从XVID_VERSION中抽取出$patch。
2 错误码
所有XviD函数都以返回小于0的值表明出现了错误。定义的错误码如下:
#define XVID_ERR_FAIL -1
#define XVID_ERR_MEMORY -2
#define XVID_ERR_FORMAT -3
#define XVID_ERR_VERSION -4
#define XVID_ERR_END -5
XVID_ERR_FAIL表示一般性错误;XVID_ERR_MEMORY表示内存分配错误;XVID_ERR_FORMAT表示文件格式错误;XVID_ERR_VERSION表明程序中使用了不再被支持的结构体版本;XVID_ERR_END是编码器独有的错误码,表示已经到达流末尾。
3 色场空间
XviD中定义的色场空间如下:
#define XVID_CSP_PLANAR (1<< 0)
#define XVID_CSP_USER XVID_CSP_PLANAR
#define XVID_CSP_I420 (1<< 1)
#define XVID_CSP_YV12 (1<< 2)
#define XVID_CSP_YUY2 (1<< 3)
#define XVID_CSP_UYVY (1<< 4)
#define XVID_CSP_YVYU (1<< 5)
#define XVID_CSP_BGRA (1<< 6)
#define XVID_CSP_ABGR (1<< 7)
#define XVID_CSP_RGBA (1<< 8)
#define XVID_CSP_ARGB (1<<15)
#define XVID_CSP_BGR (1<< 9)
#define XVID_CSP_RGB555 (1<<10)
#define XVID_CSP_RGB565 (1<<11)

#define XVID_CSP_SLICE (1<<12)
#define XVID_CSP_INTERNAL(1<<13)
#define XVID_CSP_NULL (1<<14)
#define XVID_CSP_VFLIP (1<<31)
尽管XviD定义的色场空间比较多,但实际上常用的只有XVID_CSP_I420、XVID_CSP_YV12、XVID_CSP_BGR、XVID_CSP_RGB555、XVID_CSP_RGB565这样几种。
作者个人的观点:XVID_CSP_PLANAR、XVID_CSP_USER、XVID_CSP_I420、XVID_CSP_YV12都属于YUV4:2:0色场空间,采用YUV平面格式存放;XVID_CSP_YUY2、XVID_CSP_UYVY、XVID_CSP_YVYU都属于YUV4:2:2色场空间,采用YUV紧缩格式存放。XviD似乎没有提供对YUV4:4:4和YUV4:1:1色场空间的支持——也可能是MPEG-4标准不支持。无论如何,常用的YUV色场空间是YUV4:2:0。
4 profile和level定义
XviD中定义了对三种MPEG-4 Profile@Level组合的支持:Simple(S)、Advanced RealtimeSimple(ARTS)、Advanced Simple(AS)。
#define XVID_PROFILE_S_L0 0x08
#define XVID_PROFILE_S_L1 0x01
#define XVID_PROFILE_S_L2 0x02
#define XVID_PROFILE_S_L3 0x03
#define XVID_PROFILE_ARTS_L1 0x91
#define XVID_PROFILE_ARTS_L2 0x92
#define XVID_PROFILE_ARTS_L3 0x93
#define XVID_PROFILE_ARTS_L4 0x94
#define XVID_PROFILE_AS_L0 0xf0
#define XVID_PROFILE_AS_L1 0xf1
#define XVID_PROFILE_AS_L2 0xf2
#define XVID_PROFILE_AS_L3 0xf3
#define XVID_PROFILE_AS_L4 0xf4
XviD没有定义对MPEG-4中其它Profile@Level组合的支持。
5 像素幅型比(Pixel Aspect Ration)
像素幅型比表示的是屏幕上一个像素点的宽度和高度的比值,简写为PAR(即Pixel AspectRatio的缩写)。XviD定义了对如下几种标准的像素幅型比的支持:

#define XVID_PAR_11_VGA 1
#define XVID_PAR_43_PAL 2
#define XVID_PAR_43_NTSC 3
#define XVID_PAR_169_PAL 4
#define XVID_PAR_169_NTSC 5
#define XVID_PAR_EXT 15
视频应用中常见的像素幅型比有两种:4:3和16:9,后者更具有剧场效果。PAL和NTSC是两种电视标准(另外一种电视标准是SECAM),这两种电视标准都是隔行扫描时代的产物。PAL规定的场率是50场/秒(即25帧/秒),扫描线行数是525行;NTSC规定的场率是60场/秒(即30帧/秒),扫描线行数是625行。
6 帧类型
XviD定义了如下帧类型:
#define XVID_TYPE_VOL -1
#define XVID_TYPE_NOTHING 0
#define XVID_TYPE_AUTO 0
#define XVID_TYPE_IVOP 1
#define XVID_TYPE_PVOP 2
#define XVID_TYPE_BVOP 3
#define XVID_TYPE_SVOP 4
在解码的时候,常见的做法是根据帧类型的不同而进行不同的处理。XVID_TYPE_VOL、XVID_TYPE_IVOP、XVID_TYPE_PVOP、XVID_TYPE_BVOP较常用。作者暂不清楚XVID_TYPE_SVOP的含义。
7 xvid_global()函数
函数原型:
int xvid_global(void *handle, int opt, void *param1, void*param2);
功能:
􀁺 全局初始化;
􀁺 获取XviD和硬件功能信息(全局信息);
􀁺 色场空间转换。

参数:
􀁺 handle,是一个句柄,代表着一个xvid global操作实例,
􀁺opt,指定要执行的操作,对应于上面三种功能,opt分别可取XVID_GBL_INIT、XVID_GBL_INFO、XVID_GBL_CONVERT这样三个值;
􀁺 param1,是对应操作的入口参数或者出口参数。当opt为XVID_GBL_INIT时,param1是入口参数,应当为一个xvid_gbl_init_t类型的指针;当opt为XVID_GBL_INFO时,param1是出口参数,应当为一个xvid_gbl_info_t类型的指针;当opt为XVID_GBL_CONVERT时,param1是入口参数,应当为一个xvid_gbl_convert_t类型的指针;
􀁺 param2,这个参数将被忽略,通常应当设置为NULL。
返回值:
􀁺 成功:返回0;
􀁺 失败:返回相应错误码(<0)。
7.1 全局初始化
当xvid_global()函数的第二个参数opt为XVID_GBL_INIT时,xvid_global()函数对整个XviD进行初始化。初始化的内容包括要用到CPU的哪些功能以及要采用哪一个调试级别。XviD的灵活之处在于:它既可以自行确定使用CPU的哪些功能,也能够让编程者来决定如何发掘CPU的处理能力。
opt参数为XVID_GBL_INIT时,xvid_global()函数的param1参数应该为一个xvid_gbl_init_t类型的指针。xvid_gbl_init_t定义为:

typedef struct {
int version;
unsigned int cpu_flags;
int debug;
} xvid_gbl_init_t;
前面说过,XviD的API接口中所有的结构体类型都包含一个version成员,应当将其设置为所采用的XviD的版本。
对 于cpu_flags成员,当其值为0时,将由XviD自动探测所用CPU的处理能力。当想强制使用CPU的某种特殊功能时,必须同时为cpu_flags指定XVID_CPU_FORCE标志和相关的功能标志,比如,要强制使用IA32体系结构的MMX指令,就必须将cpu_flags进行如下设置:
struct.cpu_flags = XVID_CPU_FORCE | XVID_CPU_MMX;

XviD支持的CPU功能列表如下所示,其中,XVID_CPU_ALTIVEC是专门针对PPC体系结构的。其它的大部分功能都是针对IA32体系结构的。
#define XVID_CPU_FORCE (1<<31)
#define XVID_CPU_ASM (1<< 7)

#define XVID_CPU_MMX (1<< 0)
#define XVID_CPU_MMXEXT (1<< 1)
#define XVID_CPU_SSE (1<< 2)
#define XVID_CPU_SSE2 (1<< 3)
#define XVID_CPU_3DNOW (1<< 4)
#define XVID_CPU_3DNOWEXT (1<<5)
#define XVID_CPU_TSC (1<< 6)

#define XVID_CPU_ALTIVEC (1<<0)
xvid_gbl_init_t结构体中的debug成员用来表明XviD的调试级别,不同的调试级别表明了不同的出错原因。实际上,这和Linux内核编程中的打印函数printk()很相似。XviD定义了如下调试级别:
#define XVID_DEBUG_ERROR (1<<0)
#define XVID_DEBUG_STARTCODE (1<<1)
#define XVID_DEBUG_HEADER (1<<2)
#define XVID_DEBUG_TIMECODE (1<<3)
#define XVID_DEBUG_MB (1<< 4)
#define XVID_DEBUG_COEFF (1<<5)
#define XVID_DEBUG_MV (1<< 6)
#define XVID_DEBUG_RC (1<< 7)
#define XVID_DEBUG_DEBUG(1<<31)
由于每一种调试级别实际上都是以一个标志位来表示的,因此实际上可以指定多重调试级别。
下面是一个采用xvid_global()函数进行全局初始化的示例代码:
xvid_gbl_init_t xvid_gbl_init;

memset(&xvid_gbl_init, 0,sizeof(xvid_gbl_init_t));

xvid_gbl_init.version = XVID_VERSION;

xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_MMX;

xvid_gbl_init.debug = XVID_DEBUG_ERROR | XVID_DEBUG_COEFF;

xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init,NULL);
简单说明一下上述代码:首先将xvid_gbl_init结构体清零;然后依次设置版本、CPU功能、调试级别,也就是分别给三个结构体成员赋值。这里,指定采用CPU的MMX指令,同时,指定了两个调试级别:XVID_DEBUG_ERROR和XVID_DEBUG_COEFF。最后,调用xvid_global()使这些设置生效。注意到xvid_global()函数的第一个参数handle和最后一个参数param2都被置为NULL指针。
7.2 获取全局信息
当xvid_global()函数的第二个参数opt为XVID_GBL_INFO时,xvid_global()函数将用于获取xvid处理器硬件信息。xvid_global()函数的第三个参数param1为出口参数,指向一个xvid_gbl_info_t类型的结构体。

typedef struct {
int version;
int actual_version;
const char * build;
unsigned int cpu_flags;
int num_threads;
} xvid_gbl_info_t;
在调用xvid_global()函数获取信息之前,应该设置xvid_gbl_info_t结构体的version成员为当前的XviD版本,而在实际的输出结果中,actual_version表示的是XviD的实际版本;如果build指针不为空,则是指向一个描述字符串以表明xvid的构建版本;cpu_flags用于表明CPU能够支持的功能集合;num_threads表示线程数(作者未能搞清楚这个变量的含义)。
一个通过xvid_global()函数获取XviD版本信息和CPU信息的示例程序如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xvid.h"
int
main(void)
{
xvid_gbl_info_t xvid_gbl_info;

memset(&xvid_gbl_info, 0,sizeof(xvid_gbl_info_t));

xvid_gbl_info.version = XVID_VERSION;

xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info,NULL);

printf("actual version: %d.%d.%dn",
XVID_VERSION_MAJOR(xvid_gbl_info.actual_version),
XVID_VERSION_MINOR(xvid_gbl_info.actual_version),
XVID_VERSION_PATCH(xvid_gbl_info.actual_version));
if (xvid_gbl_info.cpu_flags | XVID_CPU_MMX)
printf("CPU: MMXn");
if (xvid_gbl_info.build)
printf("build: %sn", xvid_gbl_info.build);
printf("threads: %dn", xvid_gbl_info.num_threads);
return (0);
}
编译上述程序,运行结果如下:
[root@cyc test]# ./xvid_test
actual version: 1.1.2
CPU: MMX
build: xvid-1.1.2
threads: 0
7.3 色场空间转换
个功能是完成色场空间的转换。此时 xvid_global()函数的第二
个参数 opt 为 XVID_GBL_CONVERT,第三个参数 param1 应指向一个xvid_gbl_convert_t
类型
xvid_global()函数的第三
的结构体。xvid_gbl_convert_t定义为:

VID_GBL_CONVERT param1
typedef struct {
int version;
xvid_image_t input;
xvid_image_t output;
int width;
int height;
int interlacing;
} id_gbl_convert_t; xv
解释一下xvid_gbl_covert_t的各个成员:ver n sion 的含义不用再解释了,前面已多次说
以及相应的色场空间;output 表示输出图像以及相应的色场空间;
width 表示要转换的图像的宽度;height 表示要转换的图像的高度;interlacing 是一个标志,
用来
明;input表示输入图像
表明图像是否是隔行扫描图像。xvid_gbl_convert_t中的所有成员都是输入参数。input和output都是xvid_image_t类型的变量,在XviD中将xvid_image_t结构体定义为:
xvid的中文简介 肖申克的救赎中文简介
type
def struct { int csp;
void * plane[4];
int stride[4]; } xvid_image_t;
xvid_image_t结构体的第一个成员csp表示色场空间,第二个成员 plane 是一个 4 元素
中的每一个指针指向一个输出色场平面;第四个参数 stride 也是一个 4 元
素的数组,数组中的每一个元素都用于指明在相应色场平面上的步长为多少,所谓步长实际
上就
8 xvid_decore 函数
ecore()。xvid_decore()的函数原型如下:
的指针数组,数组
是指一行像素点的个数。(示例程序暂略)
()
XviD解码的核心函数是xvid_d
int xvid_decore(void *handle, int opt, void *param1, void*param2);
xvid_decore()函数的几个参数的含义分别是:
。opt 可取如下值之一:
XVID_DEC_CREATE、XVID_DEC_DESTROY、XVID_DEC_DECODE。和
XviD 解码实例
DE),在解码
)。
􀁺 比
􀁺 handle,是一个句柄,用来代表一个XviD解码操作实例;
􀁺 opt,指定xvid_decore()函数要执行的操作
xvid_global()函数不同,在执行解码操作时,必须先创建一个
(XVID_DEC_CREATE),然后进入解码循环(XVID_DEC_DECO循环完成之后应当销毁一开始创建的XviD解码实例(XVID_DEC_DESTROYparam1,是一个通用指针类型,具体应该指向什么根据opt参数的取值而定,如,当opt的值为XVID_DEC_CREATE时,param1应该指向一个xvid_dec_create_t类型的结构体。对于opt为XVID_DEC_CREATE和XVID_DEC_DECODE的情
形,param1都是必要参数。对于opt为XVID_DEC_DESTROY的情况,param1参数将被忽略,通常设置为NULL即可。
􀁺
下面就 的。
8.1 创建
在使用 XviD 进行解码之前,必须先创建 XviD 解码实例。创建 xvid 解码实例的具体做
te_t 类型的结构体,然后将其地址做为 param1 参数传
递给 xvid_decore()函数,其中,opt 参数指定为 XVID_DEC_CREATE。第一个参数 handle
和 param
param2,是一个可选参数,只在opt为XVID_DEC_DECODE的时候有效,指向一个xvid_dec_stats_t类型的结构体。依次来看看xvid_decore()函数都是如何调用
xvid解码实例
法是:首先初始化一个xvid_dec_crea
2参数都可以指定为NULL。在xvid中,xvid_dec_create_t定义如下:
typedef struct {
int version;
int width;
int height;
void * handle;
} xvid_dec_create_t;
在xvid_dec_creat_t的几个成员中: e
采用的 XviD 的版本,按照前面的方式初始化即可;
􀁺 width,是解码后的图像的宽度,如果解码之前已经事先知道,可设置,否则设

􀁺 xvid_decore()
成之后再从 xvid_dec_create_t 的 handle 成员
示例:
􀁺 version,是
置为0即可。width是输入参数
􀁺 height,是解码后的图像的高度,如果解码之前已经事先知道,可设置,否则设
置为0即可。height是输入参数; handle,是一个句柄。之所以有这个成员,其原因是:通常在调用
函数创建XviD解码实例的时候,都将xvid_decore()函数的第一个参数handle设置为NULL,在创建xvid解码实例完
中得到这个句柄。此后在调用xvid_decore()函数进行解码的时候就可以使用这个句柄了。Handle成员是输出参数。
xvid_dec_create_t xvid_dec_create;
void *d ndle = NULL;
ec_ha

memset(&xvid_dec_create, 0,sizeof(xvid_dec_create_t));

xvid_dec_create.version = XVID_VERSION;
xvid_dec_create.width = 0;
xvid_dec_create.height = 0;
ret = xvid_decore(NULL, XVID_DEC_CREATE,&xvid_dec_create, NULL);
dec_handle = xvid_dec_create.handle;
上面的这段示例代码定义了一个句柄 dec_handle(其实是一个无类型指针),在调用
vid_decore()函数完成 XviD 解码实例的创建工作之后,通过
x
dec_handle = xvid_dec_create.handle;
将创建的句柄指定给了dec_handle。
8.2 解码
开始真正的解码了。解码也是通过 xvid_decore()
函数来完成的。解码要用到两个结构体类型:xvid_dec_frame_t 和 xvid_dec_stats_t,
c_fram _t 指 定 给 xvid_decore() 函 数 的 param1 参 数 , xvid_dec_stats_t 指定 给
数的 param2 参数。尽管 param2 是可选参数,但是通常情况下都是应该指定
的,因为通过它才能知道解码过程的状态。此外,xvid_decore()函数的第一个参数 handle 应
该为
_
在创建了解码实例之后,接下来就是
xvid_deexvid_decore()函
创建XviD解码实例时返回的xvid_dec_create_t类型的结构体中的handle成员。在进行解码操作时,xvid_decore()函数的opt参数应当设置为XVID_DEC_DECODE。XviD对xviddec_frame_t类型的定义如下: typedefstruct { int version; int general;
from)*/
void *bitstream;
xvid_image_t output;

int brightness;
} id_dec_frame_t; xv
xvid_dec_frame_t中各个成员的作用简单说明如下:
􀁺 general,是一个可选输入参数。这个参数的取值可以是下面这些标志取或的结果:

#define XVID_LOWDELAY (1<<0)
#def break in stream */
ine XVID_DISCONTINUITY (1<<1)
#define XVID_DEBLOCKUV (1<<3)
#define XVID_FILMEFFECT (1<<4)
#define XVID_DERINGUV (1<<5)
#define XVID_DERINGY (1<<6)
#define XVID_DEC_FAST (1<<29) #defineXVID_DEC_DROP (1<<30) #defineXVID_DEC_PREROLL (1<<31)
这些标志控制着解码器的某些功能:
􀂄 XVID_LOWDELAY 以低延迟模式解码;
􀂄 XVID_DEBLOCKY 去除亮度块状化(猜测);
除色差块状化(猜测);

图像畸变),要求开启去除
去除块状化标志;
用,暂未实现;
􀂄 EROLL 尽可能快地解码,甚至不显示输出。
通常 的 些
􀁺 it
􀁺 n
􀁺 ut id 的输出流,
􀂄 XVID_DISCONTINUITY 以非连续模式解码;
􀂄 XVID_DEBLOCKUV 去
􀂄 XVID_FILMEFFECT 添加影片效果(猜测)
􀂄 XVID_DERINGUV 去除色差“振铃”(一种
块状化标志;
􀂄 XVID_DERINGY 去除亮度“振铃”,要求开启
􀂄 XVID_DEC_FAST 禁用后处理以减少CPU使
􀂄 XVID_DEC_DROP 丢弃B帧以减少CPU使用,暂未实现; XVID_DEC_PR
情况下,如果不需要上面这功能,可以将general设置为0。
bstream,是一个输入参数,指向要解码的输入流;
legth,是一个输入参数,表明bitstream所指向的输入码流的长度;
oput,输入参数,是一个xv_image_t类型的变量,用来指定解码后
xvid_image_t类型前面已有说明,这里再次列举如下:
typedef struct {
in sp
t c;
void *
plane[4];
int stride[ [in] image stride; "bytes per row"*/ 4]; _DECODE
typedef struct
{
int versio
n;
t
int type;
union{
struct {
int general;
int time_base;
int time_increment;
int * qscale;
int qscale_stride;
} p; vo
stru ct { VOL
int general;
int width;
int height; int par;
int par_width;
int par_height;
} l; vo } ta; da
} idec_stats_t; xv _d
xvid_dec_stats_t 类型中最重要的部分是 data,这是一个联合,联合的两个成员分别是两
结 体 结 体 vol 则描述
类型中,type 成员的作用是用来确定解出来的帧的类型,有关帧的类型
type 的值为 XVID_TYPE_VOL 时,data 联合中存放的是 vol;当 type 的
VOP、XVID_TYPE_PVOP、XVID_TYPE_BVOP、XVID_TYPE_SVOP
之一时,data 联合中存放的是 vop。
以像素为单位,
的 NTSC 或者 PAL 幅型比,则 par_width 和 par_height
对 v
隔;
􀁺 长(具体含义未搞清楚)。
图像的大小,可以在创建 XviD 解码实例的时候指定
解码后 图 可以在解码的过程中知道解出
来的图像的大小,这就是通过 xvid_dec_stats_t 中的 vol 结构体来实现的。
示例代码:
个构,构体vop描述了一个视频对象平面(Video Object Plane);而结构
了一个视频对象层(Video Object Layer)。
xvid_dec_stats_t
前面已做说明。当
值为XVID_TYPE_I
首先来解释vol结构体中的各个成员: 􀁺 general中保存的是解码器解码时所采用的标志; 􀁺width是解码出来的图像的宽度,
􀁺 height是解码出来的图像的高度,以像素为单位; 􀁺 par是解码出来的图像的像素幅型比; 􀁺如果解码后的图像不是标准
就是实际所采用的像素幅型比。
于op结构体中的各个成员:
􀁺 general中保存的是解码器解码时所采用的标志;
􀁺 time_base是相对于开始解码时的时间长度(猜测);
􀁺 time_increment是相对于上一帧的时间间
􀁺 qscale指向外部提供的量化表(猜测); qscale_stride代表量化器的缩放步
前面说过,如果事先知道解出来的
的像的大小;如果不知道的话,也没有关系,XviD
#defin
e IN_BITSTREAM_SIZE 1024
#define
OUT_BITSTREAM_SIZE 1024
#define STRIDE 352
unsigned char istream[IN_BITSTREAM_SIZE]; unsigned charostream[OUT_BITSTREAM_SIZE];
int i IN_BITSTREAM_SIZE;
stream_size =
xvid_dec_frame_t xvid_dec_frame;
xvid_dec_stats_t xvid_dec_stats;

memset(&xvid_dec_frame, 0,sizeof(xvid_dec_frame_t));
memset(&xvid_dec_stats, 0,sizeof(xvid_dec_stats_t));

xvid_dec_frame.version = XVID_VERSION;
xvid_dec_stats.version = XVID_VERSION;

xvid_dec_frame.general = 0;

xvid_dec_frame.bitstream = istream;
xvid_dec_frame.length = istream_size;

xvid_dec_frame.output.plane[0] = ostream;
xvid_dec_frame.output.stride[0] = STRIDE;
xvid_dec_frame.output.csp = XVID_CSP_UYVY;

xvid_decore(dec_handle, XVID_DEC_DECODE,&xvid_dec_frame,&xvid_dec_stats);
在 xvid_decore()函数中,dec_handle 是上一节创建 XviD 解码实例时得到的那个句柄。
文件或者其它媒介(比如网络)读取输入码流的过程,解码得
:2:2 紧缩格式),采用单平面输出。另外,通常
据解码的状态决定对解码得到的码流如何处理,
显示设备输出或者保存到文件中。而如果
码得到的是 vol,那么可能会根据需要调整输出图像缓冲区的大小,等等。
上面的实例代码中没有加入从
到的图像采用的是UYVY格式(一种YUV 4
情况下的做法是在一个循环中不断解码,根
比如,如果解码正常,那么可能会将得到图像通过

8.3 销毁xvid解码实例
销毁XviD解码实例比较简单。方法如下:将xvid_decore()函数的第一个参数handle设为创建XviD解码实例后得到的句柄;第二个参数opt设置为XVID_DEC_DESTROY;参数param1和param2都设为NULL。销毁XviD解码实例之后,不能再通过其对输入码流进行解码。示例代码:
xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL);
上述代码中的第一个参数 dec_handle 是创建 XviD 解码实例之后得到的。

9 xvid_encore()函数
-4 标准规定的码流。与
xvid_decore()函数的工作流程一样:xvid_encore()函数的使用方法也是先创建一个 XviD 编码
实例 建的 XviD
编码实例。不过,与 xvid_decore()相比,xvid_encore()函数的使用要复杂一些,主要原因是
vid_encore()函数原型定义如下:
xvid_encore()是对输入的原始图像进行编码,输出符合MPEG
;然后执行实际的编码操作;最后,在所有的解码过程都结束之后,销毁所创
编码过程的参数设置要麻烦一些。x
int xvid_encore(void *handle, int opt, void *param1, void*param2);
xvid_encore() 函数的几个参数的含义分别是: 􀁺 handle,编码实例的句柄,用来代表一个xvid编码操作实例; 􀁺opt,指定xvid_encore()函数要执行的操作。opt可取如下值之一:XVID_ENC_CREATE、XVID_ENC_DESTROY、XVID_ENC_ENCODE。在执行
编码操作时,必须先创建一个 编码实例( CREATE),然后进
应当销毁所创建的
)。
,是一个通用指针类型,具体应该指向什么根据 opt 参数的取值而定。当
XVID_ENC_CREATE 时,param xv nc_create_t 类
ODE 的情形,
􀁺
xvid_dec_sta
返 值
􀁺
函数返回输出的字节数表示执行成功;
示执行失败,对于 opt 为
XVID_ENC_ENCODE 的情形,xvid_encore()函数返回 0 表示该帧不应该被写入;
下面就来依次看看
9.1 创建
在 创 建 数 设 为一 个
xvid_enc_c
XviDXVID_ENC_入编码循环(XVID_ENC_ENCODE),在编码循环完成之后
XviD编码实例(XVID_ENC_DESTROY
􀁺 param1opt的值为1应该指向一个id_e
型 的结构体。对于opt为XVID_ENC_CREATE和XVID_ENC_ENCparam1都是必要参数。对于opt为XVID_ENC_DESTROY的情况,param1应当为NULL。param2,是一个可选参数,只在opt为XVID_ENC_ENCODE的时候有效,指向一个ts_t类型的结构体。
回:成功:对于opt为XVID_ENC_CREATE和XVID_ENC_DESTROY的情形,xvid_encore()函数返回0表示成功,对于opt为XVID_ENC_ENCODE的情形,xvid_encore()
􀁺失败:对于opt为XVID_ENC_CREATE和XVID_ENC_DESTROY的情形,xvid_encore()函数返回小于0的错误码表
xvid_encore()函数是如何完成不同的功能的。xvid编码实例
XviD编码实例时,应当将xvid_encore()函数的param1参reate_t类型的结构体的地址。xvid_enc_create_t类型定义如下:

typedef struct {
int version;
int profile;
int width;
int height;
int num_zones;
xvid_enc_zone_t * zones;
int num_plugins;
xvid_enc_plugin_t * plugins;
int num_threads;
int max_bframes;
int global;

int fincr; fra
int fbase;


int max_key_interval; int frame_drop_ratio;
int bquant_ratio; ci
int bquant_offset;
int min_quant[3]; int max_quant[3];

void *handle;
} id_enc_create_t; xv
下面对 xvid_enc_create_t 中的成员逐一进行简要说明:
同前;
level 组合,XviD 编码器将据此决定如
间进行折衷。关于 profile 和 level 的定
设定为 XVID_PROFILE_S_L0,就表明
码。profile 是一个
􀁺 width,为输入帧的宽度,以像素为单位。width 是一个输入参数;
,这是一个可选输入参数;
􀁺
􀁺
􀁺 num_threads,线程数,(作用未知),这是一个可选输入参数;
􀁺 es,最大 B 帧数,设为 0 禁用 B 这是一个可选输入参数;
􀁺 global,全局标志位,这些标志位控制着 XviD 编码器的行为。这是一个可选输
􀁺 version,应当设置为所用的xvid的版本,
􀁺 profile,应当设置为准备采用的profile和
何在编码质量和压缩效率以及运算强度之义在前面已有说明。比如,如果将profile
希望XviD编码器按照MPEG-4 Simple profile的level 0进行编
输入参数;
􀁺 height,为输入帧的高度,以像素为单位。height是一个输入参数;
􀁺 num_zones,似乎是码流zone数目(作用未搞清楚)
􀁺 zones,似乎是zone数组(作用未搞清楚),这是一个可选输入参数; num_plugins,插件数目,这是一个可选输入参数;plugins,插件数组,这是一个可选输入参数;
max_bfram帧,
入参数,当不需要控制编码器的行为时,将其设为0即可。global中允许的标志
位如下(作者窃以为这些标志都是为视频编码专家准备的):

#define XV eam */ ID_GLOBAL_PACKED(1<<0)
#define XVID_GLOBAL_EXTRASTATS_ENABLE(1<<2)
#if 0
#define XVID_GLOBAL_VOL_AT_IVOP(1<<3) #defineXVID_GLOBAL_FORCE_VOL
(1<<4) #
endif #define XVID_GLOBAL_DIVX5_USERDATA(1<<5)
􀁺 fincr,帧率增量,设为0时为可变帧率(作用未完全搞清楚),这是一个可选输
入参数;
员用于确定帧之间的间隔时间,计算公式为:帧间间隔=fincr/fbase
e)与关键帧之间的最大间隔,单位为帧。
比如,如果设为 50,就表示两个关键帧之间应该有 50 个 P 帧或者 B 帧。这是一
􀁺 o,B 帧量化器 multipier(作用未搞清楚),这是一个可选输入参数;
(past_ref_quant,future_ref_quant)*bquant_ratio + bquant_offset) /100 计算 B
􀁺
􀁺 ,可选输入参数;
尽 x
参数仅 面
例代码(未
􀁺 fbase,这个成
秒; 􀁺 max_key_interval,关键帧(即Intra fram
个可选输入参数;
􀁺 frame_drop_ratio,为丢弃帧占总帧数的比例,取值为0到100之间,为0时不丢
弃帧,为100时丢弃所有帧。这是一个可选输入参数; bquant_rati
􀁺 bquant_offset,B帧量化器偏移(作用未搞清楚)。似乎是通过下面的公式bquant = (avg
帧的量化器系数,在此公式中用到了bquant_ratio和bquant_offset;min_quant[3],最小量化系数(作用未知),可选输入参数; max_quant[3],最大量化系数(作用未知)
􀁺handle,在创建xvid编码实例之后,xvid_encore()函数将通过这个成员返回一个编码实例的句柄。这个成员是一个输出参数。
管vid_enc_create_t中需要设置的参数比较多,但是很多都是可选参数,必须设置的
下这样几个:version、profile、width、height。因此,下面就给出一个最简单的示经过验证):
#define C
IF_ROW 352
#define CIF_CO 8 L 28
void * enc
_handle = NULL;
xvid_enc_create_t xvid_enc_create;
memset(&xvid_enc_create, 0,sizeof(xvid_enc_create_t)); xvid_enc_create.version =XVID_VERSION;

xvi
d_enc_create.width = CIF_ROW;
xvid_enc_create.height = CIF_COL;
xvid_enc_create.profile = XVID_PROFILE_S_L0;
xvid_encore(NULL, XVID_ENC_CREATE,&xvid_enc_create, NULL);

enc_handle = xvid_enc_create.handle;
在调用xvid_encore()函数创建XviD编码实例的时候,第一个参数 handle 指定为 NULL
API 函数忽略掉),在创建完成之后,从 xvid_enc_create
c_handle。此后,在编码过程中或者在销毁编码实例的
enc_handle。
.2 编码
行真正的编码工作了,这也是通过
码过程,xvid_encore()函数的 param1 参数应当设定为
一个指向 xvid_enc_frame_t 类型的结构体,可选参数 param2 可以指向一个xvid_enc_stats_t
类型
xvid_enc_frame_t 是 param1 参数应当指向的类型,xvid_enc_frame_t 在 XviD中定义为:
(实际上即使指定了值也会被XviD的
中取出创建的编码实例的句柄赋给en
时候,都应该将xvid_encore()函数的handle参数指定为
9
在创建了XviD编码实例之后,紧接着的事情就是进
xvid_encore()函数完成的。为了完成编
的结构体,如果不关心编码状态,也可以将param2设置为NULL。xvid_encore()函数的第一个参数handle通常应当设置为创建XviD编码实例之后得到的句柄,而opt参数应该指定为XVID_ENC_ENCODE。当xvid_encore()函数调用成功时,将返回编码后输出的字节数,如果返回0则表明当前所在的帧不应该写入。

#define XVID_KEYFRAME (1<<1)

typedef struct {
int version;

int vol_flags;
unsigned char *quant_intra_matrix;
unsigned char *quant_inter_matrix;
int par;
int par_width;
int par_height;

int fincr;
int vop_flags;
int motion;
xvid_image_t input;
int type;
int quant;
int bframe_threshold;
void *bitstream;
int length;
int out_flags;
} id_enc_frame_t; xv
在xvid_enc_frame_t中,各个成员的含义如下所示:
􀁺 version,前面已多次说明,应设为当前所用的 XviD 版本;
􀁺 vol_flags,包含vol标志位,vol_flags是一个输入参数。xvid支持的标志位如下:
#define XVID_VOL_MPEGQUANT(1<<0)
#define XVID_VOL_EXTRASTATS(1<<1)
#define X RTERPEL (1<<2)
#defin
e XVID_VOL_GMC (1<<3)
#define XVID_VOL_REDUCED_ENABLE(1<<4)

#define XVID_VOL_INTERLACING(1<<5)
􀁺 quant_intra_matrix,是一个可选输入参数,可以将其指向一个自定义的帧内(intra)
帧间(inter)
个可选输入参数,用于指定像素幅型比,其取值应该是几个标准的像
一个可选输入参数,用于指定像素幅型比的宽度;
于 VOP 的标志位。允许的标志位定
量化矩阵;
􀁺 quant_inter_matrix,是一个可选输入参数,可以将其指向一个自定义的
量化矩阵; 􀁺 par,是一
素幅型比宏定义中的一个(XVID_PAR_xxx); 􀁺 par_width,是
􀁺 par_height,是一个可选输入参数,用于指定像素幅型比的高度;
􀁺 fincr,是一个可选输入参数,指定帧率增量,只适用于可变帧率的情形; 􀁺vop_flags,是一个输入参数,其中保存着基
义如下所示:


#define EBUG (1<< 0)
#defin V
e XID_VOP_HALFPEL (1<< 1)
#defin V
e XID_VOP_INTER4V (1<< 2)
#define XVID_VOP_TRELLISQUANT (1<<3)
#define XVID_VOP_CHROMAOPT (1<<4)
#define XVID_VOP_CARTOON (1<<5)
#define XVID_VOP_GREYSCALE (1<<6)
#define XVID_VOP_HQACPRED (1<<7)
#define XVID_VOP_MODEDECISION_RD (1<<8)
#define XVID_VOP_FAST_MODEDECISION_RD(1<<12)
#define XVID_VOP_RD_BVOP(1<<13)
#define XVID_VOP_TOPFIELDFIRST (1<<9) #define XVID_VOP_ALTERNATESCAN(1<<10)
#define XVID_VOP_REDUCED(1<<11)

􀁺 motion,是一个输入参数,其中保存着用于运动估计的标志位。允许的标志位定
义如下:


#define XVID_ME_ADVANCEDDIAMOND16(1<< 0) #defineXVID_ME_ADVANCEDDIAMOND8 (1<<1)
#defin
e XVID_ME_USESQUARES16 (1<< 2) rchpattern
#define XVID_ME_USESQUARES8 (1<<3)

#define XVID_ME_HALFPELREFINE16 (1<<4)
#define XVID_ME_HALFPELREFINE8 (1<<6)
#define XVID_ME_QUARTERPELREFINE16(1<< 7)
#define XVID_ME_QUARTERPELREFINE8(1<< 8)
#define XVID_ME_GME_REFINE (1<<9)
#define XVID_ME_EXTSEARCH16(1<<10)
#define XVID_ME_EXTSEARCH8(1<<11)
#define XVID_ME_CHROMA_PVOP(1<<12)
#define XVID_ME_CHROMA_BVOP(1<<13)
#define XVID_ME_FASTREFINE16(1<<25)
#define XVID_ME_FASTREFINE8(1<<29)

#define XVID_ME_HALFPELREFINE16_RD(1<<14)
#define XVID_ME_HALFPELREFINE8_RD(1<<15)
#define XVID_ME_QUARTERPELREFINE16_RD(1<<16)
#define XVID_ME_QUARTERPELREFINE8_RD(1<<17)
#define XVID_ME_EXTSEARCH_RD(1<<18)
#define XVID_ME_CHECKPREDICTION_RD(1<<19)

#define XVID_ME_DETECT_STATIC_MOTION(1<<24) #defineXVID_ME_SKIP_DELTASEARCH (1<<26)#define XVID_ME_FAST_MODEINTERPOLATE(1<<27) #defineXVID_ME_BFRAME_EARLYSTOP(1<<28)
#define XVID_ME_UNRESTRICTED16(1<<20) #define XVID_ME_OVERLAPPING16(1<<21)
#define XVID_ME_UNRESTRICTED8(1<<22)
#define XVID_ME_OVERLAPPING8(1<<23)
􀁺 input,是一个xvid_image_t类型的输入参数,代表着输入流,其中不仅指定了输入流的输入
数据,也指定了输入流采用的色场空间; 􀁺 type,是一个可选的输入参数,用于指定编码的类型,通常可以指定为
XVID_TYPE_AUTO;
nt,是一个输入参数,表示帧量化器,如果取值小于等于 0,则自动选择(码
bitstream,是一个可选输入参数,指向编码后的输出缓冲区;
长度,单位为字节;
当执行编码操作时,xvid_encore()函数的 param2 参数可以指向一个 xvid_enc_stats_t 类
型的结构体。xvid_enc_stats_t 类型定义如下:
􀁺 qua
率控制);
􀁺 bframe_threshold,(作用未知); 􀁺
􀁺 length,是一个可选输入参数,表明输出缓冲区(即bitstream所指向的空间)的
􀁺 out_flags,是一个输出参数,包含输出码流的相关标志。
-----------
typedef stru
ct {
in er
t vsion;
int type;
int quant; int vol_flags;
int vop_flags;
int length;
int hlength; int kblks;
int mblks;
int ublks;
int sse_y;
int sse_u;
int sse_v;
} id_enc_stats_t; xv
xvid_enc_stats_t可以用作xvid_encore()函数的 既 param2 参 数 , 也 可 以 包 含在
id vid_enc_stats_t 用作 xvid_encore()
数的 param2 参数的情形。在此种情况下,除了 version 外,xvid_enc_stats_t 中的所有成员
回编码操作执行的状态。各个成员的简单说明如下:


􀁺 hlength,是一个输出参数,编码后的头部长度,单位为字节;
一 数,帧间编码压缩的宏块数目;
一个输出参数,标记为不编码的宏块数目;
示例代码:
xv_plg_data_t类型中(插件数据)。下面的讨论只针对x

都是输出参数,用来返
􀁺 type,是一个输出参数,表明编码类型
􀁺 quant,是个输出参数,表明采用的量化器;
􀁺 vol_flags,是一个输出参数,表明为编码器指定的vol标志;
􀁺 vop_flags,是一个输出参数,表明为编码器指定的vop标志;
􀁺 length,是一个输出参数,编码的一帧的长度;
􀁺 kblks,是一个输出参数,帧内编码压缩的宏块数目;
􀁺 mblks,是个输出参数,是一个输出参
􀁺 ublks,是
􀁺 sse_y,是一个输出参数,Y平面上的sse值(SSE表示总方误差); 􀁺 sse_u,是一个输出参数,U平面上的sse值; 􀁺sse_v,是一个输出参数,V平面上的sse值。
#defin
e CIF_ROW 352
#defin
e CIF_COL 288
#define CSP XVID_CSP_I420
#defin B
e PP 1
unsigned char
image[CIF_ROW * CIF_COL * BPP];
unsigned [1024]; char bitstream
xvid_e
nc_frame_t xvid_enc_frame;
xvid_enc_st id_enc_stats;
ats_t xv

memset(&xvid_enc_frame, 0,sizeof(xvid_enc_frame_t));
xvid_enc_frame.version = XVID_VERSION;
mems x
et(&vid_enc_stats, 0,sizeof(xvid_enc_stats_t));
xvid sion = XVID_VERSION;
_enc_stats.ver

xvid_enc_frame.input.plane[0] = image;
xvid_enc_frame.input.csp = CSP;
xvid_enc_frame.input.stride[0] = CIF_ROW;

xvid_enc_frame.vol_flags = 0;
xvid_enc_frame.vop_flags = 0;

xvid_enc_frame.motion = 0;

xvid_enc_frame.type = XVID_TYPE_AUTO;

xvid_enc_frame.quant = 0;
xvid_encore(enc_handle, XVID_ENC_ENCODE,&xvid_enc_frame,
&xvid_enc_stats);
在上述示例代码中,image中保存的是输入图像;bitstream 用于保存编码后的码流;大
分 xvid_enc_frame 中的成员都采用默认设置,实际上的设置工作集中在设定输入图像和输
,调用 xvid_encore()函数,其中第一个参数 enc_handle
实例句柄,编码状态通过 xvid_enc_stats 返回。
.3 销毁 xvid 编码实例
做法如下:将 xvid_encore()函数的第一个参数 handle 设
opt 设置为 XVID_ENC_DESTROY;参数
实例之后,不能再用它进行编码。
示例代码:

出流上。设置好xvid_enc_frame之后
是创建XviD编码实例后返回的
9
销毁XviD编码实例非常简单。

创建XviD编码实例后得到的句柄;第二个参数
param1和param2都设为NULL。销毁XviD编码
xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL);
上述代码中的第一个参数 enc_handle 是创建 XviD 编码实例之后得到的句柄。
有看到 的官方文档。显然,接口清晰易懂并不是不给出官方文档的理由。
程中,可以插入相关的插件完成一些额外的操作,比
将编码前后的码流转储到文件中以便于调试或者分析。
这些插件函数和前面说明的三个核心函数具有相同的接口形式。XviD 本身定义了六个标准
的插
10 总结
XviD的三个核心API接口都采用了同样的参数形式(只是形式上相同),不可否认,XviD采用这样的处理方式,使得应用程序接口非常清晰,非常便于使用。这为通过XviD编写应用程序的开发人员提供了不少方便。但是一个比较不好的地方是:到目前为止,还没XviD
另外,在通过XviD进行编码的过如通过插件对编码情况进行统计或者
件函数,用于计算psnr(Peek Signal NoiseRate,峰值信噪比,一种通用的衡量视频质量的方法)以及进行码率控制等工作。在本文中没有对这些插件函数进行说明,本文档的下一版本中也许会增加对这些插件函数的说明。

  

爱华网本文地址 » http://www.413yy.cn/a/25101014/229916.html

更多阅读

电影 《肖申克的救赎》精彩影评 肖申克的救赎专业影评

【电影简介】故事发生在1947年,银行家安迪被指控因为妻子有婚外情,酒醉后本想用枪杀了妻子和她的情人,但是他没有下手,巧合的是那晚刚好有人枪杀了他妻子和她情人,他被指控谋杀罪,被判无期徒刑,这意味着他将在肖申克监狱中渡过余生。

肖申克救赎影评 肖申克的救赎影评论文

酒醉后误被指控用枪杀死了她和她的情人,安迪被判无期徙刑,这意味着他将在肖申克监狱中渡过余生。 瑞德1927年因谋杀罪被判无期徙刑,数次假释都未获成功。他现在已经成为肖申克监狱中的“权威人物”,只要你付得起钱,他几乎有办法搞到任何

肖申克的救赎 人生必看的10部电影

添加义项这是一个多义词,请在下列义项中选择浏览1.由弗兰克·达拉邦特导演的经典影片2.斯蒂芬·金《不同的季节》里收录的小说 1.由弗兰克·达拉邦特导演的经典影片编辑本义项肖申克的救赎求助编辑百科名片 《肖申克的救赎》美国海报《

声明:《xvid的中文简介 肖申克的救赎中文简介》为网友怪人叔叔分享!如侵犯到您的合法权益请联系我们删除