转自:http://www.cnblogs.com/TaigaCon/p/3551001.html

本文参考自http://wenku.baidu.com/link?url=ZPF0iSKzwLQg_8K02pnnd_- Zd6ISnsOGWsGYb98ucLkELZO4nOv-X-v2GKLzI3r0VMN4R0TC8cM6AQy7xOjDZ4AQJBYWT_-VOYlxQFCvaj_

视频编码顺序与视频的播放顺序,并不完全相同

视频编码时,如果采用了B帧编码,由于B帧很多时候都是双向预测得来的,这时会先编码B帧的后向预测图像(P帧),然后再进行B帧编码,

因此会把视频原来的播放顺序打乱,以新的编码顺序输出码流

而在解码断接收到码流后,需要把顺序还原成原本的播放顺序,以输出正确的视频

在编解码中,视频的播放顺序序号叫做POC(picture order count)

POC有两种类型:

1、把POC的低位编进码流内        (pic_order_cnt_type = 0)

2、依赖frame_num求解POC      (pic_order_cnt_type = 1)

对于第一种类型,POC的低位pic_order_cnt_lsb可以从码流内得到,而POC的高位PicOrderCntMsb则要求解码器自行计数

计数方式依赖于前一编码帧(PrevPicOrderCntMsb与PrevPicOrderCntLsb),代码如下

// Calculate the MSBs of current picture
if( img->pic_order_cnt_lsb < img->PrevPicOrderCntLsb &&
( img->PrevPicOrderCntLsb - img->pic_order_cnt_lsb ) >= ( MaxPicOrderCntLsb / ) )
img->PicOrderCntMsb = img->PrevPicOrderCntMsb + MaxPicOrderCntLsb;
else if ( img->pic_order_cnt_lsb > img->PrevPicOrderCntLsb &&
( img->pic_order_cnt_lsb - img->PrevPicOrderCntLsb ) > ( MaxPicOrderCntLsb / ) )
img->PicOrderCntMsb = img->PrevPicOrderCntMsb - MaxPicOrderCntLsb;
else
img->PicOrderCntMsb = img->PrevPicOrderCntMsb;

可以对比下图分析

如果序列内出现了mmco==5,
如果是场模式,并且出现在底场,PrevPicOrderCntMsb与PrevPicOrderCntLsb都要清零
如果出现在顶场,只需要清零PrevPicOrderCntMsb
如果mmco==5出现在帧模式,也是只清零PrevPicOrderCntMsb

另外如果出现了IDR,那么PrevPicOrderCntMsb与PrevPicOrderCntLsb都要清零

代码如下

    // 1st
if(img->idr_flag)
{
img->PrevPicOrderCntMsb = ;
img->PrevPicOrderCntLsb = ;
}
else
{
if (img->last_has_mmco_5)
{
if (img->last_pic_bottom_field)
{
img->PrevPicOrderCntMsb = ;
img->PrevPicOrderCntLsb = ;
}
else
{
img->PrevPicOrderCntMsb = ;
img->PrevPicOrderCntLsb = img->toppoc;
}
}
}

可以对比下图分析

对于第二种类型,是通过frame_num来计算得出POC
在解析步骤之前通过下图来分析一下帧序列结构

该序列分3个循环,

除开I帧外,每个循环有相同的结构其中frame_num是由解码器计数的,这里不在讨论范围内,直接拿来用,

另外有两个参数是从码流内(sps)获取:

num_ref_frames_in_pic_order_cnt_cycle    除I帧外,每个循环内有多少个参考帧(P帧)

offset_for_ref_frame[i]                             一个循环内参考帧之间的间隔

假设我们需要计算POC为42的B帧的poc值

有如下步骤:

1、判断IDR,mmco==5

2、根据frame_num获取AbsFrameNum,如果是B帧则需要减一

3、计算POC,其中又分为以下几个步骤:

  计算一个循环的长度,即offset_for_ref_frame[i]所有元素加起来,4+6+8 = 18

  计算AbsFrameNum所在循环的位置(9-1)/ 3 = 2 ,即第三个循环

  计算AbsFrameNum在循环内的偏移(9-1)%3 = 2,偏移2,即需要加上offset_for_ref_frame[0],offset_for_ref_frame[1]两个

  计算前两个循环的长度 2x18 = 36

  前两个循环长度加上偏移长度 36 + 4 + 6 = 46

  由于是B帧,最后要加上offset_for_non_ref_pic,offset_for_non_ref_pic = -2*(连续B帧的数量),而这里由于有多个连续B帧,所以取平均值2,即 offset_for_non_ref_pic = -2*2 = -4

  最后加上delta_pic_order_cnt[0] = 0,delta_pic_order_cnt[1] = 0 , 即POC = 42

代码如下:

  case : // POC MODE 1
// 1st
if(img->idr_flag)
{
img->FrameNumOffset=; // first pix of IDRGOP,
img->delta_pic_order_cnt[]=; //ignore first delta
if(img->frame_num) error("frame_num != 0 in idr pix", -);
}
else
{
if (img->last_has_mmco_5)
{
img->PreviousFrameNumOffset = ;
img->PreviousFrameNum = ;
}
if (img->frame_num<img->PreviousFrameNum)
{ //not first pix of IDRGOP
img->FrameNumOffset = img->PreviousFrameNumOffset + img->MaxFrameNum;
}
else
{
img->FrameNumOffset = img->PreviousFrameNumOffset;
}
} // 2nd
if(active_sps->num_ref_frames_in_pic_order_cnt_cycle)
img->AbsFrameNum = img->FrameNumOffset+img->frame_num;
else
img->AbsFrameNum=;
if(img->disposable_flag && img->AbsFrameNum>)
img->AbsFrameNum--; // 3rd
img->ExpectedDeltaPerPicOrderCntCycle=; if(active_sps->num_ref_frames_in_pic_order_cnt_cycle)
for(i=;i<(int) active_sps->num_ref_frames_in_pic_order_cnt_cycle;i++)
img->ExpectedDeltaPerPicOrderCntCycle += active_sps->offset_for_ref_frame[i]; if(img->AbsFrameNum)
{
img->PicOrderCntCycleCnt = (img->AbsFrameNum-)/active_sps->num_ref_frames_in_pic_order_cnt_cycle;
img->FrameNumInPicOrderCntCycle = (img->AbsFrameNum-)%active_sps->num_ref_frames_in_pic_order_cnt_cycle;
img->ExpectedPicOrderCnt = img->PicOrderCntCycleCnt*img->ExpectedDeltaPerPicOrderCntCycle;
for(i=;i<=(int)img->FrameNumInPicOrderCntCycle;i++)
img->ExpectedPicOrderCnt += active_sps->offset_for_ref_frame[i];
}
else
img->ExpectedPicOrderCnt=; if(img->disposable_flag)
img->ExpectedPicOrderCnt += active_sps->offset_for_non_ref_pic; if(img->field_pic_flag==)
{ //frame pix
img->toppoc = img->ExpectedPicOrderCnt + img->delta_pic_order_cnt[];
img->bottompoc = img->toppoc + active_sps->offset_for_top_to_bottom_field + img->delta_pic_order_cnt[];
img->ThisPOC = img->framepoc = (img->toppoc < img->bottompoc)? img->toppoc : img->bottompoc; // POC200301
}
else if (img->bottom_field_flag==)
{ //top field
img->ThisPOC = img->toppoc = img->ExpectedPicOrderCnt + img->delta_pic_order_cnt[];
}
else
{ //bottom field
img->ThisPOC = img->bottompoc = img->ExpectedPicOrderCnt + active_sps->offset_for_top_to_bottom_field + img->delta_pic_order_cnt[];
}
img->framepoc=img->ThisPOC; img->PreviousFrameNum=img->frame_num;
img->PreviousFrameNumOffset=img->FrameNumOffset; break;

计算POC还有一种类型,即没有B帧的,这种最简单,直接通过frame_num推导,

但是应该注意,在这种情况下不存在连续 的非参考图象(注释),且解码输出的顺序和显示输出顺序一致(注释),意思就是说不出现B帧,但可以出现非参考的P场,这也是为什么当 nal_ref_idc=0的时候

tempPicOrderCnt = 2 * ( FrameNumOffset + frame_num ) –1的情况。这里保证了参考场的POC始终为偶数,并且大于同帧的另外一个场

代码如下

  case : // POC MODE 2
if(img->idr_flag) // IDR picture
{
img->FrameNumOffset=; // first pix of IDRGOP,
img->ThisPOC = img->framepoc = img->toppoc = img->bottompoc = ;
if(img->frame_num) error("frame_num != 0 in idr pix", -);
}
else
{
if (img->last_has_mmco_5)
{
img->PreviousFrameNum = ;
img->PreviousFrameNumOffset = ;
}
if (img->frame_num<img->PreviousFrameNum)
img->FrameNumOffset = img->PreviousFrameNumOffset + img->MaxFrameNum;
else
img->FrameNumOffset = img->PreviousFrameNumOffset; img->AbsFrameNum = img->FrameNumOffset+img->frame_num;
if(img->disposable_flag)
img->ThisPOC = (*img->AbsFrameNum - );
else
img->ThisPOC = (*img->AbsFrameNum); if (img->field_pic_flag==)
img->toppoc = img->bottompoc = img->framepoc = img->ThisPOC;
else if (img->bottom_field_flag==)
img->toppoc = img->framepoc = img->ThisPOC;
else img->bottompoc = img->framepoc = img->ThisPOC;
} if (!img->disposable_flag)
img->PreviousFrameNum=img->frame_num;
img->PreviousFrameNumOffset=img->FrameNumOffset;
break;

h.264的POC计算(转载)的更多相关文章

  1. h.264的POC计算

    本文参考自http://wenku.baidu.com/link?url=ZPF0iSKzwLQg_8K02pnnd_-Zd6ISnsOGWsGYb98ucLkELZO4nOv-X-v2GKLzI3r ...

  2. h.264语法结构分析

    NAL Unit Stream Network Abstraction Layer,简称NAL. h.264把原始的yuv文件编码成码流文件,生成的码流文件就是NAL单元流(NAL unit Stre ...

  3. h.264参考图像列表、解码图像缓存

    1.参考图像列表(reference picture list) 一般来说,h.264会把需要编码的图像分为三种类型:I.P.B,其中的B.P类型的图像由于采用了帧间编码的这种编码方式,而帧间编码又是 ...

  4. MPEG-4与H.264的区别 , 编码 以及 应用

    MPEG4是适用于监控领域的压缩技术 MPEG4于1998年11月公布,原预计1999 年1月投入使用的国际标准MPEG4不仅是针对一定比特率下的视频.音频编码,更加注重多媒体系统的交互性和灵活性.M ...

  5. H.264(MPEG-4 AVC)级别(Level)、DPB 与 MaxDpbMbs 详解(转载)

    转自:http://www.cnblogs.com/zyl910/archive/2011/12/08/h264_level.html 对于H.264(MPEG-4 AVC)而言,级别(Level)是 ...

  6. (转载)H.264码流的RTP封包说明

    H.264的NALU,RTP封包说明(转自牛人) 2010-06-30 16:28 H.264 RTP payload 格式 H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) ...

  7. H.264学习笔记之一(层次结构,NAL,SPS)

    一 H.264句法 1.1元素分层结构 H.264编码器输出的Bit流中,每个Bit都隶属于某个句法元素.句法元素被组织成有层次的结构,分别描述各个层次的信息. 图1 H.264分层结构由五层组成,分 ...

  8. h.264直接预测

    直接预测是B帧上一种独有的预测方式,其中直接预测又分为两种模式: 时域直接模式(temporal direct).空域直接模式(spatial direct). 在分析这两种模式之前,有一个前提概念需 ...

  9. h.264加权预测

    帧间运动是基于视频亮度(luma)不发生改变的一个假设,而在视频序列中经常能遇到亮度变化的场景,比如淡入淡出.镜头光圈调整.整体或局部光源改变等,在这些场景中,简单帧间运动补偿的效果可想而知(实际编码 ...

随机推荐

  1. 一种排序(nyoj8)(简单排序)

    一种排序 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描写叙述 如今有非常多长方形.每个长方形都有一个编号,这个编号能够反复.还知道这个长方形的宽和长,编号.长.宽都是整数 ...

  2. Linux下的ELF可执行文件的格式解析 (转)

    LInux命令只是和Kernel一起被编译进操作系统的存在于FS的ELF格式二进制文件,或者权限足够的脚本,或者一个软链 ELF(Executable and Linking Format)是一种对象 ...

  3. 2014MadCon厦门分享会-笔记(下)

    32 <如何与百度互动,不知道这些就不要做SEO了>百度站长平台资深产品运营师 曹丽丽(飞鸟) 33 注意百度站长平台的提醒.如果你不留电话,不留其他联系方式,出问题了,百度怎么提醒你呢? ...

  4. 【hdu】Mayor&#39;s posters(线段树区间问题)

    须要离散化处理,线段树的区间改动问题. 须要注意的就是离散化的时候,由于给的数字是一段单位长度,所以须要特殊处理(由于线段的覆盖和点的覆盖是不一样的) 比方:(1,10)(1,4) (6,10) 离散 ...

  5. 移动GPU渲染原理的流派——IMR、TBR及TBDR

    移动GPU渲染原理的流派--IMR.TBR及TBDR 移动GPU相对桌面级的GPU仅仅能算是未长大的小孩子,尽管小孩子在某些场合也能比成人更有优势(比方杂技.柔术之类的表演).但在力量上还是有先天的区 ...

  6. centos 7.xx 安装LAMP环境

    一.安装Apache 1.安装yum -y install httpd2.开启apache服务systemctl start httpd.service3.设置apache服务开机启动systemct ...

  7. mysql order by的一些技巧

    1. 只按日期排序,忽略年份> select date, description from table_name order by month(date),dayofmonth(date);注意 ...

  8. Arcgis Engine(ae)接口详解(7):地图(map)操作

    IMap map = null; //跟map同一层次的activeView对象,他们都是“地图”的对象,map管理地图内容,activeView管理显示内容 IActiveView activeVi ...

  9. &lt;十二&gt;读&lt;&lt;大话设计模式&gt;&gt;之状态模式

    对于状态模式,<<大话设计模式>>是以人从上班到下班到加班的状态来展开讲述的.状态模式事实上就是某一个对象在某个过程或者时间的一个状态记录,可是这个状态的顺序不能发生变化.在程 ...

  10. delphi中的HOOK [转贴]

    按事件分类,有如下的几种常用类型的钩子: 1)键盘钩子可以监视各种键盘消息. 2)鼠标钩子可以监视各种鼠标消息. 3)外壳钩子可以监视各种Shell事件消息. 4)日志钩子可以记录从系统消息队列中取出 ...