Mp4v2封装H264+AAC为MP4

来源:互联网 发布:js把字符串转成数组 编辑:程序博客网 时间:2024/06/06 15:05

本文介绍Mp4v2的使用,成功将H264 ES文件和AAC文件封装成MP4文件


1. Mp4V2使用VS2013编译

studio9.0\下打开方案

一般情况,编译会出现错误

原因是缺少几个关键文件:vstudio9.0\libmp4v2\Version.rc

Libplatform\platform_win32_impl.h  Libplatform\platform_win32.cpp

点击下载缺失文件(http://download.csdn.net/download/u011298831/9594523):点击打开链接

下载文件放入响应位置即可成功编译,生成bin\目录下的相关文件


2. 新建项目Mux

这里给出一个MP4Encoder的封装类

/********************************************************************filename:   MP4Encoder.hcreated:    2016-08-06author:     Donyjpurpose:    MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。*********************************************************************/#pragma once#include "mp4v2\mp4v2.h"// NALU单元typedef struct _MP4ENC_NaluUnit{int type;int size;unsigned char *data;}MP4ENC_NaluUnit;typedef struct _MP4ENC_Metadata{// video, must be h264 typeunsigned intnSpsLen;unsigned charSps[1024];unsigned intnPpsLen;unsigned charPps[1024];} MP4ENC_Metadata, *LPMP4ENC_Metadata;class MP4Encoder{public:MP4Encoder(void);~MP4Encoder(void);public:// open or creat a mp4 file.bool MP4FileOpen(const char *fileName, int width, int height, int timeScale = 90000, int frameRate = 25);// wirte 264 metadata in mp4 file.bool Write264Metadata(MP4FileHandle hMp4File, LPMP4ENC_Metadata lpMetadata);// wirte 264 data, data can contain  multiple frame.int WriteH264Data(MP4FileHandle hMp4File, const unsigned char* pData, int size);// close mp4 file.void MP4FileClose();// convert H264 file OR aac file to mp4 file.bool MP4FileWrite(int(*read_h264)(unsigned char *buf, int buf_size), int(*read_aac)(unsigned char *buf, int buf_size));// Prase H264 metamata from H264 data framestatic bool PraseMetadata(const unsigned char* pData, int size, MP4ENC_Metadata &metadata);private:// read one nalu from H264 data bufferstatic int ReadOneNaluFromBuf(const unsigned char *buffer, unsigned int nBufferSize, unsigned int offSet, MP4ENC_NaluUnit &nalu);private:int m_nWidth;int m_nHeight;double m_nFrameRate;int m_nTimeScale;MP4FileHandle m_hMp4File;MP4TrackId m_videoId;MP4TrackId m_audioId;};

本例存在使用默认已知参数的情况,读者可根据自己的情况修改参数,或者实时从数据中解析出来进行设置;一下是完整cpp文件:

/********************************************************************filename:   MP4Encoder.hcreated:    2016-08-06author:     Donyjpurpose:    MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。*********************************************************************/#include "MP4Encoder.h"//#include "sps_decode.h"#include <string.h>#include "sps_pps_parser.h"#include <stdio.h>#include <Windows.h>static double audio_tick_gap = (1024000.0) / (48000.0);static double video_tick_gap = (1000.0 + 1.0) / 30.0;static int sps_wt = 0; //确保sps已经 MP4AddH264SequenceParameterSetstatic int pps_wt = 0; //确保pps已经 MP4AddH264PictureParameterSet#define BUFFER_SIZE(1024*1024)#define FRAME_FRATE(30)#define TIME_SCALE(90000)MP4Encoder::MP4Encoder(void) :m_videoId(NULL),m_nWidth(0),m_nHeight(0),m_nTimeScale(TIME_SCALE),m_nFrameRate(FRAME_FRATE){m_hMp4File = NULL;m_audioId = NULL;}MP4Encoder::~MP4Encoder(void){if (m_hMp4File != NULL){MP4Close(m_hMp4File);m_hMp4File = NULL;}}bool MP4Encoder::MP4FileOpen(const char *pFileName, int width, int height, int timeScale/* = 90000*/, int frameRate/* = 25*/){if (pFileName == NULL){return false;}// create mp4 filem_hMp4File = MP4Create(pFileName);if (m_hMp4File == MP4_INVALID_FILE_HANDLE){printf("ERROR:Open file fialed.\n");return false;}m_nWidth = width;m_nHeight = height;m_nTimeScale = TIME_SCALE;m_nFrameRate = FRAME_FRATE;MP4SetTimeScale(m_hMp4File, m_nTimeScale);return true;}bool MP4Encoder::Write264Metadata(MP4FileHandle hMp4File, LPMP4ENC_Metadata lpMetadata){m_videoId = MP4AddH264VideoTrack(hMp4File,m_nTimeScale,m_nTimeScale / m_nFrameRate,m_nWidth, // widthm_nHeight,// heightlpMetadata->Sps[1], // sps[1] AVCProfileIndicationlpMetadata->Sps[2], // sps[2] profile_compatlpMetadata->Sps[3], // sps[3] AVCLevelIndication3);           // 4 bytes length before each NAL unitif (m_videoId == MP4_INVALID_TRACK_ID){printf("add video track failed.\n");return false;}MP4SetVideoProfileLevel(hMp4File, 0x03); //  Simple Profile @ Level 3// write spsMP4AddH264SequenceParameterSet(hMp4File, m_videoId, lpMetadata->Sps, lpMetadata->nSpsLen);// write ppsMP4AddH264PictureParameterSet(hMp4File, m_videoId, lpMetadata->Pps, lpMetadata->nPpsLen);return true;}int MP4Encoder::WriteH264Data(MP4FileHandle hMp4File, const unsigned char* pData, int size){if (hMp4File == NULL){return -1;}if (pData == NULL){return -1;}MP4ENC_NaluUnit nalu;int pos = 0, len = 0;int wt_frame = 0;  //测试 - 单帧单Nalu发送while (len = ReadOneNaluFromBuf(pData, size, pos, nalu)){if (nalu.type == 0x07 && sps_wt == 0) // sps{//从sps pps中获取信息float fps = 0.0;//int ret = h264_decode_sps(nalu.data, nalu.size, &m_nWidth, &m_nHeight, &fps);get_bit_context buffer;memset(&buffer, 0, sizeof(get_bit_context));SPS _sps;buffer.buf = nalu.data + 1;buffer.buf_size = nalu.size - 1;int ret = h264dec_seq_parameter_set(&buffer, &_sps);m_nWidth = h264_get_width(&_sps);m_nHeight = h264_get_height(&_sps);ret = h264_get_framerate(&fps, &_sps);if (ret == 0){m_nFrameRate = (double)fps;}video_tick_gap = (1000.0 + 1.0) / m_nFrameRate;// 添加h264 track    m_videoId = MP4AddH264VideoTrack(hMp4File,m_nTimeScale,(double)m_nTimeScale / m_nFrameRate,m_nWidth,     // widthm_nHeight,    // heightnalu.data[1], // sps[1] AVCProfileIndicationnalu.data[2], // sps[2] profile_compatnalu.data[3], // sps[3] AVCLevelIndication3);           // 4 bytes length before each NAL unitif (m_videoId == MP4_INVALID_TRACK_ID){printf("add video track failed.\n");return 0;}MP4SetVideoProfileLevel(hMp4File, 1); //  Simple Profile @ Level 3MP4AddH264SequenceParameterSet(hMp4File, m_videoId, nalu.data, nalu.size);sps_wt = 1;}else if (nalu.type == 0x08 && pps_wt == 0) // pps{MP4AddH264PictureParameterSet(hMp4File, m_videoId, nalu.data, nalu.size);pps_wt = 1;}else if (nalu.type == 0x01 || nalu.type == 0x05){int datalen = nalu.size + 4;unsigned char *data = new unsigned char[datalen];// MP4 Nalu前四个字节表示Nalu长度data[0] = nalu.size >> 24;data[1] = nalu.size >> 16;data[2] = nalu.size >> 8;data[3] = nalu.size & 0xff;memcpy(data + 4, nalu.data, nalu.size);bool syn = 0;if (nalu.type == 0x05){syn = 1;}//if (!MP4WriteSample(hMp4File, m_videoId, data, datalen, MP4_INVALID_DURATION, 0, syn))if (!MP4WriteSample(hMp4File, m_videoId, data, datalen, 90000 / 30, 0, syn)){return 0;}delete[] data;wt_frame++;}pos += len;if (wt_frame > 0){break;}}return pos;}int MP4Encoder::ReadOneNaluFromBuf(const unsigned char *buffer, unsigned int nBufferSize, unsigned int offSet, MP4ENC_NaluUnit &nalu){int i = offSet;while (i<nBufferSize){if (buffer[i++] == 0x00 &&buffer[i++] == 0x00 &&buffer[i++] == 0x00 &&buffer[i++] == 0x01){int pos = i;while (pos<nBufferSize){if (buffer[pos++] == 0x00 &&buffer[pos++] == 0x00 &&buffer[pos++] == 0x00 &&buffer[pos++] == 0x01){break;}}if (pos == nBufferSize){nalu.size = pos - i;}else{nalu.size = (pos - 4) - i;}nalu.type = buffer[i] & 0x1f;nalu.data = (unsigned char*)&buffer[i];return (nalu.size + i - offSet);}}return 0;}void MP4Encoder::MP4FileClose(){if (m_hMp4File){MP4Close(m_hMp4File);m_hMp4File = NULL;}}bool MP4Encoder::MP4FileWrite(int(*read_h264)(unsigned char *buf, int buf_size), int(*read_aac)(unsigned char *buf, int buf_size)){//添加aac音频 -- default init, you can get config information by parsering aac data if you wantm_audioId = MP4AddAudioTrack(m_hMp4File, 48000, 1024, MP4_MPEG4_AUDIO_TYPE); //1024??? 这里不明白为什么用1024 希望有大神解释下if (m_audioId == MP4_INVALID_TRACK_ID){printf("add audio track failed.\n");return false;}MP4SetAudioProfileLevel(m_hMp4File, 0x2);uint8_t buf3[2] = { 0x11, 0x88 }; //important! AAC config infomation;  读者应该根据使用的AAC数据分析出此数据,MP4SetTrackESConfiguration(m_hMp4File, m_audioId, buf3, 2);//--------------------------------------------------------------------unsigned char *buffer = new unsigned char[BUFFER_SIZE];unsigned char audioBuf[1024];int pos = 0;int readlen = 0;int writelen = 0;//--------------------------------------------------------------------uint32_t audio_tick_now, video_tick_now, last_update;unsigned int tick = 0;unsigned int audio_tick = 0;unsigned int video_tick = 0;uint32_t tick_exp_new = 0;uint32_t tick_exp = 0;//--------------------------------------------------------------------audio_tick_now = video_tick_now = GetTickCount();/*尝试时间音视频间隔内去取得视频或者音频数据进行Write*/while (1){last_update = GetTickCount();//时间溢出情况处理if (read_h264 != NULL){if (last_update - video_tick_now > video_tick_gap - tick_exp){printf("now:%lld last_update:%lld video_tick:%d tick_exp:%d\n", video_tick_now, last_update, video_tick, tick_exp);video_tick += video_tick_gap;/////////////////////////////////////////////////-- 这里针对单帧单Nalu的情况处理, 若有差异,请读者自行修改readlen = read_h264(buffer + pos, BUFFER_SIZE - pos);if (readlen <= 0 && pos == 0){break;}readlen += pos;//查找开始位 -- 确保存在Nalu起始位writelen = 0;for (int i = readlen; i >= 4; i--){if (buffer[i - 1] == 0x01 &&buffer[i - 2] == 0x00 &&buffer[i - 3] == 0x00 &&buffer[i - 4] == 0x00){writelen = i - 4; //???break;}}//单个NALUwritelen = WriteH264Data(m_hMp4File, buffer, writelen);if (writelen <= 0){break;}//剩余数据memcpy(buffer, buffer + writelen, readlen - writelen);pos = readlen - writelen;if (pos == 0){break;}///////////////////////////////////////////////video_tick_now = GetTickCount();}}if (read_aac != NULL){if (last_update - audio_tick_now > audio_tick_gap - tick_exp){printf("now:%lld last_update:%lld audio_tick:%d tick_exp:%d\n", audio_tick_now, last_update, audio_tick, tick_exp);audio_tick += audio_tick_gap;/////////////////////////////////////////////////////int audio_len = read_aac(audioBuf, 1024); //get aac header if you want , so that you can get aac config infoif (audio_len <= 0){break;}MP4WriteSample(m_hMp4File, m_audioId, audioBuf, audio_len, MP4_INVALID_DURATION, 0, 1);/////////////////////////////////////////////////////audio_tick_now = GetTickCount();}}tick_exp_new = GetTickCount();tick_exp = tick_exp_new - last_update;//sleep}}bool MP4Encoder::PraseMetadata(const unsigned char* pData, int size, MP4ENC_Metadata &metadata){if (pData == NULL || size<4){return false;}MP4ENC_NaluUnit nalu;int pos = 0;bool bRet1 = false, bRet2 = false;while (int len = ReadOneNaluFromBuf(pData, size, pos, nalu)){if (nalu.type == 0x07){memcpy(metadata.Sps, nalu.data, nalu.size);metadata.nSpsLen = nalu.size;bRet1 = true;}else if ((nalu.type == 0x08)){memcpy(metadata.Pps, nalu.data, nalu.size);metadata.nPpsLen = nalu.size;bRet2 = true;}pos += len;}if (bRet1 && bRet2){return true;}return false;}

为了获取H264视频的帧率和分辨率,这里给出SPS解析的源码(存在部分H264 ES文件无framerate 描述是,采用默认帧率进行处理

/********************************************************************filename:   sps_pps_parser.hcreated:    2016-08-06author:     Donyj*********************************************************************/#ifndef _sps_pps_H_#define _sps_pps_H_//#include <stdint.h>#if defined (__cplusplus)extern "C" {#endif/**** Sequence parameter set* 可参考H264标准第7节和附录D E*/#define Extended_SAR 255typedef struct vui_parameters{int aspect_ratio_info_present_flag; //0 u(1) int aspect_ratio_idc;               //0 u(8) int sar_width;                      //0 u(16) int sar_height;                     //0 u(16) int overscan_info_present_flag;     //0 u(1) int overscan_appropriate_flag;      //0 u(1) int video_signal_type_present_flag; //0 u(1) int video_format;                   //0 u(3) int video_full_range_flag;          //0 u(1) int colour_description_present_flag; //0 u(1) int colour_primaries;                //0 u(8) int transfer_characteristics;        //0 u(8) int matrix_coefficients;             //0 u(8) int chroma_loc_info_present_flag;     //0 u(1) int chroma_sample_loc_type_top_field;  //0 ue(v) int chroma_sample_loc_type_bottom_field; //0 ue(v) int timing_info_present_flag;          //0 u(1) uint32_t num_units_in_tick;           //0 u(32) uint32_t time_scale;                 //0 u(32) int fixed_frame_rate_flag;           //0 u(1) int nal_hrd_parameters_present_flag; //0 u(1)int cpb_cnt_minus1;                 //0 ue(v)int bit_rate_scale;                 //0 u(4)int cpb_size_scale;                 //0 u(4)int bit_rate_value_minus1[16];      //0 ue(v)int cpb_size_value_minus1[16];      //0 ue(v)int cbr_flag[16];                   //0 u(1)int initial_cpb_removal_delay_length_minus1; //0 u(5)int cpb_removal_delay_length_minus1;         //0 u(5)int dpb_output_delay_length_minus1;         //0 u(5)int time_offset_length;                      //0 u(5)int vcl_hrd_parameters_present_flag;         //0 u(1)int low_delay_hrd_flag;                      //0 u(1)int pic_struct_present_flag;                 //0 u(1)int bitstream_restriction_flag;              //0 u(1)int motion_vectors_over_pic_boundaries_flag;  //0 ue(v)int max_bytes_per_pic_denom;                  //0 ue(v)int max_bits_per_mb_denom;                    //0 ue(v)int log2_max_mv_length_horizontal;            //0 ue(v)int log2_max_mv_length_vertical;              //0 ue(v)int num_reorder_frames;                       //0 ue(v)int max_dec_frame_buffering;                  //0 ue(v)}vui_parameters_t;typedef struct SPS{int profile_idc;int constraint_set0_flag;int constraint_set1_flag;int constraint_set2_flag;int constraint_set3_flag;int reserved_zero_4bits;int level_idc;int seq_parameter_set_id;//ue(v)intchroma_format_idc;//ue(v)intseparate_colour_plane_flag;//u(1)intbit_depth_luma_minus8;//0 ue(v) intbit_depth_chroma_minus8;//0 ue(v) intqpprime_y_zero_transform_bypass_flag;//0 u(1) int seq_scaling_matrix_present_flag;//0 u(1)intseq_scaling_list_present_flag[12];intUseDefaultScalingMatrix4x4Flag[6];intUseDefaultScalingMatrix8x8Flag[6];intScalingList4x4[6][16];intScalingList8x8[6][64];int log2_max_frame_num_minus4;//0ue(v)int pic_order_cnt_type;//0 ue(v)int log2_max_pic_order_cnt_lsb_minus4;//intdelta_pic_order_always_zero_flag;           //u(1)intoffset_for_non_ref_pic;                     //se(v)intoffset_for_top_to_bottom_field;            //se(v)intnum_ref_frames_in_pic_order_cnt_cycle;    //ue(v)intoffset_for_ref_frame_array[16];           //se(v)int num_ref_frames;                           //ue(v)intgaps_in_frame_num_value_allowed_flag;    //u(1)intpic_width_in_mbs_minus1;                //ue(v)intpic_height_in_map_units_minus1;         //u(1)intframe_mbs_only_flag;                  //0 u(1) intmb_adaptive_frame_field_flag;           //0 u(1) intdirect_8x8_inference_flag;              //0 u(1) intframe_cropping_flag;                    //u(1)intframe_crop_left_offset;                //ue(v)intframe_crop_right_offset;                //ue(v)intframe_crop_top_offset;                  //ue(v)intframe_crop_bottom_offset;            //ue(v)int vui_parameters_present_flag;            //u(1)vui_parameters_t vui_parameters;}SPS;/**** Picture parameter set*/typedef struct PPS{int pic_parameter_set_id;int seq_parameter_set_id;int entropy_coding_mode_flag;int pic_order_present_flag;int num_slice_groups_minus1;int slice_group_map_type;int run_length_minus1[32];int top_left[32];int bottom_right[32];int slice_group_change_direction_flag;int slice_group_change_rate_minus1;int pic_size_in_map_units_minus1;int slice_group_id[32];int num_ref_idx_10_active_minus1;int num_ref_idx_11_active_minus1;int weighted_pred_flag;int weighted_bipred_idc;int pic_init_qp_minus26;int pic_init_qs_minus26;int chroma_qp_index_offset;int deblocking_filter_control_present_flag;int constrained_intra_pred_flag;int redundant_pic_cnt_present_flag;int transform_8x8_mode_flag;int pic_scaling_matrix_present_flag;int pic_scaling_list_present_flag[32];int second_chroma_qp_index_offset;intUseDefaultScalingMatrix4x4Flag[6];intUseDefaultScalingMatrix8x8Flag[6];int ScalingList4x4[6][16];int ScalingList8x8[2][64];}PPS;typedef struct get_bit_context{uint8_t *buf;         /*指向SPS start*/int     buf_size;     /*SPS 长度*/int     bit_pos;      /*bit已读取位置*/int     total_bit;    /*bit总长度*/int     cur_bit_pos;  /*当前读取位置*/}get_bit_context;int h264dec_seq_parameter_set(void *buf, SPS *sps_ptr);int h264dec_picture_parameter_set(void *buf, PPS *pps_ptr);int h264_get_width(SPS *sps_ptr);int h264_get_height(SPS *sps_ptr);int h264_get_format(SPS *sps_ptr);int h264_get_framerate(float *framerate, SPS *sps_ptr);typedef struct _sequence_header_{unsigned int sequence_header_code; // 0x000001b3unsigned int frame_rate_code : 4;unsigned int aspect_ratio_information : 4;unsigned int vertical_size_value : 12;unsigned int horizontal_size_value : 12;unsigned int marker_bit : 2;unsigned int bit_rate_value : 30;}sequence_header;// sequence extensiontypedef struct _sequence_extension_{unsigned int sequence_header_code; // 0x000001b5unsigned int marker_bit : 1;unsigned int bit_rate_extension : 12;unsigned int vertical_size_extension : 2;unsigned int horizontal_size_extension : 2;unsigned int chroma_format : 2;unsigned int progressive_sequence : 1;unsigned int profile_and_level_indication : 8;unsigned int extension_start_code : 4;}sequence_extension;void memcpy_sps_data(uint8_t *dst, uint8_t *src, int len);#if defined (__cplusplus)}#endif#endif
/********************************************************************filename:   sps_pps_parser.ccreated:    2016-08-06author:     Donyj*********************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h> /* for uint32_t, etc */#include "sps_pps_parser.h"#ifdef __cplusplus extern "C" {#endif /* report level */#define RPT_ERR (1) // error, system error#define RPT_WRN (2) // warning, maybe wrong, maybe OK#define RPT_INF (4) // important information#define RPT_DBG (8) // debug informationstatic int rpt_lvl = RPT_ERR; /* report level: ERR, WRN, INF, DBG *//* report micro */#define RPT(lvl, ...) \do {\if (lvl & rpt_lvl) {\switch (lvl) {\case RPT_ERR: \fprintf(stderr, "\"%s\" line %d [err]: ", __FILE__, __LINE__); \break; \case RPT_WRN: \fprintf(stderr, "\"%s\" line %d [wrn]: ", __FILE__, __LINE__); \break; \case RPT_INF: \fprintf(stderr, "\"%s\" line %d [inf]: ", __FILE__, __LINE__); \break; \case RPT_DBG: \fprintf(stderr, "\"%s\" line %d [dbg]: ", __FILE__, __LINE__); \break; \default: \fprintf(stderr, "\"%s\" line %d [???]: ", __FILE__, __LINE__); \break; \} \fprintf(stderr, __VA_ARGS__); \fprintf(stderr, "\n"); \} \} while (0)#define SPS_PPS_DEBUG#undef  SPS_PPS_DEBUG#define MAX_LEN 32/***  @brief Function get_1bit()   读1个bit*  @param[in]     h     get_bit_context structrue*  @retval        0: success, -1 : failure*  @pre*  @post*/static int get_1bit(void *h){get_bit_context *ptr = (get_bit_context *)h;int ret = 0;uint8_t *cur_char = NULL;uint8_t shift;if (NULL == ptr){RPT(RPT_ERR, "NULL pointer");ret = -1;goto exit;}cur_char = ptr->buf + (ptr->bit_pos >> 3);shift = 7 - (ptr->cur_bit_pos);ptr->bit_pos++;ptr->cur_bit_pos = ptr->bit_pos & 0x7;ret = ((*cur_char) >> shift) & 0x01;exit:return ret;}/***  @brief Function get_bits()  读n个bits,n不能超过32*  @param[in]     h     get_bit_context structrue*  @param[in]     n     how many bits you want?*  @retval        0: success, -1 : failure*  @pre*  @post*/static int get_bits(void *h, int n){get_bit_context *ptr = (get_bit_context *)h;uint8_t temp[5] = { 0 };uint8_t *cur_char = NULL;uint8_t nbyte;uint8_t shift;uint32_t result;uint64_t ret = 0;if (NULL == ptr){RPT(RPT_ERR, "NULL pointer");ret = -1;goto exit;}if (n > MAX_LEN){n = MAX_LEN;}if ((ptr->bit_pos + n) > ptr->total_bit){n = ptr->total_bit - ptr->bit_pos;}cur_char = ptr->buf + (ptr->bit_pos >> 3);nbyte = (ptr->cur_bit_pos + n + 7) >> 3;shift = (8 - (ptr->cur_bit_pos + n)) & 0x07;if (n == MAX_LEN){RPT(RPT_DBG, "12(ptr->bit_pos(:%d) + n(:%d)) > ptr->total_bit(:%d)!!! ", \ptr->bit_pos, n, ptr->total_bit);RPT(RPT_DBG, "0x%x 0x%x 0x%x 0x%x", (*cur_char), *(cur_char + 1), *(cur_char + 2), *(cur_char + 3));}memcpy(&temp[5 - nbyte], cur_char, nbyte);ret = (uint32_t)temp[0] << 24;ret = ret << 8;ret = ((uint32_t)temp[1] << 24) | ((uint32_t)temp[2] << 16)\| ((uint32_t)temp[3] << 8) | temp[4];ret = (ret >> shift) & (((uint64_t)1 << n) - 1);result = ret;ptr->bit_pos += n;ptr->cur_bit_pos = ptr->bit_pos & 0x7;exit:return result;}/***  @brief Function parse_codenum() 指数哥伦布编码解析,参考h264标准第9节*  @param[in]     buf*  @retval        code_num*  @pre*  @post*/static int parse_codenum(void *buf){uint8_t leading_zero_bits = -1;uint8_t b;uint32_t code_num = 0;for (b = 0; !b; leading_zero_bits++){b = get_1bit(buf);}code_num = ((uint32_t)1 << leading_zero_bits) - 1 + get_bits(buf, leading_zero_bits);return code_num;}/***  @brief Function parse_ue() 指数哥伦布编码解析 ue(),参考h264标准第9节*  @param[in]     buf       sps_pps parse buf*  @retval        code_num*  @pre*  @post*/static int parse_ue(void *buf){return parse_codenum(buf);}/***  @brief Function parse_se() 指数哥伦布编码解析 se(), 参考h264标准第9节*  @param[in]     buf       sps_pps parse buf*  @retval        code_num*  @pre*  @post*/static int parse_se(void *buf){int ret = 0;int code_num;code_num = parse_codenum(buf);ret = (code_num + 1) >> 1;ret = (code_num & 0x01) ? ret : -ret;return ret;}/***  @brief Function get_bit_context_free()  申请的get_bit_context结构内存释放*  @param[in]     buf       get_bit_context buf*  @retval        none*  @pre*  @post*/static void get_bit_context_free(void *buf){get_bit_context *ptr = (get_bit_context *)buf;if (ptr){if (ptr->buf){free(ptr->buf);}free(ptr);}}static void *de_emulation_prevention(void *buf){get_bit_context *ptr = NULL;get_bit_context *buf_ptr = (get_bit_context *)buf;int i = 0, j = 0;uint8_t *tmp_ptr = NULL;int tmp_buf_size = 0;int val = 0;if (NULL == buf_ptr){RPT(RPT_ERR, "NULL ptr");goto exit;}ptr = (get_bit_context *)malloc(sizeof(get_bit_context));if (NULL == ptr){RPT(RPT_ERR, "NULL ptr");goto exit;}memcpy(ptr, buf_ptr, sizeof(get_bit_context));printf("fun = %s line = %d ptr->buf_size=%d \n", __FUNCTION__, __LINE__, ptr->buf_size);ptr->buf = (uint8_t *)malloc(ptr->buf_size);if (NULL == ptr->buf){RPT(RPT_ERR, "NULL ptr ");goto exit;}memcpy(ptr->buf, buf_ptr->buf, buf_ptr->buf_size);tmp_ptr = ptr->buf;tmp_buf_size = ptr->buf_size;for (i = 0; i<(tmp_buf_size - 2); i++){/*检测0x000003*/val = (tmp_ptr[i] ^ 0x00) + (tmp_ptr[i + 1] ^ 0x00) + (tmp_ptr[i + 2] ^ 0x03);if (val == 0){/*剔除0x03*/for (j = i + 2; j<tmp_buf_size - 1; j++){tmp_ptr[j] = tmp_ptr[j + 1];}/*相应的bufsize要减小*/ptr->buf_size--;}}/*重新计算total_bit*/ptr->total_bit = ptr->buf_size << 3;return (void *)ptr;exit:get_bit_context_free(ptr);return NULL;}/***  @brief Function get_bit_context_free()  VUI_parameters 解析,原理参考h264标准*  @param[in]     buf       get_bit_context buf*  @param[in]     vui_ptr   vui解析结果*  @retval        0: success, -1 : failure*  @pre*  @post*/static int vui_parameters_set(void *buf, vui_parameters_t *vui_ptr){int ret = 0;int SchedSelIdx = 0;if (NULL == vui_ptr || NULL == buf){RPT(RPT_ERR, "ERR null pointer\n");ret = -1;goto exit;}vui_ptr->aspect_ratio_info_present_flag = get_1bit(buf);if (vui_ptr->aspect_ratio_info_present_flag){vui_ptr->aspect_ratio_idc = get_bits(buf, 8);if (vui_ptr->aspect_ratio_idc == Extended_SAR){vui_ptr->sar_width = get_bits(buf, 16);vui_ptr->sar_height = get_bits(buf, 16);}}vui_ptr->overscan_info_present_flag = get_1bit(buf);if (vui_ptr->overscan_info_present_flag){vui_ptr->overscan_appropriate_flag = get_1bit(buf);}vui_ptr->video_signal_type_present_flag = get_1bit(buf);if (vui_ptr->video_signal_type_present_flag){vui_ptr->video_format = get_bits(buf, 3);vui_ptr->video_full_range_flag = get_1bit(buf);vui_ptr->colour_description_present_flag = get_1bit(buf);if (vui_ptr->colour_description_present_flag){vui_ptr->colour_primaries = get_bits(buf, 8);vui_ptr->transfer_characteristics = get_bits(buf, 8);vui_ptr->matrix_coefficients = get_bits(buf, 8);}}vui_ptr->chroma_loc_info_present_flag = get_1bit(buf);if (vui_ptr->chroma_loc_info_present_flag){vui_ptr->chroma_sample_loc_type_top_field = parse_ue(buf);vui_ptr->chroma_sample_loc_type_bottom_field = parse_ue(buf);}vui_ptr->timing_info_present_flag = get_1bit(buf);if (vui_ptr->timing_info_present_flag){vui_ptr->num_units_in_tick = get_bits(buf, 32);vui_ptr->time_scale = get_bits(buf, 32);vui_ptr->fixed_frame_rate_flag = get_1bit(buf);}vui_ptr->nal_hrd_parameters_present_flag = get_1bit(buf);if (vui_ptr->nal_hrd_parameters_present_flag){vui_ptr->cpb_cnt_minus1 = parse_ue(buf);vui_ptr->bit_rate_scale = get_bits(buf, 4);vui_ptr->cpb_size_scale = get_bits(buf, 4);for (SchedSelIdx = 0; SchedSelIdx <= vui_ptr->cpb_cnt_minus1; SchedSelIdx++){vui_ptr->bit_rate_value_minus1[SchedSelIdx] = parse_ue(buf);vui_ptr->cpb_size_value_minus1[SchedSelIdx] = parse_ue(buf);vui_ptr->cbr_flag[SchedSelIdx] = get_1bit(buf);}vui_ptr->initial_cpb_removal_delay_length_minus1 = get_bits(buf, 5);vui_ptr->cpb_removal_delay_length_minus1 = get_bits(buf, 5);vui_ptr->dpb_output_delay_length_minus1 = get_bits(buf, 5);vui_ptr->time_offset_length = get_bits(buf, 5);}vui_ptr->vcl_hrd_parameters_present_flag = get_1bit(buf);if (vui_ptr->vcl_hrd_parameters_present_flag){vui_ptr->cpb_cnt_minus1 = parse_ue(buf);vui_ptr->bit_rate_scale = get_bits(buf, 4);vui_ptr->cpb_size_scale = get_bits(buf, 4);for (SchedSelIdx = 0; SchedSelIdx <= vui_ptr->cpb_cnt_minus1; SchedSelIdx++){vui_ptr->bit_rate_value_minus1[SchedSelIdx] = parse_ue(buf);vui_ptr->cpb_size_value_minus1[SchedSelIdx] = parse_ue(buf);vui_ptr->cbr_flag[SchedSelIdx] = get_1bit(buf);}vui_ptr->initial_cpb_removal_delay_length_minus1 = get_bits(buf, 5);vui_ptr->cpb_removal_delay_length_minus1 = get_bits(buf, 5);vui_ptr->dpb_output_delay_length_minus1 = get_bits(buf, 5);vui_ptr->time_offset_length = get_bits(buf, 5);}if (vui_ptr->nal_hrd_parameters_present_flag \|| vui_ptr->vcl_hrd_parameters_present_flag){vui_ptr->low_delay_hrd_flag = get_1bit(buf);}vui_ptr->pic_struct_present_flag = get_1bit(buf);vui_ptr->bitstream_restriction_flag = get_1bit(buf);if (vui_ptr->bitstream_restriction_flag){vui_ptr->motion_vectors_over_pic_boundaries_flag = get_1bit(buf);vui_ptr->max_bytes_per_pic_denom = parse_ue(buf);vui_ptr->max_bits_per_mb_denom = parse_ue(buf);vui_ptr->log2_max_mv_length_horizontal = parse_ue(buf);vui_ptr->log2_max_mv_length_vertical = parse_ue(buf);vui_ptr->num_reorder_frames = parse_ue(buf);vui_ptr->max_dec_frame_buffering = parse_ue(buf);}exit:return ret;}/*SPS 信息打印,调试使用*/#ifdef SPS_PPS_DEBUGstatic void sps_info_print(SPS* sps_ptr){if (NULL != sps_ptr){RPT(RPT_DBG, "profile_idc: %d", sps_ptr->profile_idc);RPT(RPT_DBG, "constraint_set0_flag: %d", sps_ptr->constraint_set0_flag);RPT(RPT_DBG, "constraint_set1_flag: %d", sps_ptr->constraint_set1_flag);RPT(RPT_DBG, "constraint_set2_flag: %d", sps_ptr->constraint_set2_flag);RPT(RPT_DBG, "constraint_set3_flag: %d", sps_ptr->constraint_set3_flag);RPT(RPT_DBG, "reserved_zero_4bits: %d", sps_ptr->reserved_zero_4bits);RPT(RPT_DBG, "level_idc: %d", sps_ptr->level_idc);RPT(RPT_DBG, "seq_parameter_set_id: %d", sps_ptr->seq_parameter_set_id);RPT(RPT_DBG, "chroma_format_idc: %d", sps_ptr->chroma_format_idc);RPT(RPT_DBG, "separate_colour_plane_flag: %d", sps_ptr->separate_colour_plane_flag);RPT(RPT_DBG, "bit_depth_luma_minus8: %d", sps_ptr->bit_depth_luma_minus8);RPT(RPT_DBG, "bit_depth_chroma_minus8: %d", sps_ptr->bit_depth_chroma_minus8);RPT(RPT_DBG, "qpprime_y_zero_transform_bypass_flag: %d", sps_ptr->qpprime_y_zero_transform_bypass_flag);RPT(RPT_DBG, "seq_scaling_matrix_present_flag: %d", sps_ptr->seq_scaling_matrix_present_flag);//RPT(RPT_INF, "seq_scaling_list_present_flag:%d", sps_ptr->seq_scaling_list_present_flag); RPT(RPT_DBG, "log2_max_frame_num_minus4: %d", sps_ptr->log2_max_frame_num_minus4);RPT(RPT_DBG, "pic_order_cnt_type: %d", sps_ptr->pic_order_cnt_type);RPT(RPT_DBG, "num_ref_frames: %d", sps_ptr->num_ref_frames);RPT(RPT_DBG, "gaps_in_frame_num_value_allowed_flag: %d", sps_ptr->gaps_in_frame_num_value_allowed_flag);RPT(RPT_DBG, "pic_width_in_mbs_minus1: %d", sps_ptr->pic_width_in_mbs_minus1);RPT(RPT_DBG, "pic_height_in_map_units_minus1: %d", sps_ptr->pic_height_in_map_units_minus1);RPT(RPT_DBG, "frame_mbs_only_flag: %d", sps_ptr->frame_mbs_only_flag);RPT(RPT_DBG, "mb_adaptive_frame_field_flag: %d", sps_ptr->mb_adaptive_frame_field_flag);RPT(RPT_DBG, "direct_8x8_inference_flag: %d", sps_ptr->direct_8x8_inference_flag);RPT(RPT_DBG, "frame_cropping_flag: %d", sps_ptr->frame_cropping_flag);RPT(RPT_DBG, "frame_crop_left_offset: %d", sps_ptr->frame_crop_left_offset);RPT(RPT_DBG, "frame_crop_right_offset: %d", sps_ptr->frame_crop_right_offset);RPT(RPT_DBG, "frame_crop_top_offset: %d", sps_ptr->frame_crop_top_offset);RPT(RPT_DBG, "frame_crop_bottom_offset: %d", sps_ptr->frame_crop_bottom_offset);RPT(RPT_DBG, "vui_parameters_present_flag: %d", sps_ptr->vui_parameters_present_flag);if (sps_ptr->vui_parameters_present_flag){RPT(RPT_DBG, "aspect_ratio_info_present_flag: %d", sps_ptr->vui_parameters.aspect_ratio_info_present_flag);RPT(RPT_DBG, "aspect_ratio_idc: %d", sps_ptr->vui_parameters.aspect_ratio_idc);RPT(RPT_DBG, "sar_width: %d", sps_ptr->vui_parameters.sar_width);RPT(RPT_DBG, "sar_height: %d", sps_ptr->vui_parameters.sar_height);RPT(RPT_DBG, "overscan_info_present_flag: %d", sps_ptr->vui_parameters.overscan_info_present_flag);RPT(RPT_DBG, "overscan_info_appropriate_flag: %d", sps_ptr->vui_parameters.overscan_appropriate_flag);RPT(RPT_DBG, "video_signal_type_present_flag: %d", sps_ptr->vui_parameters.video_signal_type_present_flag);RPT(RPT_DBG, "video_format: %d", sps_ptr->vui_parameters.video_format);RPT(RPT_DBG, "video_full_range_flag: %d", sps_ptr->vui_parameters.video_full_range_flag);RPT(RPT_DBG, "colour_description_present_flag: %d", sps_ptr->vui_parameters.colour_description_present_flag);RPT(RPT_DBG, "colour_primaries: %d", sps_ptr->vui_parameters.colour_primaries);RPT(RPT_DBG, "transfer_characteristics: %d", sps_ptr->vui_parameters.transfer_characteristics);RPT(RPT_DBG, "matrix_coefficients: %d", sps_ptr->vui_parameters.matrix_coefficients);RPT(RPT_DBG, "chroma_loc_info_present_flag: %d", sps_ptr->vui_parameters.chroma_loc_info_present_flag);RPT(RPT_DBG, "chroma_sample_loc_type_top_field: %d", sps_ptr->vui_parameters.chroma_sample_loc_type_top_field);RPT(RPT_DBG, "chroma_sample_loc_type_bottom_field: %d", sps_ptr->vui_parameters.chroma_sample_loc_type_bottom_field);RPT(RPT_DBG, "timing_info_present_flag: %d", sps_ptr->vui_parameters.timing_info_present_flag);RPT(RPT_DBG, "num_units_in_tick: %d", sps_ptr->vui_parameters.num_units_in_tick);RPT(RPT_DBG, "time_scale: %d", sps_ptr->vui_parameters.time_scale);RPT(RPT_DBG, "fixed_frame_rate_flag: %d", sps_ptr->vui_parameters.fixed_frame_rate_flag);RPT(RPT_DBG, "nal_hrd_parameters_present_flag: %d", sps_ptr->vui_parameters.nal_hrd_parameters_present_flag);RPT(RPT_DBG, "cpb_cnt_minus1: %d", sps_ptr->vui_parameters.cpb_cnt_minus1);RPT(RPT_DBG, "bit_rate_scale: %d", sps_ptr->vui_parameters.bit_rate_scale);RPT(RPT_DBG, "cpb_size_scale: %d", sps_ptr->vui_parameters.cpb_size_scale);RPT(RPT_DBG, "initial_cpb_removal_delay_length_minus1: %d", sps_ptr->vui_parameters.initial_cpb_removal_delay_length_minus1);RPT(RPT_DBG, "cpb_removal_delay_length_minus1: %d", sps_ptr->vui_parameters.cpb_removal_delay_length_minus1);RPT(RPT_DBG, "dpb_output_delay_length_minus1: %d", sps_ptr->vui_parameters.dpb_output_delay_length_minus1);RPT(RPT_DBG, "time_offset_length: %d", sps_ptr->vui_parameters.time_offset_length);RPT(RPT_DBG, "vcl_hrd_parameters_present_flag: %d", sps_ptr->vui_parameters.vcl_hrd_parameters_present_flag);RPT(RPT_DBG, "low_delay_hrd_flag: %d", sps_ptr->vui_parameters.low_delay_hrd_flag);RPT(RPT_DBG, "pic_struct_present_flag: %d", sps_ptr->vui_parameters.pic_struct_present_flag);RPT(RPT_DBG, "bitstream_restriction_flag: %d", sps_ptr->vui_parameters.bitstream_restriction_flag);RPT(RPT_DBG, "motion_vectors_over_pic_boundaries_flag: %d", sps_ptr->vui_parameters.motion_vectors_over_pic_boundaries_flag);RPT(RPT_DBG, "max_bytes_per_pic_denom: %d", sps_ptr->vui_parameters.max_bytes_per_pic_denom);RPT(RPT_DBG, "max_bits_per_mb_denom: %d", sps_ptr->vui_parameters.max_bits_per_mb_denom);RPT(RPT_DBG, "log2_max_mv_length_horizontal: %d", sps_ptr->vui_parameters.log2_max_mv_length_horizontal);RPT(RPT_DBG, "log2_max_mv_length_vertical: %d", sps_ptr->vui_parameters.log2_max_mv_length_vertical);RPT(RPT_DBG, "num_reorder_frames: %d", sps_ptr->vui_parameters.num_reorder_frames);RPT(RPT_DBG, "max_dec_frame_buffering: %d", sps_ptr->vui_parameters.max_dec_frame_buffering);}}}#endif/***  @brief Function h264dec_seq_parameter_set()  h264 SPS infomation 解析*  @param[in]     buf       buf ptr, 需同步00 00 00 01 X7后传入*  @param[in]     sps_ptr   sps指针,保存SPS信息*  @retval        0: success, -1 : failure*  @pre*  @post*/int h264dec_seq_parameter_set(void *buf_ptr, SPS *sps_ptr){SPS *sps = sps_ptr;int ret = 0;int profile_idc = 0;int i, j, last_scale, next_scale, delta_scale;void *buf = NULL;if (NULL == buf_ptr || NULL == sps){RPT(RPT_ERR, "ERR null pointer\n");ret = -1;goto exit;}memset((void *)sps, 0, sizeof(SPS));buf = de_emulation_prevention(buf_ptr);if (NULL == buf){RPT(RPT_ERR, "ERR null pointer\n");ret = -1;goto exit;}sps->profile_idc = get_bits(buf, 8);sps->constraint_set0_flag = get_1bit(buf);sps->constraint_set1_flag = get_1bit(buf);sps->constraint_set2_flag = get_1bit(buf);sps->constraint_set3_flag = get_1bit(buf);sps->reserved_zero_4bits = get_bits(buf, 4);sps->level_idc = get_bits(buf, 8);sps->seq_parameter_set_id = parse_ue(buf);profile_idc = sps->profile_idc;if ((profile_idc == 100) || (profile_idc == 110) || (profile_idc == 122) || (profile_idc == 244)|| (profile_idc == 44) || (profile_idc == 83) || (profile_idc == 86) || (profile_idc == 118) || \(profile_idc == 128)){sps->chroma_format_idc = parse_ue(buf);if (sps->chroma_format_idc == 3){sps->separate_colour_plane_flag = get_1bit(buf);}sps->bit_depth_luma_minus8 = parse_ue(buf);sps->bit_depth_chroma_minus8 = parse_ue(buf);sps->qpprime_y_zero_transform_bypass_flag = get_1bit(buf);sps->seq_scaling_matrix_present_flag = get_1bit(buf);if (sps->seq_scaling_matrix_present_flag){for (i = 0; i < ((sps->chroma_format_idc != 3) ? 8 : 12); i++){sps->seq_scaling_list_present_flag[i] = get_1bit(buf);if (sps->seq_scaling_list_present_flag[i]){if (i < 6){for (j = 0; j < 16; j++){last_scale = 8;next_scale = 8;if (next_scale != 0){delta_scale = parse_se(buf);next_scale = (last_scale + delta_scale + 256) % 256;sps->UseDefaultScalingMatrix4x4Flag[i] = ((j == 0) && (next_scale == 0));}sps->ScalingList4x4[i][j] = (next_scale == 0) ? last_scale : next_scale;last_scale = sps->ScalingList4x4[i][j];}}else{int ii = i - 6;next_scale = 8;last_scale = 8;for (j = 0; j < 64; j++){if (next_scale != 0){delta_scale = parse_se(buf);next_scale = (last_scale + delta_scale + 256) % 256;sps->UseDefaultScalingMatrix8x8Flag[ii] = ((j == 0) && (next_scale == 0));}sps->ScalingList8x8[ii][j] = (next_scale == 0) ? last_scale : next_scale;last_scale = sps->ScalingList8x8[ii][j];}}}}}}sps->log2_max_frame_num_minus4 = parse_ue(buf);sps->pic_order_cnt_type = parse_ue(buf);if (sps->pic_order_cnt_type == 0){sps->log2_max_pic_order_cnt_lsb_minus4 = parse_ue(buf);}else if (sps->pic_order_cnt_type == 1){sps->delta_pic_order_always_zero_flag = get_1bit(buf);sps->offset_for_non_ref_pic = parse_se(buf);sps->offset_for_top_to_bottom_field = parse_se(buf);sps->num_ref_frames_in_pic_order_cnt_cycle = parse_ue(buf);for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++){sps->offset_for_ref_frame_array[i] = parse_se(buf);}}sps->num_ref_frames = parse_ue(buf);sps->gaps_in_frame_num_value_allowed_flag = get_1bit(buf);sps->pic_width_in_mbs_minus1 = parse_ue(buf);sps->pic_height_in_map_units_minus1 = parse_ue(buf);sps->frame_mbs_only_flag = get_1bit(buf);if (!sps->frame_mbs_only_flag){sps->mb_adaptive_frame_field_flag = get_1bit(buf);}sps->direct_8x8_inference_flag = get_1bit(buf);sps->frame_cropping_flag = get_1bit(buf);if (sps->frame_cropping_flag){sps->frame_crop_left_offset = parse_ue(buf);sps->frame_crop_right_offset = parse_ue(buf);sps->frame_crop_top_offset = parse_ue(buf);sps->frame_crop_bottom_offset = parse_ue(buf);}sps->vui_parameters_present_flag = get_1bit(buf);if (sps->vui_parameters_present_flag){vui_parameters_set(buf, &sps->vui_parameters);}#ifdef SPS_PPS_DEBUGsps_info_print(sps);#endifexit:get_bit_context_free(buf);return ret;}/***  @brief Function more_rbsp_data()  计算pps串最后一个为1的比特位及其后都是比特0的个数*  @param[in]     buf       get_bit_context structure*  @retval*  @pre*  @post*  @note  这段代码来自网友的帮助,并没有验证,使用时需注意*/static int more_rbsp_data(void *buf){get_bit_context *ptr = (get_bit_context *)buf;get_bit_context tmp;if (NULL == buf){RPT(RPT_ERR, "NULL pointer, err");return -1;}memset(&tmp, 0, sizeof(get_bit_context));memcpy(&tmp, ptr, sizeof(get_bit_context));for (tmp.bit_pos = ptr->total_bit - 1; tmp.bit_pos > ptr->bit_pos; tmp.bit_pos -= 2){if (get_1bit(&tmp)){break;}}return tmp.bit_pos == ptr->bit_pos ? 0 : 1;}/***  @brief Function h264dec_picture_parameter_set()  h264 PPS infomation 解析*  @param[in]     buf       buf ptr, 需同步00 00 00 01 X8后传入*  @param[in]     pps_ptr   pps指针,保存pps信息*  @retval        0: success, -1 : failure*  @pre*  @post*  @note: 用法参考sps解析*/int h264dec_picture_parameter_set(void *buf_ptr, PPS *pps_ptr){PPS *pps = pps_ptr;int ret = 0;void *buf = NULL;int iGroup = 0;int i, j, last_scale, next_scale, delta_scale;if (NULL == buf_ptr || NULL == pps_ptr){RPT(RPT_ERR, "NULL pointer\n");ret = -1;goto exit;}memset((void *)pps, 0, sizeof(PPS));buf = de_emulation_prevention(buf_ptr);if (NULL == buf){RPT(RPT_ERR, "ERR null pointer\n");ret = -1;goto exit;}pps->pic_parameter_set_id = parse_ue(buf);pps->seq_parameter_set_id = parse_ue(buf);pps->entropy_coding_mode_flag = get_1bit(buf);pps->pic_order_present_flag = get_1bit(buf);pps->num_slice_groups_minus1 = parse_ue(buf);if (pps->num_slice_groups_minus1 > 0){pps->slice_group_map_type = parse_ue(buf);if (pps->slice_group_map_type == 0){for (iGroup = 0; iGroup <= pps->num_slice_groups_minus1; iGroup++){pps->run_length_minus1[iGroup] = parse_ue(buf);}}else if (pps->slice_group_map_type == 2){for (iGroup = 0; iGroup <= pps->num_slice_groups_minus1; iGroup++){pps->top_left[iGroup] = parse_ue(buf);pps->bottom_right[iGroup] = parse_ue(buf);}}else if (pps->slice_group_map_type == 3 \|| pps->slice_group_map_type == 4\|| pps->slice_group_map_type == 5){pps->slice_group_change_direction_flag = get_1bit(buf);pps->slice_group_change_rate_minus1 = parse_ue(buf);}else if (pps->slice_group_map_type == 6){pps->pic_size_in_map_units_minus1 = parse_ue(buf);for (i = 0; i<pps->pic_size_in_map_units_minus1; i++){/*这地方可能有问题,对u(v)理解偏差*/pps->slice_group_id[i] = get_bits(buf, pps->pic_size_in_map_units_minus1);}}}pps->num_ref_idx_10_active_minus1 = parse_ue(buf);pps->num_ref_idx_11_active_minus1 = parse_ue(buf);pps->weighted_pred_flag = get_1bit(buf);pps->weighted_bipred_idc = get_bits(buf, 2);pps->pic_init_qp_minus26 = parse_se(buf); /*relative26*/pps->pic_init_qs_minus26 = parse_se(buf); /*relative26*/pps->chroma_qp_index_offset = parse_se(buf);pps->deblocking_filter_control_present_flag = get_1bit(buf);pps->constrained_intra_pred_flag = get_1bit(buf);pps->redundant_pic_cnt_present_flag = get_1bit(buf);if (more_rbsp_data(buf)){pps->transform_8x8_mode_flag = get_1bit(buf);pps->pic_scaling_matrix_present_flag = get_1bit(buf);if (pps->pic_scaling_matrix_present_flag){for (i = 0; i<6 + 2 * pps->transform_8x8_mode_flag; i++){pps->pic_scaling_list_present_flag[i] = get_1bit(buf);if (pps->pic_scaling_list_present_flag[i]){if (i<6){for (j = 0; j<16; j++){next_scale = 8;last_scale = 8;if (next_scale != 0){delta_scale = parse_se(buf);next_scale = (last_scale + delta_scale + 256) % 256;pps->UseDefaultScalingMatrix4x4Flag[i] = ((j == 0) && (next_scale == 0));}pps->ScalingList4x4[i][j] = (next_scale == 0) ? last_scale : next_scale;last_scale = pps->ScalingList4x4[i][j];}}else{int ii = i - 6;next_scale = 8;last_scale = 8;for (j = 0; j<64; j++){if (next_scale != 0){delta_scale = parse_se(buf);next_scale = (last_scale + delta_scale + 256) % 256;pps->UseDefaultScalingMatrix8x8Flag[ii] = ((j == 0) && (next_scale == 0));}pps->ScalingList8x8[ii][j] = (next_scale == 0) ? last_scale : next_scale;last_scale = pps->ScalingList8x8[ii][j];}}}}pps->second_chroma_qp_index_offset = parse_se(buf);}}exit:get_bit_context_free(buf);return ret;}// calculation width height and framerateint h264_get_width(SPS *sps_ptr){return (sps_ptr->pic_width_in_mbs_minus1 + 1) * 16;}int h264_get_height(SPS *sps_ptr){printf("fun = %s line = %d sps_ptr->frame_mbs_only_flag=%d \n", __FUNCTION__, __LINE__, sps_ptr->frame_mbs_only_flag);return (sps_ptr->pic_height_in_map_units_minus1 + 1) * 16 * (2 - sps_ptr->frame_mbs_only_flag);}int h264_get_format(SPS *sps_ptr){return sps_ptr->frame_mbs_only_flag;}int h264_get_framerate(float *framerate, SPS *sps_ptr){int fr;int fr_int = 0;if (sps_ptr->vui_parameters.timing_info_present_flag){if (sps_ptr->frame_mbs_only_flag){//*framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick;*framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick / 2.0;//fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick;}else{*framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick / 2.0;//fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick / 2;}return 0;}else{return 1;}}void memcpy_sps_data(uint8_t *dst, uint8_t *src, int len){int tmp;for (tmp = 0; tmp < len; tmp++){//printf("0x%02x ", src[tmp]);dst[(tmp / 4) * 4 + (3 - (tmp % 4))] = src[tmp];}}/*_*/#ifdef __cplusplus }#endif 


Mux.cpp调用

/********************************************************************filename:   Mux.cppcreated:    2016-08-06author:     Donyjpurpose:    MP4编码器,基于开源库mp4v2实现(https://code.google.com/p/mp4v2/)。*********************************************************************/#include <stdio.h>#include<Winsock2.h>#pragma comment(lib,"ws2_32.lib")#include "MP4Encoder.h"FILE *fp_h264;FILE *fp_AAC;static int count_audio = 0;int read_h264(unsigned char *buf, int buf_size){int true_size = fread(buf, 1, buf_size, fp_h264);if (true_size > 0){return true_size;}else{//fseek(fp_AAC, 0L, SEEK_SET);//return read_aac(buf, buf_size);return 0;}}int read_aac(unsigned char *buf, int buf_size){unsigned char aac_header[7];int true_size = 0;true_size = fread(aac_header, 1, 7, fp_AAC);if (true_size <= 0){fseek(fp_AAC, 0L, SEEK_SET);return read_aac(buf, buf_size);}else{unsigned int body_size = *(unsigned int *)(aac_header + 3);body_size = ntohl(body_size); //Little Endianbody_size = body_size << 6;body_size = body_size >> 19;true_size = fread(buf, 1, body_size - 7, fp_AAC);return true_size;}}int main(int argc, char** argv){//fp_h264 = fopen("test.h264", "rb");//fp_h264 = fopen("1080.h264", "rb");fp_h264 = fopen("bitstream.h264", "rb");fp_AAC = fopen("test.aac", "rb");MP4Encoder mp4Encoder;// convert H264 file to mp4 filemp4Encoder.MP4FileOpen("test.mp4", 1, 1);mp4Encoder.MP4FileWrite(read_h264, read_aac);mp4Encoder.MP4FileClose();fclose(fp_h264);fclose(fp_AAC);}


这里是在Windows平台的代码,MP4V2库编译完成后需要对新建的Mux工作做库和头文件的引入,这里不做介绍。

若是应用平台,请做响应修改!


我的疑问:我在Linux编译成so库,strip后仍然有1M大小,不太适合个别嵌入式项目,正在做相应的裁剪工作,大家若有相关资料,希望能够分享一下!

0 0
原创粉丝点击