在网上找的资料一般雷同,发现用起来有的分辨率不能解析,最后发现一篇文章方法与其他不一样,贴的有代码看着也像从源码中摘出来的然后自己做了修改,亲测还挺好使,工程已引用

直接上代码

SPSparse_SPS.h

封成一个通用函数h264_parse_sps(const uint8_t* buf,int len,h264_sps_data_t* sps);

#ifndef __SPSparse__SPS__
#define __SPSparse__SPS__#include <stdio.h>
#ifdef _MSC_VER
typedef signed char     int8_t;
typedef unsigned char   uint8_t;
typedef short           int16_t;
typedef unsigned short  uint16_t;
typedef int             int32_t;
typedef unsigned        uint32_t;
#else
#include <stdint.h>
#endif //#ifdef __cplusplus
extern "C" {#endif#define NAL_SPS     0x07 /* Sequence Parameter Set */
#define NAL_AUD     0x09 /* Access Unit Delimiter */
#define NAL_END_SEQ 0x0a /* End of Sequence */#if defined(__i386__) || defined(__x86_64__)
#  define IS_NAL_SPS(buf)     (*(const uint32_t *)(buf) == 0x07010000U)
#  define IS_NAL_AUD(buf)     (*(const uint32_t *)(buf) == 0x09010000U)
#  define IS_NAL_END_SEQ(buf) (*(const uint32_t *)(buf) == 0x0a010000U)
#else
#  define IS_NAL_SPS(buf)     ((buf)[0] == 0 && (buf)[1] == 0 && (buf)[2] == 1 && (buf)[3] == NAL_SPS)
#  define IS_NAL_AUD(buf)     ((buf)[0] == 0 && (buf)[1] == 0 && (buf)[2] == 1 && (buf)[3] == NAL_AUD)
#  define IS_NAL_END_SEQ(buf) ((buf)[0] == 0 && (buf)[1] == 0 && (buf)[2] == 1 && (buf)[3] == NAL_END_SEQ)
#endiftypedef struct mpeg_rational_s {int num;int den;} mpeg_rational_t;typedef struct video_size_s {uint16_t        width;uint16_t        height;mpeg_rational_t pixel_aspect;} video_size_t;typedef struct {uint16_t        width;uint16_t        height;mpeg_rational_t pixel_aspect;uint8_t   profile;uint8_t   level;} h264_sps_data_t;struct video_size_s;/** input: start of NAL SPS ( 00 00 01 07 or 00 00 00 01 67 0r 67)*/int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps);#ifdef __cplusplus
}#endif#endif /* defined(__SPSparse__SPS__) */

实现:bitstream.h  bitstream.cpp

# ifdef NOCACHEtypedef struct {const uint8_t *data; //存放除了sps数据int            count; /* in bits */int            index; /* in bits */
} br_state;#define BR_INIT(data,bytes) {(data), 8*(bytes), 0}#define BR_EOF(br) ((br)->index >= (br)->count)static inline void br_init(br_state *br, const uint8_t *data, int bytes)
{br->data  = data;br->count = 8*bytes;br->index = 0;}static inline int br_get_bit(br_state *br)
{if(br->index >= br->count)return 1; /* -> no infinite colomb's ... */int r = (br->data[br->index>>3] >> (7 - (br->index&7))) & 1;br->index++;return r;}static inline uint32_t br_get_bits(br_state *br, uint32_t n)
{uint32_t r = 0;while(n--)r = r | (br_get_bit(br) << n);return r;}#define br_skip_bit(br) br_skip_bits(br,1)static inline void br_skip_bits(br_state *br, int n)
{br->index += n;}# else /* NOCACHE */typedef struct {uint8_t *data;uint8_t *data_end;uint32_t cache;uint32_t cache_bits;} br_state;#define BR_INIT(data,bytes) {(data), (data)+(bytes), 0, 0}static inline void br_init(br_state *br, const uint8_t *data, int bytes)
{br->data       = data;br->data_end   = data + bytes;br->cache      = 0;br->cache_bits = 0;}#define BR_GET_BYTE(br) \
(br->data < br->data_end ? *br->data++ : 0xff)#define BR_EOF(br) ((br)->data >= (br)->data_end)static inline uint32_t br_get_bits(br_state *br, uint32_t n)
{if(n > 24)return (br_get_bits(br, 16) << 16) | br_get_bits(br, n-16);while (br->cache_bits < 24) {br->cache = (br->cache<<8) | BR_GET_BYTE(br);br->cache_bits += 8;}br->cache_bits -= n;return (br->cache >> br->cache_bits) & ((1<<n) - 1);}static inline int br_get_bit(br_state *br)
{if(!br->cache_bits) {br->cache = BR_GET_BYTE(br);br->cache_bits = 7;} else {br->cache_bits--;}return (br->cache >> br->cache_bits) & 1;}static inline void br_skip_bit(br_state *br)
{if(!br->cache_bits) {br->cache = BR_GET_BYTE(br);br->cache_bits = 7;} else {br->cache_bits--;}}static inline void br_skip_bits(br_state *br, int n)
{if(br->cache_bits >= n) {br->cache_bits -= n;} else {/* drop cached bits */n -= br->cache_bits;/* drop full bytes */br->data += (n >> 3);n &= 7;/* update cache */if(n) {br->cache = BR_GET_BYTE(br);br->cache_bits = 8 - n;} else {br->cache_bits = 0;}}}# endif /* NOCACHE */#define br_get_u8(br)         br_get_bits(br, 8)
#define br_get_u16(br)        ((br_get_bits(br, 8)<<8) | br_get_bits(br, 8))static inline uint32_t br_get_ue_golomb(br_state *br)
{int n = 0;while (!br_get_bit(br) && n < 32)n++;return n ? ((1<<n) - 1) + br_get_bits(br, n) : 0;}#pragma warning(disable: 4146)static inline int32_t br_get_se_golomb(br_state *br)
{uint32_t r = br_get_ue_golomb(br) + 1;return (r&1) ? -(r>>1) : (r>>1);}static inline void br_skip_golomb(br_state *br)
{int n = 0;while (!br_get_bit(br) && n < 32)n++;br_skip_bits(br, n);}#define br_skip_ue_golomb(br) br_skip_golomb(br)
#define br_skip_se_golomb(br) br_skip_golomb(br)
int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps) {//find spsbool findSPS = false;if (buf[2] == 0) {if ((buf[4]&0x1f) == 7) { //start code 0 0 0 1len -= 5;buf += 5;findSPS = true;}} else if (buf[2] == 1) {//start code 0 0 1if ((buf[3]&0x1f) == 7) {len -= 4;buf += 4;findSPS = true;}} else {if ((buf[0]&0x1f) == 7) { //no start code 0x67 开头len -= 1;buf += 1;findSPS = true;}}br_state br = BR_INIT(buf, len);int profile_idc, pic_order_cnt_type;int frame_mbs_only;int i, j;profile_idc = br_get_u8(&br);sps->profile = profile_idc;printf("H.264 SPS: profile_idc %d", profile_idc);/* constraint_set0_flag = br_get_bit(br);    *//* constraint_set1_flag = br_get_bit(br);    *//* constraint_set2_flag = br_get_bit(br);    *//* constraint_set3_flag = br_get_bit(br);    *//* reserved             = br_get_bits(br,4); */sps->level = br_get_u8(&br);br_skip_bits(&br, 8);br_skip_ue_golomb(&br);   /* seq_parameter_set_id */if (profile_idc >= 100) {if (br_get_ue_golomb(&br) == 3) /* chroma_format_idc      */br_skip_bit(&br);     /* residual_colour_transform_flag */br_skip_ue_golomb(&br); /* bit_depth_luma - 8             */br_skip_ue_golomb(&br); /* bit_depth_chroma - 8           */br_skip_bit(&br);       /* transform_bypass               */if (br_get_bit(&br))    /* seq_scaling_matrix_present     */for (i = 0; i < 8; i++)if (br_get_bit(&br)) {/* seq_scaling_list_present    */int last = 8, next = 8, size = (i<6) ? 16 : 64;for (j = 0; j < size; j++) {if (next)next = (last + br_get_se_golomb(&br)) & 0xff;last = next ? next: last;}}}br_skip_ue_golomb(&br);      /* log2_max_frame_num - 4 */pic_order_cnt_type = br_get_ue_golomb(&br);if (pic_order_cnt_type == 0)br_skip_ue_golomb(&br);    /* log2_max_poc_lsb - 4 */else if (pic_order_cnt_type == 1) {br_skip_bit(&br);          /* delta_pic_order_always_zero     */br_skip_se_golomb(&br);    /* offset_for_non_ref_pic          */br_skip_se_golomb(&br);    /* offset_for_top_to_bottom_field  */j = br_get_ue_golomb(&br); /* num_ref_frames_in_pic_order_cnt_cycle */for (i = 0; i < j; i++)br_skip_se_golomb(&br);  /* offset_for_ref_frame[i]         */}br_skip_ue_golomb(&br);      /* ref_frames                      */br_skip_bit(&br);            /* gaps_in_frame_num_allowed       */sps->width  /* mbs */ = br_get_ue_golomb(&br) + 1;sps->height /* mbs */ = br_get_ue_golomb(&br) + 1;frame_mbs_only        = br_get_bit(&br);printf("H.264 SPS: pic_width:  %u mbs", (unsigned) sps->width);printf("H.264 SPS: pic_height: %u mbs", (unsigned) sps->height);printf("H.264 SPS: frame only flag: %d", frame_mbs_only);sps->width  *= 16;sps->height *= 16 * (2-frame_mbs_only);if (!frame_mbs_only)if (br_get_bit(&br)) /* mb_adaptive_frame_field_flag */printf("H.264 SPS: MBAFF");br_skip_bit(&br);      /* direct_8x8_inference_flag    */if (br_get_bit(&br)) {/* frame_cropping_flag */uint32_t crop_left   = br_get_ue_golomb(&br);uint32_t crop_right  = br_get_ue_golomb(&br);uint32_t crop_top    = br_get_ue_golomb(&br);uint32_t crop_bottom = br_get_ue_golomb(&br);printf("H.264 SPS: cropping %d %d %d %d",crop_left, crop_top, crop_right, crop_bottom);sps->width -= 2*(crop_left + crop_right);if (frame_mbs_only)sps->height -= 2*(crop_top + crop_bottom);elsesps->height -= 4*(crop_top + crop_bottom);}/* VUI parameters */sps->pixel_aspect.num = 0;if (br_get_bit(&br)) {/* vui_parameters_present flag */if (br_get_bit(&br)) {/* aspect_ratio_info_present */uint32_t aspect_ratio_idc = br_get_u8(&br);printf("H.264 SPS: aspect_ratio_idc %d", aspect_ratio_idc);if (aspect_ratio_idc == 255 /* Extended_SAR */) {sps->pixel_aspect.num = br_get_u16(&br); /* sar_width */sps->pixel_aspect.den = br_get_u16(&br); /* sar_height */printf("H.264 SPS: -> sar %dx%d", sps->pixel_aspect.num, sps->pixel_aspect.den);} else {static const mpeg_rational_t aspect_ratios[] ={/* page 213: *//* 0: unknown */{0, 1},/* 1...16: */{1,  1}, {12, 11}, {10, 11}, {16, 11}, {40, 33}, {24, 11}, {20, 11}, {32, 11}, {80, 33}, {18, 11}, {15, 11}, {64, 33}, {160, 99}, {4,  3}, {3,  2}, {2,  1}};if (aspect_ratio_idc < sizeof(aspect_ratios)/sizeof(aspect_ratios[0])) {memcpy(&sps->pixel_aspect, &aspect_ratios[aspect_ratio_idc], sizeof(mpeg_rational_t));printf("H.264 SPS: -> aspect ratio %d / %d", sps->pixel_aspect.num, sps->pixel_aspect.den);} else {printf("H.264 SPS: aspect_ratio_idc out of range !");}}}}printf("H.264 SPS: -> video size %dx%d, aspect %d:%d",sps->width, sps->height, sps->pixel_aspect.num, sps->pixel_aspect.den);return 1;
}

标记位00 00 00 01    00 00 01 解析上有缺陷,关键帧数据解析出sps,直接传sps,方法好用!

H264解析sps提取宽高(好用)相关推荐

  1. css设置元素的宽高为整数,为什么有的浏览器解析出来的宽高是小数?

    如图: 因为把当前的标签页缩放显示了,所以浏览器会渲染出非整数的盒子尺寸 参考文章:css设置元素的宽高为整数,为什么有的浏览器解析出来的宽高是小数? - 孙北吉的回答 - 知乎

  2. 音视频系列--哥伦布编码和H264片段sps解析宽高信息

    H.264码流中的NALU进行了一个简单的划分,标出了NALU的类型和长度等信息.因为我们在解析SPS和PPS中要使用到指数哥伦布编码的解析,所以有必要了解一下指数哥伦布编码. 一.指数哥伦布编码(理 ...

  3. 解析H264的SPS信息

    原文链接 在做音视频开发的时候,存在不解码视频帧的前提下需要获取视频宽高.帧率等信息,而H.264中的SPS数据可为我们提供这些相关的信息.在此之前,我们需要对一些协议和算法有一定的初步了解,后文中有 ...

  4. 视频知识点(20)- H264码流如何在SPS中获取宽高信息?

    <音视频开发>系列-总览 前沿 了解H264视频编码格式的小伙伴都知道,H264编码中存在两个非常重要的参数集.没错,它们就是序列参数集(SPS)和图像参数集(PPS),而且通常情况下,P ...

  5. H264之sps解析分辨率

    sps定义如下: 解析如下: 分辨率: 宽高可从SPS字段计算得到,公式如下: Width = (pic_width_in_mbs_minus1+1)*16; Height = (pic_height ...

  6. H264码流解析(三):解析SPS和PPS

    上两篇里面写了划分NALU和指数哥伦布编码,这一篇主要写解析SPS和PPS. 1.下载bs.h头文件 下载bs.h头文件,并在项目中使用 下载地址 2.解析SPS H264官方文档英文版下载 先看SP ...

  7. 从h264码流中获取图像的宽高---版本1 (移植于ffmpeg)

    在工程中,我们常常需要知道视频流的宽高,虽然可以借助一些开源库,但是仅为了获取宽高,却需要调用几十或是几百K的开源库,不太划算.因此,本文从开源库中移植了解析264码流宽高的代码,具体如下: ##1 ...

  8. H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流

    SkySeraph Apr 1st 2012 Email:skyseraph00@163.com 一.MP4格式基本概念 MP4格式对应标准MPEG-4标准(ISO/IEC14496) 二.MP4封装 ...

  9. html获取此次点击的id,github项目解析(八)--Activity启动过程中获取组件宽高的三种方式...

    转载请标明出处:1片枫叶的专栏 上1个github小项目中我们介绍了避免按钮重复点击的小框架,其实现的核心逻辑是重写OnClickListener的onClick方法,添加避免重复点击的逻辑,即为第2 ...

最新文章

  1. 嵌入式开发有年龄限制吗_2021年考监理工程师有年龄限制吗?女生可以考监理工程师吗?...
  2. Tensorflow-gpu1.13.1 和 Tensorflow-gpu2.0.0共存之安装教程
  3. python 画三维函数图-Python之Numpy:二元函数绘制/三维数据可视化/3D
  4. JavaScript实现detectDirectedCycle检测定向循环算法(附完整源码)
  5. Qt Creator运行自动测试
  6. My SQL出错代码及出错信息对照
  7. VS2017 调用Tesseract
  8. C# 读写Ini文件
  9. matlab线性拉伸函数,采用线性变换对图像的每一个像素灰度作线性拉伸-Read.PPT
  10. NAS实现类型对比:统一式、网关式和横向扩展式(Scale-out)
  11. 做游戏,学编程(C语言) 10 僵尸危机
  12. python3 asyncio 不阻塞_Python中的并发处理之asyncio包使用的详解
  13. 对称构型机器人轮直径校准思路
  14. font-spider(字蛛) 让页面引入中文web字体
  15. 一键关闭 openwrt路由器的led灯
  16. 数字签名工具signtool
  17. 基于matlab的谐波处理及无功功率补偿源码,谐波抑制和无功功率补偿(第3版) pdf epub mobi txt 下载...
  18. 强连通分量(Tarjan算法)
  19. 基于DAC8563模块的低速模拟振镜驱动,实现直线插补,点到点划线
  20. 1044 : 不及格率

热门文章

  1. string转换long
  2. springboot报错(三) webjars被拦截或找不到
  3. 【TS TSP】基于matlab禁忌搜索求解旅行商问题【含Matlab源码 447期】
  4. 不能对多重选定区域使用此命令
  5. SSM三大框架整合(Spring+SpringMVC+MyBatis)
  6. 编程资料 -C# 多线程
  7. 715. Range Module
  8. 保罗·奥兰德:预测金融市场走势
  9. 机器人巨头争霸,谁主沉浮?
  10. 第十八次CCF计算机软件能力认证