h264检测是I帧还是P帧,解决录像第一帧有马赛克问题
最近使用h264码流数据进行录像,但是录出来的第一帧有马赛克,究其原因是录像的第一帧不是关键帧,所以需要录像是需要判断第一帧是否是关键帧,方法有两种,第一种是原码流的基础上查找,第二种是将原码流传递给ffmpeg让ffmpeg判断key_frame,第二种相对简单,但是由于这样一来录像和解码视频切合的太紧密,之后修改比较麻烦,所以选择第一种方案,查看注释1可以明白如何检测h264码流的关键帧,下面是我截取原码流的关键帧和p帧
0000000 :是sps
0000000 : 是pps
0000000 : 是帧类型
关键帧类型:
- <span style="color:#FF0000;"><span style="font-size:24px;">0000000: <span style="color:#CCCCCC;">0000 0001 6742 401f 9654 0501 ed00 f39e ....gB@..T......
- 0000010: a</span><span style="color:#3366FF;">000 0000 0168 ce38 80</span>00 0000 01<span style="color:#000000;">65</span> 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....</span>
- </span>
P帧类型:
- 0000000: <span style="color:#C0C0C0;">0000 0001 6742 401f 9654 0501 ed00 f39e ....gB@..T......
- 0000010: a</span><span style="color:#3366FF;">000 0000 0168 ce38 80</span>00 0000 01<span style="color:#000000;">41</span> 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
- //<span style="font-size:16px"></span>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在表中查找即可获得需要的结果。
h264检测是I帧还是P帧,解决录像第一帧有马赛克问题的更多相关文章
- 第五十二篇、 OC获取视频的第一帧图片thumbnailImage
获取视频的第一帧图片 有时候我们拍摄完视频后,希望获取一张图片当作这个视频的介绍,这个图片thumbnailImage可以从视频的第一帧获取到. 我们的思路是先获取视频的URL,然后初始化一个MPMo ...
- video标签,在移动端获取第一帧作为展示
写在前面 video标签,获取第一帧作为poster.网上能找着很多案例,很容易实现,在pc端 效果明显.但是在移动端,这些实现方式并不能起作用.原因是 移动端 对video标签的限制,许多video ...
- 关于video标签移动端开发遇到的问题,获取视频第一帧,全屏,自动播放,自适应等问题
最近一直在处理video标签在IOS和Android端的兼容问题,其中遇到不少坑,绝大多数问题已经解决,下面是处理问题经验的总结: 1.获取视频的第一帧作为背景图: 技术:canvas绘图 windo ...
- 视频转码成mp4格式,添加关键帧,添加元数据,把元数据放在第一帧,可拖动
作者测试是在windows下使用,所以下载的页面地址是: http://ffmpeg.zeranoe.com/builds/点击页面上的Download FFmpeg git-738ebb4 64-b ...
- Android使用帧动画内存溢出解决方法
Android使用帧动画内存溢出解决方法https://blog.csdn.net/daitu_liang/article/details/52336015https://blog.csdn.net/ ...
- Opencv打开摄像头,读不到图像,一般来说先读取第一帧,舍弃,然后就正常了
舍弃第一帧的程序: cap >> img; cv::waitKey(100); if (cvWaitKey(5) == 27) break; cap >> img;
- java获取视频播第一帧
FFMPEG 功能很强大,做视频必备的软件.大家可通过 http://ffmpeg.org/ 了解.Windows版本的软件,可通过 http://ffmpeg.zeranoe.com/builds/ ...
- Android -- 获取视频第一帧缩略图
干货 从API 8开始,新增了一个类: android.media.ThumbnailUtils这个类提供了3个静态方法一个用来获取视频第一帧得到的Bitmap,2个对图片进行缩略处理. public ...
- PHP获取视频的第一帧与时长
//获得视频文件的缩略图 function getVideoCover($file,$time,$name) { if(empty($time))$time = '1';//默认截取第一秒第一帧 $s ...
随机推荐
- 【unity3d游戏开发之基础篇】unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子
原地址:http://www.cnblogs.com/xuling/archive/2013/03/04/2943154.html 最近开始研究U3D,它的强大就不多说了, 今天研究了研究射线相关东西 ...
- POJ 3126 Prime Path(BFS求“最短路”)
题意:给出两个四位数的素数,按如下规则变换,使得将第一位数变换成第二位数的花费最少,输出最少值,否则输出0. 每次只能变换四位数的其中一位数,使得变换后的数也为素数,每次变换都需要1英镑(即使换上的数 ...
- 2013 ACM-ICPC长沙赛区全国邀请赛—Special equations
……但是没仔细看,直接跳过了 这题直接枚举就可以过了 ;}
- CLR 读书笔记
http://www.cnblogs.com/wang_yb/tag/CLR%20via%20C%23%E7%AC%94%E8%AE%B0/
- hdu1021 Fibonacci Again
http://acm.hdu.edu.cn/showproblem.php?pid=1021 //找规律.. #include<iostream> #include<stdio.h& ...
- python学习[一]
Vamei写了很好的python教程,感谢:http://www.cnblogs.com/vamei/archive/2012/09/13/2682778.html 摘录笔记 print命令行模式: ...
- 【Linux高频命令专题(19)】vi/vim
概述 其实在Linux中一切命令或者软件都是文件,所以把vi/vim作为高频命令专题之一,也没什么不妥.虽然大家都称之为编辑器~~ vim是vi的高级版本,比如有代码高亮,也就是说可以把vim定位为程 ...
- AE数据加载
1. 数据加载问题: 任何系统都离不开数据的加载,下边就AE中几种常用的数据加载做一个列举.以便查阅: 1.加载个人数据库 个人数据库是保存在Access中的数据库.其加载方式有两种:通过名字和通过属 ...
- idea15 如何设置代码不自动折叠
IDEA默认情况下,如果方法体中只有一行,这个方法体会折叠起来,就像这种
- eclipse Juno Indigo Helios Galileo这几种版本的意思(转)
Galileo Ganymede Europa 这些名字代表eclipse不同的版本 2001年11月7日 ,Eclipse 1.0发布 半年之后,2002年6月27日Eclipse进入了2.0 ...