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

##1 代码源自ffmpeg
###1.1 新建get_bits.h文件

#ifndef AVCODEC_GET_BITS_H
#define AVCODEC_GET_BITS_H#include <stdint.h>#ifdef WIN
#define inline __inline
#else
#define inline
#endiftypedef struct GetBitContext {const uint8_t *buffer, *buffer_end;int index;int size_in_bits;int size_in_bits_plus8;
} GetBitContext;#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)#ifndef AV_RB32
#   define AV_RB32(x)                                \(((uint32_t)((const uint8_t*)(x))[0] << 24) |    \(((const uint8_t*)(x))[1] << 16) |    \(((const uint8_t*)(x))[2] <<  8) |    \((const uint8_t*)(x))[3])
#endif#define OPEN_READER_NOSIZE(name, gb)            \unsigned int name ## _index = (gb)->index;  \unsigned int /*av_unused*/ name ## _cache#define OPEN_READER(name, gb)                   \OPEN_READER_NOSIZE(name, gb);               \unsigned int name ## _size_plus8 = (gb)->size_in_bits_plus8#define CLOSE_READER(name, gb) (gb)->index = name ## _index# define UPDATE_CACHE_BE(name, gb) name ## _cache = \AV_RB32((gb)->buffer + (name ## _index >> 3)) << (name ## _index & 7)# define UPDATE_CACHE(name, gb) UPDATE_CACHE_BE(name, gb)#   define SKIP_COUNTER(name, gb, num) \name ## _index = FFMIN(name ## _size_plus8, name ## _index + (num))#define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num)#define GET_CACHE(name, gb) ((uint32_t) name ## _cache)#   define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s)))
#define SHOW_UBITS_BE(name, gb, num) NEG_USR32(name ## _cache, num)
#   define SHOW_UBITS(name, gb, num) SHOW_UBITS_BE(name, gb, num)const static uint8_t ff_log2_tab[256]={0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};const static uint8_t ff_golomb_vlc_len[512] = {19, 17, 15, 15, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, 11, 11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};const static uint8_t ff_ue_golomb_vlc_code[512] = {32, 32, 32, 32, 32, 32, 32, 32, 31, 32, 32, 32, 32, 32, 32, 32, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14,3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};const static int8_t ff_se_golomb_vlc_code[512] = {17, 17, 17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17, 17, 17, 8, -8, 9, -9, 10, -10, 11, -11, 12, -12, 13, -13, 14, -14, 15, -15,4, 4, 4, 4, -4, -4, -4, -4, 5, 5, 5, 5, -5, -5, -5, -5, 6, 6, 6, 6, -6, -6, -6, -6, 7, 7, 7, 7, -7, -7, -7, -7,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};#ifndef ff_log2
#define ff_log2 ff_log2_c
static /*av_always_inline av_const*/ int ff_log2_c(unsigned int v)
{int n = 0;if (v & 0xffff0000) {v >>= 16;n += 16;}if (v & 0xff00) {v >>= 8;n += 8;}n += ff_log2_tab[v];return n;
}
#endif#define av_log2       ff_log2/**
* Read 1-25 bits.
*/
static inline unsigned int get_bits(GetBitContext *s, int n)
{register int tmp;OPEN_READER(re, s);//av_assert2(n>0 && n <= 25);UPDATE_CACHE(re, s);tmp = SHOW_UBITS(re, s, n);LAST_SKIP_BITS(re, s, n);CLOSE_READER(re, s);return tmp;
}static inline unsigned int get_bits1(GetBitContext *s)
{unsigned int index = s->index;uint8_t result = s->buffer[index >> 3];
#ifdef BITSTREAM_READER_LEresult >>= index & 7;result &= 1;
#elseresult <<= index & 7;result >>= 8 - 1;
#endif
#if 1//!UNCHECKED_BITSTREAM_READERif (s->index < s->size_in_bits_plus8)
#endifindex++;s->index = index;return result;
}static inline void skip_bits(GetBitContext *s, int n)
{OPEN_READER(re, s);LAST_SKIP_BITS(re, s, n);CLOSE_READER(re, s);
}/**
* read unsigned exp golomb code, constraint to a max of 31.
* the return value is undefined if the stored value exceeds 31.
*/
static inline int get_ue_golomb_31(GetBitContext *gb)
{unsigned int buf;OPEN_READER(re, gb);UPDATE_CACHE(re, gb);buf = GET_CACHE(re, gb);buf >>= 32 - 9;LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);CLOSE_READER(re, gb);return ff_ue_golomb_vlc_code[buf];
}/**
* Read an unsigned Exp-Golomb code in the range 0 to 8190.
*/
static inline int get_ue_golomb(GetBitContext *gb)
{unsigned int buf;OPEN_READER(re, gb);UPDATE_CACHE(re, gb);buf = GET_CACHE(re, gb);if (buf >= (1 << 27)) {buf >>= 32 - 9;LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);CLOSE_READER(re, gb);return ff_ue_golomb_vlc_code[buf];}else {int log = 2 * av_log2(buf) - 31;LAST_SKIP_BITS(re, gb, 32 - log);CLOSE_READER(re, gb);if (log < 7) {//av_log(NULL, AV_LOG_ERROR, "Invalid UE golomb code\n");return -1;//AVERROR_INVALIDDATA;}buf >>= log;buf--;return buf;}
}/**
* read signed exp golomb code.
*/
static inline int get_se_golomb(GetBitContext *gb)
{unsigned int buf;OPEN_READER(re, gb);UPDATE_CACHE(re, gb);buf = GET_CACHE(re, gb);if (buf >= (1 << 27)) {buf >>= 32 - 9;LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);CLOSE_READER(re, gb);return ff_se_golomb_vlc_code[buf];}else {int log = av_log2(buf), sign;LAST_SKIP_BITS(re, gb, 31 - log);UPDATE_CACHE(re, gb);buf = GET_CACHE(re, gb);buf >>= log;LAST_SKIP_BITS(re, gb, 32 - log);CLOSE_READER(re, gb);sign = -(buf & 1);buf = ((buf >> 1) ^ sign) - sign;return buf;}
}#endif

###1.2 新建parser_sps.h文件

#ifndef _H264_PARSER_SPS
#define _H264_PARSER_SPS#include <stdint.h>
#include "get_bits.h"#ifdef WIN
#define inline __inline
#else
#define inline
#endif#define MAX_SPS_COUNT     32
#define MAX_LOG2_MAX_FRAME_NUM    (12 + 4)
#define MIN_LOG2_MAX_FRAME_NUM    4#define MAX_DELAYED_PIC_COUNT  16#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))/*** Rational number (pair of numerator and denominator).*/
typedef struct AVRational{int num; ///< Numeratorint den; ///< Denominator
} AVRational;/*** H264Context*/
typedef struct H264Context {GetBitContext gb;// =============================================================// Things below are not used in the MB or more inner codeint nal_ref_idc;int nal_unit_type;uint8_t *rbsp_buffer[2];unsigned int rbsp_buffer_size[2];int is_avc;           ///< this flag is != 0 if codec is avc1int nal_length_size;  ///< Number of bytes used for nal length (1, 2 or 4)
} H264Context;/* NAL unit types */
enum {NAL_SLICE           = 1,NAL_DPA             = 2,NAL_DPB             = 3,NAL_DPC             = 4,NAL_IDR_SLICE       = 5,NAL_SEI             = 6,NAL_SPS             = 7,NAL_PPS             = 8,NAL_AUD             = 9,NAL_END_SEQUENCE    = 10,NAL_END_STREAM      = 11,NAL_FILLER_DATA     = 12,NAL_SPS_EXT         = 13,NAL_AUXILIARY_SLICE = 19,NAL_FF_IGNORE       = 0xff0f001,
};/*** Chromaticity coordinates of the source primaries.*/
enum AVColorPrimaries {AVCOL_PRI_RESERVED0   = 0,AVCOL_PRI_BT709       = 1,  ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex BAVCOL_PRI_UNSPECIFIED = 2,AVCOL_PRI_RESERVED    = 3,AVCOL_PRI_BT470M      = 4,  ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)AVCOL_PRI_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAMAVCOL_PRI_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSCAVCOL_PRI_SMPTE240M   = 7,  ///< functionally identical to aboveAVCOL_PRI_FILM        = 8,  ///< colour filters using Illuminant CAVCOL_PRI_BT2020      = 9,  ///< ITU-R BT2020AVCOL_PRI_SMPTEST428_1 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ)AVCOL_PRI_SMPTE431    = 11, ///< SMPTE ST 431-2 (2011)AVCOL_PRI_SMPTE432    = 12, ///< SMPTE ST 432-1 D65 (2010)AVCOL_PRI_NB                ///< Not part of ABI
};/*** Color Transfer Characteristic.*/
enum AVColorTransferCharacteristic {AVCOL_TRC_RESERVED0    = 0,AVCOL_TRC_BT709        = 1,  ///< also ITU-R BT1361AVCOL_TRC_UNSPECIFIED  = 2,AVCOL_TRC_RESERVED     = 3,AVCOL_TRC_GAMMA22      = 4,  ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAMAVCOL_TRC_GAMMA28      = 5,  ///< also ITU-R BT470BGAVCOL_TRC_SMPTE170M    = 6,  ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSCAVCOL_TRC_SMPTE240M    = 7,AVCOL_TRC_LINEAR       = 8,  ///< "Linear transfer characteristics"AVCOL_TRC_LOG          = 9,  ///< "Logarithmic transfer characteristic (100:1 range)"AVCOL_TRC_LOG_SQRT     = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)"AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4AVCOL_TRC_BT1361_ECG   = 12, ///< ITU-R BT1361 Extended Colour GamutAVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)AVCOL_TRC_BT2020_10    = 14, ///< ITU-R BT2020 for 10-bit systemAVCOL_TRC_BT2020_12    = 15, ///< ITU-R BT2020 for 12-bit systemAVCOL_TRC_SMPTEST2084  = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systemsAVCOL_TRC_SMPTEST428_1 = 17, ///< SMPTE ST 428-1AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"AVCOL_TRC_NB                 ///< Not part of ABI
};/*** YUV colorspace type.*/
enum AVColorSpace {AVCOL_SPC_RGB         = 0,  ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)AVCOL_SPC_BT709       = 1,  ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex BAVCOL_SPC_UNSPECIFIED = 2,AVCOL_SPC_RESERVED    = 3,AVCOL_SPC_FCC         = 4,  ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)AVCOL_SPC_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601AVCOL_SPC_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSCAVCOL_SPC_SMPTE240M   = 7,  ///< functionally identical to aboveAVCOL_SPC_YCOCG       = 8,  ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16AVCOL_SPC_BT2020_NCL  = 9,  ///< ITU-R BT2020 non-constant luminance systemAVCOL_SPC_BT2020_CL   = 10, ///< ITU-R BT2020 constant luminance systemAVCOL_SPC_SMPTE2085   = 11, ///< SMPTE 2085, Y'D'zD'xAVCOL_SPC_NB                ///< Not part of ABI
};/*** Sequence parameter set*/
typedef struct SPS {unsigned int sps_id;int profile_idc;int level_idc;int chroma_format_idc;int transform_bypass;              ///< qpprime_y_zero_transform_bypass_flagint log2_max_frame_num;            ///< log2_max_frame_num_minus4 + 4int poc_type;                      ///< pic_order_cnt_typeint log2_max_poc_lsb;              ///< log2_max_pic_order_cnt_lsb_minus4int delta_pic_order_always_zero_flag;int offset_for_non_ref_pic;int offset_for_top_to_bottom_field;int poc_cycle_length;              ///< num_ref_frames_in_pic_order_cnt_cycleint ref_frame_count;               ///< num_ref_framesint gaps_in_frame_num_allowed_flag;int mb_width;                      ///< pic_width_in_mbs_minus1 + 1int mb_height;                     ///< pic_height_in_map_units_minus1 + 1int frame_mbs_only_flag;int mb_aff;                        ///< mb_adaptive_frame_field_flagint direct_8x8_inference_flag;int crop;                          ///< frame_cropping_flagint width, height;/* those 4 are already in luma samples */unsigned int crop_left;            ///< frame_cropping_rect_left_offsetunsigned int crop_right;           ///< frame_cropping_rect_right_offsetunsigned int crop_top;             ///< frame_cropping_rect_top_offsetunsigned int crop_bottom;          ///< frame_cropping_rect_bottom_offsetint vui_parameters_present_flag;AVRational sar;int video_signal_type_present_flag;int full_range;int colour_description_present_flag;enum AVColorPrimaries color_primaries;enum AVColorTransferCharacteristic color_trc;enum AVColorSpace colorspace;int timing_info_present_flag;uint32_t num_units_in_tick;uint32_t time_scale;int fixed_frame_rate_flag;short offset_for_ref_frame[256]; // FIXME dyn aloc?int bitstream_restriction_flag;int num_reorder_frames;int scaling_matrix_present;uint8_t scaling_matrix4[6][16];uint8_t scaling_matrix8[6][64];int nal_hrd_parameters_present_flag;int vcl_hrd_parameters_present_flag;int pic_struct_present_flag;int time_offset_length;int cpb_cnt;                          ///< See H.264 E.1.2int initial_cpb_removal_delay_length; ///< initial_cpb_removal_delay_length_minus1 + 1int cpb_removal_delay_length;         ///< cpb_removal_delay_length_minus1 + 1int dpb_output_delay_length;          ///< dpb_output_delay_length_minus1 + 1int bit_depth_luma;                   ///< bit_depth_luma_minus8 + 8int bit_depth_chroma;                 ///< bit_depth_chroma_minus8 + 8int residual_color_transform_flag;    ///< residual_colour_transform_flagint constraint_set_flags;             ///< constraint_set[0-3]_flaguint8_t data[4096];size_t data_size;
} SPS;void *h264Ps_Open();
int h264Ps_Parser(H264Context *h, const uint8_t * const buf, int buf_size, H264SPS *sps);
void h264Ps_Close(void *handle);#endif

###1.3 新建parser_sps.c文件

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "get_bits.h"
#include "parser_sps.h"static const uint8_t default_scaling4[2][16] = {{  6, 13, 20, 28, 13, 20, 28, 32,20, 28, 32, 37, 28, 32, 37, 42 },{ 10, 14, 20, 24, 14, 20, 24, 27,20, 24, 27, 30, 24, 27, 30, 34 }
};static const uint8_t default_scaling8[2][64] = {{  6, 10, 13, 16, 18, 23, 25, 27,10, 11, 16, 18, 23, 25, 27, 29,13, 16, 18, 23, 25, 27, 29, 31,16, 18, 23, 25, 27, 29, 31, 33,18, 23, 25, 27, 29, 31, 33, 36,23, 25, 27, 29, 31, 33, 36, 38,25, 27, 29, 31, 33, 36, 38, 40,27, 29, 31, 33, 36, 38, 40, 42 },{  9, 13, 15, 17, 19, 21, 22, 24,13, 13, 17, 19, 21, 22, 24, 25,15, 17, 19, 21, 22, 24, 25, 27,17, 19, 21, 22, 24, 25, 27, 28,19, 21, 22, 24, 25, 27, 28, 30,21, 22, 24, 25, 27, 28, 30, 32,22, 24, 25, 27, 28, 30, 32, 33,24, 25, 27, 28, 30, 32, 33, 35 }
};static const uint8_t ff_zigzag_direct[64] = {0,   1,  8, 16,  9,  2,  3, 10,17, 24, 32, 25, 18, 11,  4,  5,12, 19, 26, 33, 40, 48, 41, 34,27, 20, 13,  6,  7, 14, 21, 28,35, 42, 49, 56, 57, 50, 43, 36,29, 22, 15, 23, 30, 37, 44, 51,58, 59, 52, 45, 38, 31, 39, 46,53, 60, 61, 54, 47, 55, 62, 63
};static const uint8_t ff_zigzag_scan[16+1] = {0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4,
};static int decode_scaling_list(GetBitContext *gb, uint8_t *factors, int size,const uint8_t *jvt_list,const uint8_t *fallback_list)
{int i, last = 8, next = 8;const uint8_t *scan = size == 16 ? ff_zigzag_scan : ff_zigzag_direct;if (!get_bits1(gb)) /* matrix not written, we use the predicted one */memcpy(factors, fallback_list, size * sizeof(uint8_t));elsefor (i = 0; i < size; i++) {if (next) {int v = get_se_golomb(gb);if (v < -128 || v > 127) {return -1;}next = (last + v) & 0xff;}if (!i && !next) { /* matrix not written, we use the preset one */memcpy(factors, jvt_list, size * sizeof(uint8_t));break;}last = factors[scan[i]] = next ? next : last;}return 0;
}/* returns non zero if the provided SPS scaling matrix has been filled */
static int decode_scaling_matrices(GetBitContext *gb, const SPS *sps,void *pps, int is_sps,uint8_t(*scaling_matrix4)[16],uint8_t(*scaling_matrix8)[64])
{int transform_8x8_mode = 0;int fallback_sps = !is_sps && sps->scaling_matrix_present;const uint8_t *fallback[4] = {fallback_sps ? sps->scaling_matrix4[0] : default_scaling4[0],fallback_sps ? sps->scaling_matrix4[3] : default_scaling4[1],fallback_sps ? sps->scaling_matrix8[0] : default_scaling8[0],fallback_sps ? sps->scaling_matrix8[3] : default_scaling8[1]};int ret = 0;if (get_bits1(gb)) {ret |= decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]);        // Intra, Yret |= decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Crret |= decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cbret |= decode_scaling_list(gb, scaling_matrix4[3], 16, default_scaling4[1], fallback[1]);        // Inter, Yret |= decode_scaling_list(gb, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3]); // Inter, Crret |= decode_scaling_list(gb, scaling_matrix4[5], 16, default_scaling4[1], scaling_matrix4[4]); // Inter, Cbif (is_sps || transform_8x8_mode) {ret |= decode_scaling_list(gb, scaling_matrix8[0], 64, default_scaling8[0], fallback[2]); // Intra, Yret |= decode_scaling_list(gb, scaling_matrix8[3], 64, default_scaling8[1], fallback[3]); // Inter, Yif (sps->chroma_format_idc == 3) {ret |= decode_scaling_list(gb, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0]); // Intra, Crret |= decode_scaling_list(gb, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3]); // Inter, Crret |= decode_scaling_list(gb, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1]); // Intra, Cbret |= decode_scaling_list(gb, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4]); // Inter, Cb}}if (!ret)ret = is_sps;}return ret;
}int ff_h264_decode_seq_parameter_set(GetBitContext *gb, SPS* sps)
{int profile_idc, level_idc, constraint_set_flags = 0, reserved_zero_2bits;unsigned int sps_id;int i, log2_max_frame_num_minus4;  profile_idc           = get_bits(gb, 8);constraint_set_flags |= get_bits1(gb) << 0;   // constraint_set0_flagconstraint_set_flags |= get_bits1(gb) << 1;   // constraint_set1_flagconstraint_set_flags |= get_bits1(gb) << 2;   // constraint_set2_flagconstraint_set_flags |= get_bits1(gb) << 3;   // constraint_set3_flagconstraint_set_flags |= get_bits1(gb) << 4;   // constraint_set4_flagconstraint_set_flags |= get_bits1(gb) << 5;   // constraint_set5_flag//reserved_zero_2bits     = h264_bs_read_u(gb,2);skip_bits(gb, 2);                             // reserved_zero_2bitslevel_idc = get_bits(gb, 8);sps_id    = get_ue_golomb_31(gb);if (sps_id >= MAX_SPS_COUNT) {goto fail;}sps->sps_id               = sps_id;sps->time_offset_length   = 24;sps->profile_idc          = profile_idc;sps->constraint_set_flags = constraint_set_flags;sps->level_idc            = level_idc;sps->full_range           = -1;memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4));memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8));sps->scaling_matrix_present = 0;sps->colorspace = 2; //AVCOL_SPC_UNSPECIFIEDif (sps->profile_idc == 100 ||  // High profilesps->profile_idc == 110 ||  // High10 profilesps->profile_idc == 122 ||  // High422 profilesps->profile_idc == 244 ||  // High444 Predictive profilesps->profile_idc ==  44 ||  // Cavlc444 profilesps->profile_idc ==  83 ||  // Scalable Constrained High profile (SVC)sps->profile_idc ==  86 ||  // Scalable High Intra profile (SVC)sps->profile_idc == 118 ||  // Stereo High profile (MVC)sps->profile_idc == 128 ||  // Multiview High profile (MVC)sps->profile_idc == 138 ||  // Multiview Depth High profile (MVCD)sps->profile_idc == 144) {  // old High444 profilesps->chroma_format_idc = get_ue_golomb_31(gb);if (sps->chroma_format_idc > 3U) {goto fail;} else if (sps->chroma_format_idc == 3) {sps->residual_color_transform_flag = get_bits1(gb);if (sps->residual_color_transform_flag) {goto fail;}}sps->bit_depth_luma   = get_ue_golomb(gb) + 8;sps->bit_depth_chroma = get_ue_golomb(gb) + 8;if (sps->bit_depth_chroma != sps->bit_depth_luma) {goto fail;}if (sps->bit_depth_luma   < 8 || sps->bit_depth_luma   > 14 ||sps->bit_depth_chroma < 8 || sps->bit_depth_chroma > 14) {goto fail;}sps->transform_bypass = get_bits1(gb);sps->scaling_matrix_present |= decode_scaling_matrices(gb, sps, NULL, 1,sps->scaling_matrix4, sps->scaling_matrix8);} else {sps->chroma_format_idc = 1;sps->bit_depth_luma    = 8;sps->bit_depth_chroma  = 8;}log2_max_frame_num_minus4 = get_ue_golomb(gb);if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 ||log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) {goto fail;}sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4;sps->poc_type = get_ue_golomb_31(gb);if (sps->poc_type == 0) { // FIXME #defineunsigned t = get_ue_golomb(gb);if (t>12) {goto fail;}sps->log2_max_poc_lsb = t + 4;} else if (sps->poc_type == 1) { // FIXME #definesps->delta_pic_order_always_zero_flag = get_bits1(gb);sps->offset_for_non_ref_pic           = get_se_golomb(gb);sps->offset_for_top_to_bottom_field   = get_se_golomb(gb);sps->poc_cycle_length                 = get_ue_golomb(gb);if ((unsigned)sps->poc_cycle_length >=FF_ARRAY_ELEMS(sps->offset_for_ref_frame)) {goto fail;}for (i = 0; i < sps->poc_cycle_length; i++)sps->offset_for_ref_frame[i] = get_se_golomb(gb);} else if (sps->poc_type != 2) {goto fail;}sps->ref_frame_count = get_ue_golomb_31(gb);if (sps->ref_frame_count > MAX_DELAYED_PIC_COUNT) {goto fail;}sps->gaps_in_frame_num_allowed_flag = get_bits1(gb);sps->mb_width                       = get_ue_golomb(gb) + 1;sps->mb_height                      = get_ue_golomb(gb) + 1;sps->frame_mbs_only_flag = get_bits1(gb);sps->mb_height *= 2 - sps->frame_mbs_only_flag;if (!sps->frame_mbs_only_flag)sps->mb_aff = get_bits1(gb);elsesps->mb_aff = 0;if ((unsigned)sps->mb_width  >= INT_MAX / 16 ||(unsigned)sps->mb_height >= INT_MAX / (16 * (2 - sps->frame_mbs_only_flag)) ) {goto fail;}sps->direct_8x8_inference_flag = get_bits1(gb);sps->crop = get_bits1(gb);sps->width =  16 * sps->mb_width;sps->height = 16 * sps->mb_height;if (sps->crop) {unsigned int crop_left   = get_ue_golomb(gb);unsigned int crop_right  = get_ue_golomb(gb);unsigned int crop_top    = get_ue_golomb(gb);unsigned int crop_bottom = get_ue_golomb(gb);int width  = 16 * sps->mb_width;int height = 16 * sps->mb_height * (2 - sps->frame_mbs_only_flag);sps->width = width;sps->height = height;if (0) {sps->crop_left   =sps->crop_right  =sps->crop_top    =sps->crop_bottom = 0;} else {int vsub   = (sps->chroma_format_idc == 1) ? 1 : 0;int hsub   = (sps->chroma_format_idc == 1 ||sps->chroma_format_idc == 2) ? 1 : 0;int step_x = 1 << hsub;int step_y = (2 - sps->frame_mbs_only_flag) << vsub;if (crop_left & (0x1F >> (sps->bit_depth_luma > 8))) {crop_left &= ~(0x1F >> (sps->bit_depth_luma > 8));}if (crop_left  > (unsigned)INT_MAX / 4 / step_x ||crop_right > (unsigned)INT_MAX / 4 / step_x ||crop_top   > (unsigned)INT_MAX / 4 / step_y ||crop_bottom> (unsigned)INT_MAX / 4 / step_y ||(crop_left + crop_right ) * step_x >= width ||(crop_top  + crop_bottom) * step_y >= height) {goto fail;}sps->crop_left   = crop_left   * step_x;sps->crop_right  = crop_right  * step_x;sps->crop_top    = crop_top    * step_y;sps->crop_bottom = crop_bottom * step_y;}} else {sps->crop_left   =sps->crop_right  =sps->crop_top    =sps->crop_bottom =sps->crop        = 0;}sps->vui_parameters_present_flag = get_bits1(gb);if (sps->vui_parameters_present_flag) {int ret = 0;//decode_vui_parameters(gb, avctx, sps);if (ret < 0)goto fail;}return 0;fail:return -1;
}/*** Initialize GetBitContext.* @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes*        larger than the actual read bits because some optimized bitstream*        readers read 32 or 64 bit at once and could read over the end* @param bit_size the size of the buffer in bits* @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow.*/
static /*inline*/ int init_get_bits(GetBitContext *s, const uint8_t *buffer,int bit_size)
{int buffer_size;int ret = 0;if (bit_size >= INT_MAX - 7 || bit_size < 0 || !buffer) {bit_size    = 0;buffer      = NULL;ret         = -1;//AVERROR_INVALIDDATA;}buffer_size = (bit_size + 7) >> 3;s->buffer             = buffer;s->size_in_bits       = bit_size;s->size_in_bits_plus8 = bit_size + 8;s->buffer_end         = buffer + buffer_size;s->index              = 0;return ret;
}static inline int get_avc_nalsize(H264Context *h, const uint8_t *buf,int buf_size, int *buf_index)
{int i, nalsize = 0;if (*buf_index >= buf_size - h->nal_length_size)return -1;for (i = 0; i < h->nal_length_size; i++)nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];if (nalsize <= 0 || nalsize > buf_size - *buf_index) {/*av_log(h->avctx, AV_LOG_ERROR,"AVC: nal size %d\n", nalsize);*/return -1;}return nalsize;
}const uint8_t *avpriv_find_start_code(const uint8_t */*av_restrict*/ p,const uint8_t *end,uint32_t */*av_restrict*/ state)
{int i;//av_assert0(p <= end);if (p >= end)return end;for (i = 0; i < 3; i++) {uint32_t tmp = *state << 8;*state = tmp + *(p++);if (tmp == 0x100 || p == end)return p;}while (p < end) {if      (p[-1] > 1      ) p += 3;else if (p[-2]          ) p += 2;else if (p[-3]|(p[-1]-1)) p++;else {p++;break;}}p = FFMIN(p, end) - 4;*state = AV_RB32(p);return p + 4;
}static inline int find_start_code(const uint8_t *buf, int buf_size,int buf_index, int next_avc)
{uint32_t state = -1;buf_index = avpriv_find_start_code(buf + buf_index, buf + next_avc + 1, &state) - buf - 1;return FFMIN(buf_index, buf_size);
}#define FF_INPUT_BUFFER_PADDING_SIZE 32
#define MAX_MBPAIR_SIZE (256*1024) // a tighter bound could be calculated if someone cares about a few bytesstatic size_t max_alloc_size= INT_MAX;
void *av_malloc(size_t size)
{void *ptr = NULL;
#if CONFIG_MEMALIGN_HACKlong diff;
#endif/* let's disallow possibly ambiguous cases */if (size > (max_alloc_size - 32))return NULL;#if CONFIG_MEMALIGN_HACKptr = malloc(size + ALIGN);if (!ptr)return ptr;diff              = ((~(long)ptr)&(ALIGN - 1)) + 1;ptr               = (char *)ptr + diff;((char *)ptr)[-1] = diff;
#elif HAVE_POSIX_MEMALIGNif (size) //OS X on SDK 10.6 has a broken posix_memalign implementationif (posix_memalign(&ptr, ALIGN, size))ptr = NULL;
#elif HAVE_ALIGNED_MALLOCptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__ptr = memalign(ALIGN, size);
#elseptr = memalign(size, ALIGN);
#endif/* Why 64?* Indeed, we should align it:*   on  4 for 386*   on 16 for 486*   on 32 for 586, PPro - K6-III*   on 64 for K7 (maybe for P3 too).* Because L1 and L2 caches are aligned on those values.* But I don't want to code such logic here!*//* Why 32?* For AVX ASM. SSE / NEON needs only 16.* Why not larger? Because I did not see a difference in benchmarks ...*//* benchmarks with P3* memalign(64) + 1          3071, 3051, 3032* memalign(64) + 2          3051, 3032, 3041* memalign(64) + 4          2911, 2896, 2915* memalign(64) + 8          2545, 2554, 2550* memalign(64) + 16         2543, 2572, 2563* memalign(64) + 32         2546, 2545, 2571* memalign(64) + 64         2570, 2533, 2558** BTW, malloc seems to do 8-byte alignment by default here.*/
#elseptr = malloc(size);
#endifif(!ptr && !size) {size = 1;ptr= av_malloc(1);}
#if CONFIG_MEMORY_POISONINGif (ptr)memset(ptr, FF_MEMORY_POISON, size);
#endifreturn ptr;
}void *av_mallocz(size_t size)
{void *ptr = av_malloc(size);if (ptr)memset(ptr, 0, size);return ptr;
}void av_free(void *ptr)
{
#if CONFIG_MEMALIGN_HACKif (ptr) {int v= ((char *)ptr)[-1];av_assert0(v>0 && v<=ALIGN);free((char *)ptr - v);}
#elif HAVE_ALIGNED_MALLOC_aligned_free(ptr);
#elsefree(ptr);
#endif
}void av_freep(void *arg)
{void **ptr = (void **)arg;av_free(*ptr);*ptr = NULL;
}static inline int ff_fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc)
{void **p = ptr;if (min_size <= *size && *p)return 0;min_size = FFMAX(17 * min_size / 16 + 32, min_size);av_free(*p);*p = zero_realloc ? av_mallocz(min_size) : av_malloc(min_size);if (!*p)min_size = 0;*size = min_size;return 1;
}void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
{uint8_t **p = ptr;if (min_size > SIZE_MAX - FF_INPUT_BUFFER_PADDING_SIZE) {av_freep(p);*size = 0;return;}if (!ff_fast_malloc(p, size, min_size + FF_INPUT_BUFFER_PADDING_SIZE, 1))memset(*p + min_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
}const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src,int *dst_length, int *consumed, int length)
{int i, si, di;uint8_t *dst;int bufidx;// src[0]&0x80; // forbidden bith->nal_ref_idc   = src[0] >> 5;h->nal_unit_type = src[0] & 0x1F;src++;length--;#define STARTCODE_TEST                                                  \if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) {         \if (src[i + 2] != 3 && src[i + 2] != 0) {                       \/* startcode, so we must be past the end */                 \length = i;                                                 \}                                                               \break;                                                          \}#if HAVE_FAST_UNALIGNED
#define FIND_FIRST_ZERO                                                 \if (i > 0 && !src[i])                                               \i--;                                                            \while (src[i])                                                      \i++#if HAVE_FAST_64BITfor (i = 0; i + 1 < length; i += 9) {if (!((~AV_RN64A(src + i) &(AV_RN64A(src + i) - 0x0100010001000101ULL)) &0x8000800080008080ULL))continue;FIND_FIRST_ZERO;STARTCODE_TEST;i -= 7;}
#elsefor (i = 0; i + 1 < length; i += 5) {if (!((~AV_RN32A(src + i) &(AV_RN32A(src + i) - 0x01000101U)) &0x80008080U))continue;FIND_FIRST_ZERO;STARTCODE_TEST;i -= 3;}
#endif
#elsefor (i = 0; i + 1 < length; i += 2) {if (src[i])continue;if (i > 0 && src[i - 1] == 0)i--;STARTCODE_TEST;}
#endif// use second escape buffer for inter databufidx = h->nal_unit_type == NAL_DPC ? 1 : 0;av_fast_padded_malloc(&h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], length+MAX_MBPAIR_SIZE);dst = h->rbsp_buffer[bufidx];if (!dst)return NULL;if(i>=length-1){ //no escaped 0*dst_length= length;*consumed= length+1; //+1 for the headerif(1/*h->avctx->flags2 & CODEC_FLAG2_FAST*/){return src;}else{memcpy(dst, src, length);return dst;}}memcpy(dst, src, i);si = di = i;while (si + 2 < length) {// remove escapes (very rare 1:2^22)if (src[si + 2] > 3) {dst[di++] = src[si++];dst[di++] = src[si++];} else if (src[si] == 0 && src[si + 1] == 0 && src[si + 2] != 0) {if (src[si + 2] == 3) { // escapedst[di++]  = 0;dst[di++]  = 0;si        += 3;continue;} else // next start codegoto nsc;}dst[di++] = src[si++];}while (si < length)dst[di++] = src[si++];nsc:memset(dst + di, 0, FF_INPUT_BUFFER_PADDING_SIZE);*dst_length = di;*consumed   = si + 1; // +1 for the header/* FIXME store exact number of bits in the getbitcontext* (it is needed for decoding) */return dst;
}int h264Ps_Parser(H264Context *h, const uint8_t * const buf, int buf_size, H264SPS *sps)
{//H264Context *h         = s->priv_data;int buf_index, next_avc;unsigned int pps_id;unsigned int slice_type;int state = -1, got_reset = 0;const uint8_t *ptr;//int q264 = buf_size >=4 && !memcmp("Q264", buf, 4);int field_poc[2];/* set some sane default values *///s->pict_type         = AV_PICTURE_TYPE_I;//s->key_frame         = 0;//s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;//h->avctx = avctx;//ff_h264_reset_sei(h);//h->sei_fpa.frame_packing_arrangement_cancel_flag = -1;if (!buf_size)return 0;buf_index     = 0;next_avc      = h->is_avc ? 0 : buf_size;for (;;) {int src_length, dst_length, consumed, nalsize = 0;if (buf_index >= next_avc) {nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);if (nalsize < 0)break;next_avc = buf_index + nalsize;} else {buf_index = find_start_code(buf, buf_size, buf_index, next_avc);if (buf_index >= buf_size)break;if (buf_index >= next_avc)continue;}src_length = next_avc - buf_index;state = buf[buf_index];switch (state & 0x1f) {case NAL_SLICE:case NAL_IDR_SLICE:// Do not walk the whole buffer just to decode slice headerif ((state & 0x1f) == NAL_IDR_SLICE || ((state >> 5) & 0x3) == 0) {/* IDR or disposable slice* No need to decode many bytes because MMCOs shall not be present. */if (src_length > 60)src_length = 60;} else {/* To decode up to MMCOs */if (src_length > 1000)src_length = 1000;}break;}ptr = ff_h264_decode_nal(h, buf + buf_index, &dst_length,&consumed, src_length);if (!ptr || dst_length < 0)break;buf_index += consumed;init_get_bits(&h->gb, ptr, 8 * dst_length);switch (h->nal_unit_type) {case NAL_SPS:ff_h264_decode_seq_parameter_set(h, sps);break;}}//if (q264)//    return 0;/* didn't find a picture! *///av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit with size %d\n", buf_size);return -1;
}void *h264Ps_Open()
{H264Context *h;h = (H264Context *)malloc(sizeof(*h));if(h == NULL){return NULL;}memset(h, 0, sizeof(*h));return h;
}void h264Ps_Close(void *handle)
{H264Context *h = (H264Context*)handle;if(h){av_freep(&h->rbsp_buffer[1]);av_freep(&h->rbsp_buffer[0]);h->rbsp_buffer_size[0] = 0;h->rbsp_buffer_size[1] = 0;free(h);}
}

###1.4 新建parser_demo.c文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "parser_sps.h"void ParserH264Resolution(char *cpFileName, int *ipWidth, int *ipHeight)
{   FILE *fp;long len;unsigned char *buf;H264Context *h;H264SPS  sps;fp = fopen(cpFileName,"rb");fseek(fp,0,SEEK_END);len = ftell(fp);fseek(fp,0,SEEK_SET);buf = (unsigned char*) malloc (len+1);fread(buf,1,len,fp);fclose(fp);h = h264Ps_Open();if(h == NULL){printf("[h264Ps can't malloc memory!\n]");}h264Ps_Parser(h, buf, len, &sps);h264Ps_Close(h);free(buf);return;
}int main(int argc, char *argv[])
{int iHeight=0, iWidth=0;char *cpFileName = argv[1];ParserH264Resolution(cpFileName, &iWidth, &iHeight);return 0;
}

从h264码流中获取图像的宽高---版本1 (移植于ffmpeg)相关推荐

  1. 从h264码流中获取图像的宽高---版本2(简洁版)

    从264码流中获取图像的宽高,代码如下,注意代码文件应该为cpp文件 #include <stdio.h> #include <stdlib.h> #include <s ...

  2. H264码流中SPS、PPS详解

    1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SDP中包含的H.264的SPS和PPS串? 1 客户端抓包 在做客户端视频解码时,一般都会使用Wireshar ...

  3. H264码流中SPS的获取

    The h.264 Sequence Parameter Set April 20th, 2011 by Ben Mesander 此文对于想要了解如何获取h264码流中SPS参数的过程,但是又不是很 ...

  4. sps和pps一篇好的解释 H264码流中SPS PPS详解<转>

    https://blog.csdn.net/luzubodfgs/article/details/86775940 H264码流中NALU sps pps IDR帧的理解 https://blog.c ...

  5. H264码流中SPS PPS

    转载地址:https://www.cnblogs.com/wainiwann/p/7477794.html 1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SD ...

  6. 【H.264/AVC视频编解码技术】第二章【H264码流分析】

    H264码流分层 NAL层,视频数据网络抽象层,作用是控制二进制数据的传输,主要用于网络传输.  VCL层,视频数据编码层. VCL结构关系 NALU NAL Header (1B)+ RBSP H2 ...

  7. H264码流分析工具

    概述 本文作为一个笔记,记录笔者学习H264码流的过程.重点记录使用工具分析H264码流.使用该工具,可方便查看码流中NALU的结构,为我们学习和理解有很大帮助. H264码流介绍 笔者直接参考:ht ...

  8. H264码流RTP封装方式详解

    H264码流RTP封装方式详解 文章目录 H264码流RTP封装方式详解 1 H264基本概念 2 NALU Header介绍 3 RTP封装H264码流 3.1 单一NALU模式 3.2 组合帧封装 ...

  9. H264码流插入自定义数据(SEI字段)

    文章目录 前言 一.H264码流结构 1. 文字说明 2. 码流格式图解 二.自定义数据封装以及H264码流插入 1.将自定义数据封装成SEI字段通用格式即可插入H264码流中 2.编程逻辑 三.附上 ...

最新文章

  1. 贪吃蛇游戏(java)
  2. mysql返回记录的ROWNUM(转)
  3. (转)安装黑苹果 MAC OS X Lion 10.7.2过程 (未验证)
  4. linux 之 getopt_long()
  5. 手机屏幕什么计算机,windows 7系统中要实现智能手机无线投屏到计算机屏幕上可以借助的软件有哪些?...
  6. 虚拟机 centos 7 nginx安装
  7. poj1833 排列
  8. noip2002 矩形覆盖
  9. 如何用发票查验软件快速批量查验发票(返回官网查验截图)
  10. Sliced Sprite
  11. android逆向学习路线
  12. hash函数原理实现
  13. Gitlab搭建以及解决Failed asserting that ownership of /var/opt/gitlab/.ssh was git:git错误
  14. SSH端口转发Forwarding及隧道Tunneling
  15. 2016 年度开源中国新增开源软件排行榜 TOP 100
  16. java 向下转型运行时错误_8.5.2 向下转型与运行类型异常
  17. tokenizer.encode、tokenizer.tokenize、tokenizer.encode_plus的用法差异
  18. 【数据分析案例】英雄联盟美服10000条排位数据分析
  19. Kubernetes学习笔记十:部署Mysql、Redis和Shardingshere
  20. 软件工程个人阅读作业——阅读和调研

热门文章

  1. Maven 本地仓库访问私服
  2. Excel 中的日期格式变成时间戳
  3. vue.js2.0 java_详解vite2.0配置学习(typescript版本)
  4. php pdo总结,php 总结(10) PDO 连接数据库 预处理
  5. (转载)js对象原来也有类、实例属性和原型属性
  6. Oracle添加主键和唯一约束最佳实践
  7. java调用notify方法_Java线程,下面程序不知怎么调用notify方法唤醒test1,请指正
  8. git 修改commit_结合IDEA与命令行,解决常用git操作与特殊情况的最佳实践
  9. cmake 安装_linux下安装cmake
  10. 1用switch语句从控制台输入100以内的分数判断优秀,良好,及格不及格属于哪一个区间