h264检测是I帧还是P帧,解决录像第一帧有马赛克问题

最近使用h264码流数据进行录像,但是录出来的第一帧有马赛克,究其原因是录像的第一帧不是关键帧,所以需要录像是需要判断第一帧是否是关键帧,方法有两种,第一种是原码流的基础上查找,第二种是将原码流传递给ffmpeg让ffmpeg判断key_frame,第二种相对简单,但是由于这样一来录像和解码视频切合的太紧密,之后修改比较麻烦,所以选择第一种方案,查看注释1可以明白如何检测h264码流的关键帧,下面是我截取原码流的关键帧和p帧


0000000 :是sps

0000000  :  是pps

0000000  : 是帧类型

关键帧类型:

0000000: 0000 0001 6742 401f 9654 0501 ed00 f39e  ....gB@..T......
0000010: a000 0000 0168 ce38 8000 0000 0165 8880  .....h.8.....e..
0000020: 4001 8231 2000 4f11 d84d 5fff fb3b c28a  @..1 .O..M_..;..
0000030: 00bc fc83 03db b3e3 8603 9c59 fa0f a82c  ...........Y...,
0000040: df55 fdf6 8414 032a e766 bd4b fbea 05af  .U.....*.f.K....


P帧类型:

0000000: 0000 0001 6742 401f 9654 0501 ed00 f39e  ....gB@..T......
0000010: a000 0000 0168 ce38 8000 0000 0141 9a02  .....h.8.....A..
0000020: 0586 7cb9 9125 5788 8f90 7f1f 1930 7eef  ..|..%W......0~.
0000030: 6383 bebd 2cc5 3627 92c3 390b 46dc d4a5  c...,.6'..9.F...
0000040: 774b 3484 57f8 9840 fba3 1dd6 800f 2242  wK4.W..@......"B
0000050: 8816 080f 8f8d 84c6 09aa cda6 363d 00da  ............6=..
0000060: b563 4392 bc65 93e2 63bb 6d30 472e 3ef1  .cC..e..c.m0G.>.
0000070: 545d 6a3f 36c3 2f7d 6b1e 3c91 d15d d687  T]j?6./}k.<..]..

所以在代码中需要检索第29个字节,来判断是65还是41,

public static String byteToHexString(byte src){   
	    StringBuilder stringBuilder = new StringBuilder("");   
	        int v = src & 0xFF;   
	        String hv = Integer.toHexString(v);  
	        if (hv.length() < 2) {   
	            stringBuilder.append(0); 
	        }   
	        stringBuilder.append(hv);
	    return stringBuilder.toString();   
	}   
private boolean isFirstIFrame = true;
private String IFrame = "65";//关键帧是0x65
//bArrayImage是存放h264原码流字节数组
if (是在录像) {
                if (isFirstIFrame) {
                    String type = byteToHexString(bArrayImage[29]);
                    if (type.equals(IFrame)) {    //第29个字符是判断帧的类型
                        isFirstIFrame = false;
                        ShootingVideoData(bArrayImage, Video_Data_iVideoLen);//录制第一帧:关键帧
                    }
                }else {
                    ShootingVideoData(bArrayImage, Video_Data_iVideoLen);
                }
            }
这样在录制出的第一帧录像就没有马赛克了。

注释1:检测h264中I帧,P帧

原文链接:http://blog.csdn.net/zgyulongfei/article/details/7558031

今天在网上找了一些资料,知道了如何检测h264中的帧类型,在这里记录下来。

首先,贴出nal单元类型定义(图从《新一代视频压缩编码标准H.264》摘录):

假设一段h264的码流为:00 00 00 01 41 E6 60……

其中的00 00 00 01为起始码,而起始码之后的下一个字节就可以检测出这一帧的类型。

在上面的码流中起始码之后的字节位 0x41,换算成二进制为 0100 0001。

注:我解读顺序为从左往右算。

(1)第1位禁止位,值为1表示语法出错

(2)第2~3位为参考级别

(3)第4~8为是nal单元类型,在此处为 0 0001换算成十进制为1。根据上图可知道这段码流是【不分区、非IDR图像的片】,在baseline的档次中就是P帧,因为baseline没有B帧。

如果是另一段码流:00 00 00 01 65 E8……

那么根据0x65字节(0110 0101)根据后5位换算十进制为5,也就是【IDR图像中的片】,即I帧。


用代码的方式可以这样写,int type = 0x65 & 0x1f,然后根据type在表中查找即可获得需要的结果。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值