JM8.6解码——帧类型判别

  h264裸码流,根据nalu_header可以知道类型,例如该帧是I帧,P帧/B帧。

  例如,常见的0x65代表I帧,0x41代表非关键帧,即P帧或B帧,但是只根据nalu_header是无法区分P帧和B帧的,还需进入到RBSP内部根据语法含义来做判断。

1. JM实现的判别

 1 int FirstPartOfSliceHeader()
 2 {
 3   Slice *currSlice = img->currentSlice;
 4   int dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER];
 5   DataPartition *partition = &(currSlice->partArr[dP_nr]);
 6   Bitstream *currStream = partition->bitstream;
 7    tmp;
 8 
 9   UsedBits= partition->bitstream->frame_bitoffset; // was hardcoded to 31 for previous start-code. This is better.
10 
11    Get first_mb_in_slice
12   currSlice->start_mb_nr = ue_v ("SH: first_mb_in_slice",currStream);
13 
14   tmp = ue_v (SH: slice_type15   
16   if (tmp>4) tmp -=5;
17 
18   img->type = currSlice->picture_type = (SliceType) tmp;
19 
20   currSlice->pic_parameter_set_id = ue_v (SH: pic_parameter_set_id21   
22   return UsedBits;
23 }
View Code

  如上代码,第二次的ue(无符号哥伦布编码)得出了帧类型,但是还需注意到做差:"if (tmp>4) tmp -=5;",才能得到真正的SliceType:

1 typedef enum {
2     P_SLICE = 03     B_SLICE,1)">4     I_SLICE,1)">5     SP_SLICE,1)">6     SI_SLICE
7 } SliceType;

  例如,一段nalu数据为:0x00 00 01 65 88 80 06 64

  那么,从0x65后的字节0x88开始算起,

  第一个ue得到start_mb_nr,即其值为(2^0 - 1 + 0)= 0,0x88使用了最高位,当前bit_offset=1

  第二个ue得到tmp值,即其值为(2^3 - 1 + 000b)= 7,使用了7bit来计算,当前bit_offset=8,再将tmp-5得到2,那么picture_type为I帧。

  第三个ue得到pps_id值,从0x80的最高位算起,值为(2^0 - 1 + 0)= 0

2. ffmpeg的实现

  实现类似,参考文件h264_slice.c,关键代码如下:

static int h264_slice_header_parse(const H264Context *h,H264SliceContext *sl,1)"> 2                                    const H2645NAL *nal)
 3  4     const SPS *sps;
 5     const PPS *pps;
 6      ret;
 7     unsigned  slice_type,tmp,i;
 8      field_pic_flag,bottom_field_flag;
 9     int first_slice = sl == h->slice_ctx && !h->current_slice;
10      picture_structure;
11 
12     if (first_slice)
13         av_assert0(!h->setup_finished);
14 
15     sl->first_mb_addr = get_ue_golomb_long(&sl->gb);
16 
17     slice_type = get_ue_golomb_31(&sl->18     if (slice_type > 9) {
19         av_log(h->avctx,AV_LOG_ERROR,1)">20                slice type %d too large at %d\n21                slice_type,sl->first_mb_addr);
22          AVERROR_INVALIDDATA;
23     }
24     425         slice_type -= 26         sl->slice_type_fixed = 127     } else
28         sl->slice_type_fixed = 29 
30     slice_type         = ff_h264_golomb_to_pict_type[slice_type];
31     sl->slice_type     = slice_type;
32     sl->slice_type_nos = slice_type & 333 
34     if (nal->type  == H264_NAL_IDR_SLICE &&
35         sl->slice_type_nos != AV_PICTURE_TYPE_I) {
36         av_log(h->avctx,A non-intra slice in an IDR NAL unit.\n);
37         38 39 
40     sl->pps_id = get_ue_golomb(&sl->41 ...
42 }
View Code

  同样也是超过4时,再减去5即得到了帧类型。

3. 小工具实现

  本人曾做了一个小工具,参考核心代码如下:

int GetFrameType(NALU_t * nal)
    bs_t s;
int frame_type =  5 
 6     bs_init(&s,nal->buf+1,nal->len -  7 
if (nal->nal_unit_type == NALU_TYPE_SLICE || nal->nal_unit_type ==  NALU_TYPE_IDR)
 9     {
10         /* i_first_mb */
11         bs_read_ue(&s);
12          picture type 13         frame_type = bs_read_ue(&14         switch(frame_type)
15         {
16         case 0: 5:  P 17             nal->frame_type = FRAME_TYPE_P;
18             break19         1: 6:  B 20             nal->frame_type = FRAME_TYPE_B;
21             3: 8:  SP 23             nal->frame_type =24             25         2: 7:  I 26             nal->frame_type = FRAME_TYPE_I;
27             28         4: 9:  SI 29             nal->frame_type =30             31         default:
32             printf(unknown frame type! nalu_data[%#x,%#x,%#x]\n",nal->buf[0],1)">1],1)">2],1)">]);
33             34         }
35 36     37 38         nal->frame_type = nal->nal_unit_type;
39 40 
41     return 42 }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


一年前写了一个demo,用于生成几种标准的波形,如正弦波、方波、三角波。之前写的只有这几个功能:波形/通道/时长/频率的控制选择,这几天抽了些时间又加了增益控制功能。为了避免东西丢失或意外删除,特上传
wav文件格式作为一种常用的多媒体音频文件格式,其由MS在1991年8月在Windows 3.1上推出,文件扩展名为WAV,是WaveFom的简写。通常存储未压缩的pcm数据,也可存储压缩的pcm数据
mpeg2ts文件格式中有pcr和pts的概念,其代码含义如下: PCR(Program Clock Reference)——指示系统时钟本身的瞬时值的时间标签称为节目参考时钟标签(PCR)。 PTS
我的月经贴博客该更新了!!!已经有许多博文需要补了! 去年开始的jpeg解码项目,中间停止更新了大半年时间,上个月想起这事还没完工,就又做了更多兼容性和性能上的改进,目前终于接近尾声了。有需要参考的可
花了两天时间做了个h264裸流nal类型和frame类型检测的工具,已上传至github,有需要的自行下载(其中包含构建出来的可执行文件exe)。 1.NAL类型检测 nal类型检测非常容易,对照下表
随着工作业务的开展,对视频编解码的理解更加深入了一些,记录一些心得体会,以便后面回味。 某天突然有个好的想法略过心头,可以形象的向别人介绍视频编码和解码。 1.编解码像一场考试,编码就像做主观题,解码
承接昨天写的《JPEG软解码实现介绍》,今天介绍其使用方法和一些细节说明。 1.仓库下已经包含了几个jpeg文件,以方便直接校验。 2.使用命令分为两种模式。 一种是直接解码为yuv文件,另外一种是解
x264编码器,提供了两个demo来验证编码功能:一个是大而全的x264.c,另外一个是简洁版的example.c。 其中,前者demo,可以配置很多编码参数,但太冗长繁杂,对初学者不太友好。 后者d
本博文为概览性介绍。后面有空了再分几篇博文分别介绍所用到的技术细节。 1.编解码目标 编码和解码是个逆过程。jpeg编码的目的在于图形去冗余,进行数据压缩,解码的目的在于还原图像,使能够进行预览。 2
今天使用公司开发手机,调研一下当下很火的抖音客户端,其使用的视频编码类型。 在调研前,有个初步判断: 1.从抖音服务器推送到客户端的视频流要么是avc码流,要么是hevc码流(具体要视平台解码硬件支持
最近对抖音有点上瘾,经常看到这样的视频列表: 由于抖音平台的限制,用户最多只能上传60s的视频,因此分段为3个视频。而在视频列表的缩略图模式下,三个视频的封面恰好组合成一张图像。这种方式比较符合审美标
自己在学习h264的路上,欢迎讨论交流。 前段时间研究JM出品的h264编码器,代码实在看不下去,因此换了个角度来研究诸多算法——逆向方式(解码),本系列文章记录一些遇到的东西和思考。 1. JM介绍
h264裸码流,根据nalu_header可以知道类型,例如该帧是I帧,P帧/B帧。 例如,常见的0x65代表I帧,0x41代表非关键帧,即P帧或B帧,但是只根据nalu_header是无法区分P帧和