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

全部博文(668)

文章存档

2011年(1)

2010年(2)

2009年(273)

2008年(392)

分类:

2009-08-14 10:45:11

上述程序是编码器的所有功能函数,创建编码器实例、使用编码器编码图像、销毁编码器。在应用层中,编码器可以有多个,这就通过编码句柄handle来控制不同的编码器。创建编码器enc_create、销毁编码器enc_destroy均只调用一次,循环调用enc_encode编码图像帧。

下面就分别详细介绍这3个函数的功能和实现过程。

1)XviD创建编码器

创建MPEG-4编码器,首先创建编码器实例句柄,然后在该句柄下执行对编码器的参数配置、图像参数获取和空间申请等工作,这样在多路编码时,可以通过句柄来控制每一路的编码。

函数enc_create()流程如图14-2所示。

 
图14-2  enc_create()流程图
根据该流程,具体代码如下。
int  enc_create(xvid_enc_create_t * create)
{
Encoder *pEnc;
/* 创建编码器指针,注意内存对齐*/
pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE);
if (pEnc == NULL)  return XVID_ERR_MEMORY;
memset(pEnc, 0, sizeof(Encoder));            
/*初始化编码器句柄,所有指针清空*/
pEnc->mbParam.profile = create->profile;
pEnc->mbParam.global_flags = create->global; 
/*编码器全局参数标志 */
pEnc->mbParam.width = create->width;      /*视频图像的宽、高 */
pEnc->mbParam.height = create->height;
pEnc->mbParam.mb_width = (pEnc->mbParam.
width + 15) / 16;    /*图像的宏块宽度*/
pEnc->mbParam.mb_height = (pEnc->mbParam.
height + 15) / 16;/*图像的宏块高度*/
/*扩展后的视频图像大小 */
pEnc->mbParam.edged_width = 16 * pEnc->
mbParam.mb_width + 2 * EDGE_SIZE;
pEnc->mbParam.edged_height = 16 * pEnc->
mbParam.mb_height + 2 * EDGE_SIZE;
pEnc->mbParam.fincr = MAX(create->fincr,
0);               /*帧率递增模式*/
pEnc->mbParam.fbase = create->fincr
<= 0 ? 25 : create->fbase; /*帧率大小*/
pEnc->mbParam.frame_drop_ratio = MAX
(create->frame_drop_ratio, 0);/*丢帧率*/
/*最大关键帧间隔,即I帧间的最大间隔,如果没有设置则默认250*/
pEnc->mbParam.iMaxKeyInterval = create->max_
key_interval <= 0 ? (10 * (int)pEnc->mbParam.fbase) /
(int)pEnc->mbParam.fincr : create->max_key_interval;
/*分配当前编码帧和参考帧空间 */
pEnc->current = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
pEnc->reference = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
if (pEnc->current == NULL || pEnc->reference == NULL)
goto xvid_err_memory1;
/* 为当前帧和参考帧的所有宏块结构分配空间 */
pEnc->current->mbs =
xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *
pEnc->mbParam.mb_height, CACHE_LINE);
pEnc->reference->mbs =
xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *
pEnc->mbParam.mb_height, CACHE_LINE);
if (pEnc->current->mbs == NULL || pEnc->reference->mbs == NULL)
goto xvid_err_memory2;
/*图像指针清空*/
image_null(&pEnc->current->image);
image_null(&pEnc->reference->image);
image_null(&pEnc->vInterH);
image_null(&pEnc->vInterV);
image_null(&pEnc->vInterHV);
/* 创建当前视频帧图像空间 */
if (image_create(&pEnc->current->image, pEnc->mbParam.
edged_width,pEnc->mbParam. edged_height) < 0)
goto xvid_err_memory3;
/* 创建参考视频帧图像空间 */
if(image_create(&pEnc->reference->image,pEnc->mbParam.
edged_width,pEnc-> mbParam.edged_height)< 0)
goto xvid_err_memory3;
/* 创建vInterH参考帧图像空间 */
if (image_create(&pEnc->vInterH, pEnc->mbParam.
edged_width, pEnc->mbParam. edged_height) < 0)
goto xvid_err_memory3;
/* 创建vInterV参考帧图像空间 */
if (image_create(&pEnc->vInterV, pEnc->mbParam.
edged_width, pEnc->mbParam. edged_height) < 0)
goto xvid_err_memory3;
/* 创建vInterHV参考帧图像空间 */
if (image_create(&pEnc->vInterHV, pEnc->mbParam.
edged_width, pEnc->mbParam. edged_height) < 0)
goto xvid_err_memory3;
/* 初始化B帧编码序列参数*/
pEnc->queue_head = 0;
pEnc->queue_tail = 0;
pEnc->queue_size = 0;
pEnc->queue = xvid_malloc((1) * sizeof(QUEUEINFO),CACHE_LINE);
/* 图像编码序列  */
if(image_create(&pEnc->queue[0].image,pEnc->mbParam.
edged_width,pEnc-> mbParam.edged_height) < 0)
goto xvid_err_memory5;
/*时间戳清零*/
pEnc->mbParam.m_stamp = 0;
pEnc->current->stamp = 0;
pEnc->reference->stamp = 0;
pEnc->iFrameNum = 0;            /*编码图像帧数计数器清零*/
create->handle = (void *) pEnc; /*返回编码器的句柄 */
return 0;                          /* ok */
/*如果出错的话,释放以前分配的内存*/
xvid_err_memory5:
image_destroy(&pEnc->queue[0].image,pEnc->mbParam.
edged_width,pEnc->mbParam.edged_height);
xvid_free(pEnc->queue);
/* 释放图像空间*/
image_destroy(&pEnc->current->image, pEnc->mbParam.
edged_width,pEnc->mbParam. edged_height);
image_destroy(&pEnc->reference->image, pEnc->mbParam.
edged_width,pEnc->mbParam. edged_height);
image_destroy(&pEnc->vInterH, pEnc->mbParam.
edged_width,pEnc->mbParam.edged_ height);
image_destroy(&pEnc->vInterV, pEnc->mbParam.
edged_width,pEnc->mbParam.edged_ height);
image_destroy(&pEnc->vInterHV, pEnc->mbParam.
edged_width,pEnc->mbParam.edged_ height);
xvid_err_memory2:
/* 释放当前帧和参考帧的mbs宏块内存*/
xvid_free(pEnc->current->mbs);
xvid_free(pEnc->reference->mbs);
xvid_err_memory1:
/* 释放当前帧和参考帧的内存*/
xvid_free(pEnc->current);
xvid_free(pEnc->reference);
/* 释放编码器*/
xvid_free(pEnc);
xvid_err_memory3:
create->handle = NULL;
return XVID_ERR_MEMORY;
}

上述代码完成编码器的创建、编码参数的初始化、工作空间的申请等。编码器的初始化函数可以不用过多地考虑优化,因为这个函数只调用一次,不像编码函数多次循环地调用。

阅读(701) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~