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

时间:2023-02-16 23:04:09

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

0000000 :是sps

0000000  :  是pps

0000000  : 是帧类型

关键帧类型:

  1. <span style="color:#FF0000;"><span style="font-size:24px;">0000000: <span style="color:#CCCCCC;">0000 0001 6742 401f 9654 0501 ed00 f39e  ....gB@..T......
  2. 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..
  3. 0000020: 4001 8231 2000 4f11 d84d 5fff fb3b c28a  @..1 .O..M_..;..
  4. 0000030: 00bc fc83 03db b3e3 8603 9c59 fa0f a82c  ...........Y...,
  5. 0000040: df55 fdf6 8414 032a e766 bd4b fbea 05af  .U.....*.f.K....</span>
  6. </span>

P帧类型:

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

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

  1. public static String byteToHexString(byte src){
  2. StringBuilder stringBuilder = new StringBuilder("");
  3. int v = src & 0xFF;
  4. String hv = Integer.toHexString(v);
  5. if (hv.length() < 2) {
  6. stringBuilder.append(0);
  7. }
  8. stringBuilder.append(hv);
  9. return stringBuilder.toString();
  10. }
  11. private boolean isFirstIFrame = true;
  12. private String IFrame = "65";//关键帧是0x65
  13. //<span style="font-size:16px"></span>bArrayImage是存放h264原码流字节数组
  14. if (是在录像) {
  15. if (isFirstIFrame) {
  16. String type = byteToHexString(bArrayImage[29]);
  17. if (type.equals(IFrame)) {    //第29个字符是判断帧的类型
  18. isFirstIFrame = false;
  19. ShootingVideoData(bArrayImage, Video_Data_iVideoLen);//录制第一帧:关键帧
  20. }
  21. }else {
  22. ShootingVideoData(bArrayImage, Video_Data_iVideoLen);
  23. }
  24. }

这样在录制出的第一帧录像就没有马赛克了。

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

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

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

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

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

假设一段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帧,解决录像第一帧有马赛克问题的更多相关文章

  1. 第五十二篇、 OC获取视频的第一帧图片thumbnailImage

    获取视频的第一帧图片 有时候我们拍摄完视频后,希望获取一张图片当作这个视频的介绍,这个图片thumbnailImage可以从视频的第一帧获取到. 我们的思路是先获取视频的URL,然后初始化一个MPMo ...

  2. video标签,在移动端获取第一帧作为展示

    写在前面 video标签,获取第一帧作为poster.网上能找着很多案例,很容易实现,在pc端 效果明显.但是在移动端,这些实现方式并不能起作用.原因是 移动端 对video标签的限制,许多video ...

  3. 关于video标签移动端开发遇到的问题,获取视频第一帧,全屏,自动播放,自适应等问题

    最近一直在处理video标签在IOS和Android端的兼容问题,其中遇到不少坑,绝大多数问题已经解决,下面是处理问题经验的总结: 1.获取视频的第一帧作为背景图: 技术:canvas绘图 windo ...

  4. 视频转码成mp4格式,添加关键帧,添加元数据,把元数据放在第一帧,可拖动

    作者测试是在windows下使用,所以下载的页面地址是: http://ffmpeg.zeranoe.com/builds/点击页面上的Download FFmpeg git-738ebb4 64-b ...

  5. Android使用帧动画内存溢出解决方法

    Android使用帧动画内存溢出解决方法https://blog.csdn.net/daitu_liang/article/details/52336015https://blog.csdn.net/ ...

  6. Opencv打开摄像头,读不到图像,一般来说先读取第一帧,舍弃,然后就正常了

    舍弃第一帧的程序: cap >> img; cv::waitKey(100);  if (cvWaitKey(5) == 27) break; cap >> img;

  7. java获取视频播第一帧

    FFMPEG 功能很强大,做视频必备的软件.大家可通过 http://ffmpeg.org/ 了解.Windows版本的软件,可通过 http://ffmpeg.zeranoe.com/builds/ ...

  8. Android -- 获取视频第一帧缩略图

    干货 从API 8开始,新增了一个类: android.media.ThumbnailUtils这个类提供了3个静态方法一个用来获取视频第一帧得到的Bitmap,2个对图片进行缩略处理. public ...

  9. PHP获取视频的第一帧与时长

    //获得视频文件的缩略图 function getVideoCover($file,$time,$name) { if(empty($time))$time = '1';//默认截取第一秒第一帧 $s ...

随机推荐

  1. 七个结构模式之组合模式&lpar;Composite Pattern&rpar;

    定义: 组合多个对象形成树形结构来表示"整体-部分"关系的层次结构,其中的叶子对象和容器对象具有相同的接口,可以使用抽象类来进行管理. 结构图: Component:抽象构件类,对 ...

  2. UltraISO制作大于4G文件的光盘映像可启动U盘

    1.使用常规方法 制作 u盘启动 启动-->写入硬盘映像-->写入 2.制作成功后U盘 是FAT32格式 对于FAT32文件系统,其缺点不能存储超过4G的文件,而对于NTFS文件系统,则没 ...

  3. navigator&period;userAgent&period;indexOf来判断浏览器类型

    navigator.userAgent.indexOf来判断浏览器类型 (2011-03-03 11:30:40) 转载▼ 标签: 杂谈   来源:http://xtaai5233.blog.163. ...

  4. android显示证书sha1

    创建证书可以用命令 keytool -genkey -v -keystore android.keystore -alias android -keyalg RSA -validity 或者andro ...

  5. C&num; 多线程网络爬虫

    原文 C#制作多线程处理强化版网络爬虫 上次做了一个帮公司妹子做了爬虫,不是很精致,这次公司项目里要用到,于是有做了一番修改,功能添加了网址图片采集,下载,线程处理界面网址图片下载等. 说说思路:首相 ...

  6. 解析activity之间数据传递方法的详解

    转自:http://www.jb51.net/article/37227.htm 本篇文章是对activity之间数据传递的方法进行了详细的分析介绍,需要的朋友参考下     1  基于消息的通信机制 ...

  7. Mysql 复制表结构 及其表的内容

    顺便转一下Mysql复制表结构.表数据的方法: 1.复制表结构及数据到新表CREATE TABLE 新表 SELECT * FROM 旧表 这种方法会将oldtable中所有的内容都拷贝过来,当然我们 ...

  8. thinkphp整合系列之rbac的升级版auth权限管理系统demo

    权限管理基本是作为网站的标配了: 除非是像博客这类个人使用的:否则权限管理的重要性不言而喻: 今个就来写写auth权限管理: thinkphp已经内置了auth权限类位于:/ThinkPHP/Libr ...

  9. oracle导出expdp导入impdp

    conn sys/password as sysdba;创建用户test1CREATE USER test1 IDENTIFIED BY "pass1";GRANT CONNECT ...

  10. 【计蒜客】是男人就过 8 题--Pony&period;AI 题 A&period; A String Game 后缀自动机&plus;SG函数

    [题目]A. A String Game [题意]给定目标串S和n个子串Ti,Alice和Bob轮流选择一个子串操作,必须且只能在子串末尾添加一个字符使得新串也是S的子串,不能操作即输,求胜利者.|S ...