Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2224863
  • 博文数量: 668
  • 博客积分: 10016
  • 博客等级: 上将
  • 技术积分: 8588
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-29 19:22
文章分类

全部博文(668)

文章存档

2011年(1)

2010年(2)

2009年(273)

2008年(392)

分类:

2009-08-14 10:54:38

2)解码一帧图像

MPEG-4 SP视频编码算法中,编码帧类型是I帧和P帧。码流头结构中有帧类型信息、量化信息、fcode值、intra_dc_threshold等。XviD提供的MPEG-4视频解码在解码到VOL时会返回应用程序,为了应用层更直接地得到解码图像,现在修改为只有解析并解码了图像帧数据时才返回应用程序。

解码器解码图像decoder_decode()的流程如图14-7所示。根据该流程,代码实现如下。

int decoder_decode(DECODER * dec, xvid_dec_frame_t *
frame, xvid_dec_stats_t * stats)
{
uint32_t rounding;                  /*图像饱和
类型,在插值时四舍五入的饱和大小*/
uint32_t reduced_resolution;
uint32_t quant = 2;                /*默认的量化步长初始化*/
uint32_t fcode_forward;            /*运动估计中搜索窗口的大小,前向*/
uint32_t fcode_backward;           /*运动估计中搜索窗口的大小,后向*/
uint32_t intra_dc_threshold;       /*Intra块的直流DC阈值*/
WARPPOINTS gmc_warp;
int coding_type;                  /*当前编码帧类型*/
if (frame->length < 0)   return
XVID_ERR_END;   /*检测输入码流长度的合法性*/
BitstreamInit(&g_bs, frame->bitstream,
frame->length);  /*初始化码流结构体*/
/*解析视频码流头结构、信息*/
repeat:
coding_type = BitstreamReadHeaders(&g_bs, dec,
&rounding, &reduced_resolution,
&quant, &fcode_forward, &fcode_backward,
&intra_dc_threshold, &gmc_warp);
if (coding_type == -1) {    /* 继续解析头信息,直到解析到图像数据 */
goto repeat;
}
if (coding_type == -2 || coding_type == -3) {/*
当前是VOL头或需要修改图像空间大小 */
if (coding_type == -3)  decoder_resize(dec);
if (stats)  goto repeat;         /* 继续解析头信息,直到解析到图像数据 */
}
/*确保解码的第一帧是I帧,如果不是I帧则继续解析后续码流*/
if(dec->frames == 0 && coding_type != I_VOP)  goto repeat;
if (coding_type != B_VOP)  {
switch(coding_type) {
case I_VOP :         /*I帧解码*/
decoder_iframe(dec, &g_bs, reduced_resolution,
quant, intra_dc_ threshold);
break;
case P_VOP :       /*P帧解码*/
decoder_pframe(dec, &g_bs, rounding, reduced_resolution, quant,
fcode_forward, intra_dc_threshold, NULL);
break;
case S_VOP :       /*S帧解码*/
 decoder_pframe(dec, &g_bs, rounding, reduced_resolution, quant,
fcode_forward, intra_dc_threshold, &gmc_warp);
break;
}
dec_image_swap(&dec->refn[0], &dec->refn[1]);
/*交换两个参考帧的指针*/
dec_image_swap(&dec->cur, &dec->refn[0]);     
/*交换当前图像和参考帧的指针*/
dec->last_reduced_resolution = reduced_resolution;
dec->last_coding_type = coding_type;           /*保存当前帧类型*/
dec->frames++;                                 /*解码帧计数器*/
}
done :
return (BitstreamPos(&g_bs) + 7) / 8;        
/*已解码的码流,单位B*/
}
 
图14-7  decoder_decode()流程图

BitstreamReadHeaders()函数根据MPEG-4标准码流协议解析编码信息。如果用户在编码端对VOL、VOP的写头信息作了修改,则在解码端的该函数中,要一一对应起来。如为了加密需要,就可以在编码端的写VOL/VOP信息作特定的修改。SP档级的MPEG-4视频帧有I帧和P帧,本章对I帧和P帧的解码过程做剖析。I帧解码由decoder_iframe函数、P帧解码由decoder_pframe函数完成。

① decoder_iframe

解码是其编码的逆工作,获得mcbpc、acpred_flag、cbpy等,将运动向量初始化为0。

static void decoder_iframe(DECODER * dec, 
Bitstream * bs, int quant, int intra_dc_threshold)
{
uint32_t x, y;
const uint32_t mb_width = dec->mb_width;
const uint32_t mb_height = dec->mb_height;
/*循环解码所有宏块*/
for (y = 0; y < mb_height; y++)
for (x = 0; x < mb_width; x++) {
MACROBLOCK *mb;
uint32_t mcbpc, cbpc, acpred_flag, cbpy, cbp;
mb = &dec->mbs[y * dec->mb_width + x];
mcbpc = get_mcbpc_intra(bs);  /*解码得到mcbpc*/
mb->mode = mcbpc & 7;          /*宏块编码模式*/
cbpc = (mcbpc >> 4);            /*组合得到cbpc*/
acpred_flag = BitstreamGetBit(bs); /*AC预测方向*/
cbpy = get_cbpy(bs, 1);          /*解码得到cbpy*/
cbp = (cbpy << 2) | cbpc;          /*组合得到cbp*/
mb->quant = quant;
mb->mvs[0].x = mb->mvs[0].y = mb->mvs[1].x = mb->mvs[1].y =
mb->mvs[2].x = mb->mvs[2].y = mb->mvs[3].x = mb->mvs[3].y =0;
decoder_mbintra(dec, mb, x, y, acpred_flag,
cbp, bs, quant, intra_dc_ threshold, 0);
}
}
上述代码实现I帧图像的解码,首先从码流中获取mcbpc、AC预测方向、cbpy,将运动量清零,调用核心函数decoder_mbintra进行解码,以宏块为单位循环处理。
阅读(708) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~