H264关键帧和丢帧策略研究
来源:互联网 发布:畅唐网络待遇 编辑:程序博客网 时间:2024/05/29 10:59
H264关键帧和丢帧策略研究
p帧是根据前面的I帧和P帧预测而来
首先,你看开头是000001还是00000001,然后看到后面一般是41,67
67可能代表的就是关键帧,41为非关键帧
然后与0x1F做与运算,观察结果的不同,来判断是否为关键帧
int type = packet.data[4]&0x1F;
if (type == 0) {NSLog(@"%d",type);
return;
}
type为:0,1,2,3,4。。。0,1,2
当为0的时候该帧为关键帧,关键帧不能被丢掉,要丢掉也要和后面的p帧,b帧一起丢掉
问题1:如何识别关键帧?
从x264的源代码中可以看到,如果某一帧为关键帧,这么这一帧的所携带的几个nalu中,必然有一个的type 必然为NAL_SLICE_IDR。
view plaincopy to clipboardprint?
/* Set output picture properties */
if( h->sh.i_type == SLICE_TYPE_I )
pic_out->i_type = h->i_nal_type == NAL_SLICE_IDR ? X264_TYPE_IDR : X264_TYPE_I;
else if( h->sh.i_type == SLICE_TYPE_P )
pic_out->i_type = X264_TYPE_P;
else
pic_out->i_type = X264_TYPE_B;
/* Set output picture properties */
if( h->sh.i_type == SLICE_TYPE_I )
pic_out->i_type = h->i_nal_type == NAL_SLICE_IDR ? X264_TYPE_IDR : X264_TYPE_I;
else if( h->sh.i_type == SLICE_TYPE_P )
pic_out->i_type = X264_TYPE_P;
else
pic_out->i_type = X264_TYPE_B;
我的理解就是如果nalu的type为NAL_SLICE_IDR的话,那么这帧肯定就是关键帧了。
因此只需要判断每一帧的nalu的type中是否包还有type为NAL_SLICE_IDR的,如果有则是关键帧。
判断nalu的type的可用如下的方法。
for(int i=0; i<i_nalu; i++)
{
uint8_t *ptr = nalu[i];
int type = ptr[4]&0x1F;
if(type == NAL_SLICE_IDR)
{
key_frame = true;
break;
}
}
判断nalu的type中用到int type = ptr[4]&0x1F; 为什么是0x1F呢,这得说说每个nalu的结构;
nalu有三部分组成。
起始码 nalu_header data
起始码: 分为longcode 和 shortcode ;
longcode :0x 00 00 00 01;
shortcode :0x 00 00 01;
nalu_header:有三个子域;
NALU 头由一个字节组成, 它的语法如下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
F: 1 个比特.
forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.
NRI: 2 个比特.
nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性, 如 00 的 NALU 解码器可以丢弃它而不影响图像的回放. 不过一般情
况下不太关心
这个属性.
Type: 5 个比特.
nal_unit_type. 这个 NALU 单元的类型. 简述如下:
0 没有定义
1-23 NAL单元 单个 NAL 单元包.
24 STAP-A 单一时间的组合包
24 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义
大家可以看到,要获得type的话,就得将nalu起始码后面紧跟的第一个字节的内容与0x1F做与运算后得到。
问题2:如何判断每一帧的中nalu的起始和结束。
数据在经过int x264_nal_encode( void *, int *, int b_annexeb, x264_nal_t *nal )后,会将数据组装成nalu的标准格式,即按照上面的格式:
起始码 nalu_header data。
x264使用0x 00 00 00 01作为起始码(longcode)。int x264_nal_encode( void *, int *, int b_annexeb, x264_nal_t *nal )的作用就是使得数据流中不会再出现连续的两个以上的0。如果有的话就会插入一个0x03;
因此如果要还原一帧数据中的逻辑结构的话,可以遍历数据流,寻找0x00000001这样的特征代码。
这一点对于使用x264自带的mkv文件保存接口很是有用。因为我们接收到的网络数据可能没有没有带上详细的nalu分界信息和帧类型,需要自己重新还原
- H264关键帧和丢帧策略研究
- H264关键帧和丢帧策略研究
- 判断H264码流的关键帧
- 判断H264码流的关键帧
- Live555接收H264流判断关键帧
- 判断H264码流的关键帧
- H264 NALU分析(sps,pps,关键帧,非关键帧)
- sip info 方法 发起 h264关键帧请求
- sip info 方法 发起 h264关键帧请求
- 关键帧和动画
- Kafka 几个关键概念和采用策略
- rtp传输h264编码的视频判断是否为关键帧
- 达芬奇处理器的H264编码关键模块的实现研究----笔记
- 帧、关键帧和空白关键帧的作用
- 帧、关键帧和空白关键帧的作用
- 关键帧
- 关键帧
- H264 CAVLC 研究
- 【笔试面试——24】链表04——反转链表
- IOS中Json解析的四种方法
- sql回滚语句
- 薄膜电容器的特性
- 什么是响应式Web设计?怎样进行?
- H264关键帧和丢帧策略研究
- PHP大小写:函数名和类名不区分,变量名区分
- Android Xutils 开发框架
- 艾玛迪斯咨询讨论定价的iPhone应用程序的最大的成功
- getline()函数的详解
- ViewPage滑动冲突解决办法
- Js获取当前日期时间及其它操作
- 二叉树的三种遍历的相互转化——已知先序中序求后序
- 算法之--数组分割