背景描述

我们经常在网络直播推流或者客户端拉流的时候,需要对获取到的H.264视频帧进行判断后处理,我们经常获取到各种不同的视频数据0x67 0x68 0x65 0x61,0x27 0x28 0x25 0x21,0x47 0x48 0x45 0x41,各种不同的编码芯片有时间出来的NAL Header规则不大一样,那么我们怎么来以统一的方式判断帧的类型呢:sps、pps、IDR、P

如下转自EasyDarwin开源贡献者Kim的博客:http://blog.csdn.net/jinlong0603/article/details/70170042

H264

H264在网络传输的是NALU,NALU的结构是:NAL头+RBSP,实际传输中的数据流如图所示:

其中NAL头占一个字节,其低5个bit位表示NAL type,具体如下表:

NAL type NAL类型
0 未使用
1 非IDR的片
2 片数据A分区
3 片数据B分区
4 片数据C分区
5 IDR图像的片
6 补充增强信息单元(SEI)
7 序列参数集(SPS)
8 图像参数集(PPS)
9 分界符
10 序列结束
11 码流结束
12 填充
13..23 保留
24..31 不保留

RBSP 为原始字节序列载荷。

NAL type为5,则此帧为I帧即关键帧,type为1时为非关键帧(P帧…)。

在实际的H264数据帧中,往往帧NAL type前面带有00 00 00 01 或 00 00 01分隔符,一般来说编码器编出的首帧数据为PPS与SPS,接着为I帧,然后是P帧…

EasyPusher/EasyRTMP 视频流推送

EasyPusher和EasyRTMP是通过调用摄像机SDK、拉取RTSP流、读mp4文件等方式获取到H264视频流及音频视频流到本地作为视频源,再以RTSP、RTMP方式推送给流媒体服务器。它们都是支持Windows、Linux、Android、iOS、ARM等全平台的视频流推送程序。

下面介绍下它们在获取到视频流到本地后如何区分I帧和P帧等,然后推送的:

  1. //这段代码是从文件中读取h264数据,然后推送给服务器
  2. unsigned char *ptr=new unsigned char [sample_size];
  3. fread(ptr, sample_size, 1, g_fin);
  4. //写一帧数据 --- 可以直接进行网络推送
  5. //fwrite(ptr, sample_size, 1, fout);
  6. EASY_AV_Frame avFrame;
  7. memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));
  8. /*
  9. *ptr的前4字节是帧分分割符00 00 00 01 , 第5个字节是NAL type
  10. */
  11. unsigned char naltype = ( (unsigned char)ptr[4] & 0x1F);
  12. avFrame.pBuffer = (unsigned char*)ptr;
  13. avFrame.u32AVFrameLen = sample_size;
  14. avFrame.u32VFrameType = (naltype==0x05)?EASY_SDK_VIDEO_FRAME_I:EASY_SDK_VIDEO_FRAME_P;
  15. avFrame.u32AVFrameFlag = EASY_SDK_VIDEO_FRAME_FLAG;
  16. avFrame.u32TimestampSec = lTimeStamp/1000000;
  17. avFrame.u32TimestampUsec = (lTimeStamp%1000000);

如果视频源不是文件,而是IPCamera 或者RTSP流等,在他们的视频流回调中可能已经告知当前帧是I帧还是P帧,就省去了判断NAL type的步骤。

  1. HI_S32 NETSDK_APICALL OnStreamCallback(HI_U32 u32Handle,/* 句柄 */
  2. HI_U32 u32DataType, /* 数据类型,视频或音频数据或音视频复合数据 */
  3. HI_U8* pu8Buffer, /* 数据包含帧头 */
  4. HI_U32 u32Length, /* 数据长度 */
  5. HI_VOID* pUserData /* 用户数据*/
  6. )
  7. {
  8. HI_S_AVFrame* pstruAV = HI_NULL;
  9. HI_S_SysHeader* pstruSys = HI_NULL;
  10. if (u32DataType == HI_NET_DEV_AV_DATA)
  11. {
  12. pstruAV = (HI_S_AVFrame*)pu8Buffer;
  13. if (pstruAV->u32AVFrameFlag == HI_NET_DEV_VIDEO_FRAME_FLAG)
  14. {
  15. if(fPusherHandle == 0 ) return 0;
  16. if(pstruAV->u32AVFrameLen > 0)
  17. {
  18. unsigned char* pbuf = (unsigned char*)(pu8Buffer+sizeof(HI_S_AVFrame));
  19. EASY_AV_Frame avFrame;
  20. memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));
  21. avFrame.u32AVFrameLen = pstruAV->u32AVFrameLen;
  22. avFrame.pBuffer = (unsigned char*)pbuf;
  23. avFrame.u32VFrameType = (pstruAV->u32VFrameType==HI_NET_DEV_VIDEO_FRAME_I)?EASY_SDK_VIDEO_FRAME_I:EASY_SDK_VIDEO_FRAME_P;
  24. avFrame.u32AVFrameFlag = EASY_SDK_VIDEO_FRAME_FLAG;
  25. avFrame.u32TimestampSec = pstruAV->u32AVFramePTS/1000;
  26. avFrame.u32TimestampUsec = (pstruAV->u32AVFramePTS%1000)*1000;
  27. EasyPusher_PushFrame(fPusherHandle, &avFrame);
  28. }
  29. }
  30. else
  31. if (pstruAV->u32AVFrameFlag == HI_NET_DEV_AUDIO_FRAME_FLAG)
  32. {
  33. if(fPusherHandle == 0 ) return 0;
  34. if(pstruAV->u32AVFrameLen > 0)
  35. {
  36. //不同IPCamera,这里数据头不一样,需要根据各自的SDK跳过对应的大小。有些可能没有自定义数据
  37. unsigned char* pbuf = (unsigned char*)(pu8Buffer+sizeof(HI_S_AVFrame));
  38. EASY_AV_Frame avFrame;
  39. memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));
  40. avFrame.u32AVFrameLen = pstruAV->u32AVFrameLen-4;//去掉厂家自定义的4字节头
  41. avFrame.pBuffer = (unsigned char*)pbuf+4;
  42. avFrame.u32AVFrameFlag = EASY_SDK_AUDIO_FRAME_FLAG;
  43. avFrame.u32TimestampSec = pstruAV->u32AVFramePTS/1000;
  44. avFrame.u32TimestampUsec = (pstruAV->u32AVFramePTS%1000)*1000;
  45. EasyPusher_PushFrame(fPusherHandle, &avFrame);
  46. }
  47. }
  48. }
  49. else
  50. if (u32DataType == HI_NET_DEV_SYS_DATA)
  51. {
  52. pstruSys = (HI_S_SysHeader*)pu8Buffer;
  53. printf("Video W:%u H:%u Audio: %u \n", pstruSys->struVHeader.u32Width, pstruSys->struVHeader.u32Height, pstruSys->struAHeader.u32Format);
  54. }
  55. return HI_SUCCESS;
  56. }

有了数据源,只需要调用libEasyPusher或libEasyRTMP就可以完成RTSP、RTMP直播推送了!

下载

EasyDarwin服务器下载:https://github.com/EasyDarwin/EasyDarwin或者国内镜像http://git.oschina.net/easydarwin/EasyDarwin

EasyPusher 下载:https://github.com/EasyDarwin/EasyPusher

EasyRTMP 下载:https://github.com/EasyDarwin/EasyRTMP

获取更多信息

邮件:support@easydarwin.org

WEB:www.EasyDarwin.org

Copyright © EasyDarwin.org 2012-2017

对H.264帧类型判断方法的更多相关文章

  1. H.264帧结构详解

    6.1.2.源码简单浏览 6.1.3.重点1:h.264帧结构6.1.4.重点2:帧结构分析软件的使用6.1.5.重点3:rtsp网络编程6.1.6.重点4:wireshark网络抓包工具的使用 6. ...

  2. 获得H.264视频分辨率的方法

    转自:http://www.cnblogs.com/likwo/p/3531241.html 在使用ffmpeg解码播放TS流的时候(例如之前写过的UDP组播流),在连接时往往需要耗费大量时间.经过d ...

  3. 【转载】 H264的I/P/B帧类型判断

    http://blog.csdn.net/zhuweigangzwg/article/details/44152239 这里首先说明下H264的结构: 00 00 00 01/00 00 01-> ...

  4. 使用ASP.NET 上传文件 三种类型判断方法(后缀,MIME,数据流)

    #region 一. 安全性比较低,把文本文件1.txt改成1.jpg照样可以上传,但其实现方法容易理解,实现也简单,所以网上很多还是采取这种方法. Boolean fileOk = false; s ...

  5. javascript类型判断方法

    判断javascript中的类型,共有四种常用的方法 var a=6; var b="str"; var c=true; var arr=[]; typeof 用于基本类型的判断 ...

  6. JS万金油的类型判断方法

    Object.prototype.toString.call(data).slice(8, -1).toLowerCase();

  7. H.264视频压缩标准

    H.264 这部分一直在讲,但是却没有系统的来说.接下来要详细. 参看:H.264视频压缩标准 一.简介 H.264是最新的视频压缩标准,它也称为MPEG-4 Part 10或AVC(高级视频编码). ...

  8. jQuery使用(十二):工具方法之type()之类型判断

    type()的使用 类型判断方法之is...() 实现原理可以参考我的另一篇js源码剖析博客: 类型和原生函数及类型转换(二:终结js类型判断) $.type( undefined ) === &qu ...

  9. (转载)H.264码流的RTP封包说明

    H.264的NALU,RTP封包说明(转自牛人) 2010-06-30 16:28 H.264 RTP payload 格式 H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) ...

随机推荐

  1. 分享tiny4412,emmc烧录u-boot, 支持fastboot模式烧写emmc

    转载 : http://www.arm9home.net/read.php?tid-83474.html 本人是第一次在此发帖,希望大家多多支持,发帖目的是为了分享,分享的目的是传递开源的精神.Tin ...

  2. Apple激活日期查询

    需要输入的信息为苹果产品的序列号 查看您的保修服务和支持期限 - Apple 支持 或者通过果粉查询网站获取结果

  3. Attempt to invoke virtual method 'void android.app.ActionBar.setTitle的解决方法

    在安卓4.4.2的关于蓝牙开发的一个sample BluetoothChat中,调试时,老是出错:Attempt to invoke virtual method 'void android.app. ...

  4. DevExpress的GridControl如何实现打印和打印预览 z

    第一种方法:             System.Drawing.Printing.PageSettings set_print_page = new System.Drawing.Printing ...

  5. mac os+selenium2+chrome驱动+python3

    mac os 10.11.5 mac自带python2.7,自己下载了python3.5,pip list查看系统中的安装包,本人电脑中已经安装了pip和setuptools,若未安装,请先使用 su ...

  6. php性能监控扩展xhprof

    XHProf是facebook开源出来的一个php轻量级的性能分析工具,跟Xdebug类似,但性能开销更低,还可以用在生产环境中,也可以由程序开 关来控制是否进行profile.总体来说是个不错的工具 ...

  7. jquery的一点点认识

    概述 JQuery是继prototype之后又一个优秀的Javascript库.它是轻量级的js库 .它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, Safari 2.0+, O ...

  8. 我的跟我学Ffmpeg 视频受众有哪些人

    经常有人问我如何学习音视频以及如何学习Ffmpeg,问我有没有比较好的书的书推荐.比较好的音视频以及FFmpeg方面的 书,我了解到的比较全面又能深入浅出的还真没有.很多朋友都推荐雷神的博客,雷神的博 ...

  9. python正则中的贪婪与非贪婪

    当重复一个正则表达式时,如用 a*,操作结果是尽可能多地匹配模式.当你试着匹配一对对称的定界符,如 HTML 标志中的尖括号.匹配单个 HTML 标志的模式不能正常工作,因为 .* 的本质是“贪婪”的 ...

  10. Java集合01----ArrayList的遍历方式及应用

                                                 Java集合01----ArrayList的遍历方式及应用 前面已经学习了ArrayList的源代码,为了学以 ...