h264 sps解析,提取宽高

1、sps 数据结构
1)、从Bit流中取出句法元素的方法。
|编号 | 语法 |说明|

1              ae(e)          CABAC
2              b(8)            读进连续的8个Bit
3              ce(v)          CAVLC
4              f(n)             读进连续的n个Bit
5              i(n)/i(v)    读进连续的若干Bit,并把它们解释为有符号整数
6              me(v)           映射指数Golomb熵编码
7              se(v)            有符号指数Golomb熵编码
8              te(v)             截断指数Golomb熵编码
9              u(n)/u(v)  读进连续的若干Bit,并把它们解释为无符号整数
10             ue(v)              无符号指数Golomb熵编码

主要是同过bitstream.h 进行处理的 代码如下:

# ifdef NOCACHE

typedef 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)

2、nal 语法
自己百度或google。这里就不介绍了,下面具体说下sps结构体里面的字段
3、sps
详细信息可以参考链接sps详解介绍
4、代码实现

#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)
#endif


    typedef 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__) */
#include "SPS.h"


#include <string.h>
#include <stdio.h>

#define NOCACHE 1
#include "BitStream.h"


int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps) {

        //find sps
    bool findSPS = false;

    if (buf[2] == 0) {
        if ((buf[4]&0x1f) == 7) { //start code 0 0 0 1
            len -= 5;
            buf += 5;
            findSPS = true;
        }
    } else if (buf[2] == 1) {//start code 0 0 1
        if ((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);
        else
            sps->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;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值