FFmpeg ff_h264_parse_sprop_parameter_sets函数剖析

SDP中SPS内容
        sprop-parameter-sets=Z0IAKpY1QPAET8s3AQEBQAABwgAAV+QB,aM48gA==

该函数主要是读取Z0IAKpY1QPAET8s3AQEBQAABwgAAV+QB的内容到data_ptr,一共32个字节
还没有读取SPS的每一个字段,然后赋值给SPS相应的字段
int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s,
                                       uint8_t **data_ptr, int *size_ptr,
                                       const char *value)
{
    char base64packet[1024];
    uint8_t decoded_packet[1024];
    int packet_size;

while (*value) {
//通过dst保存数据的头指针
        char *dst = base64packet;

//将value字符串拷贝一份到dst指针
        while (*value && *value != ','
               && (dst - base64packet) < sizeof(base64packet) - 1) {
            *dst++ = *value++;
        }
        *dst++ = '\0';
//base64packet=Z0IAKpY1QPAET8s3AQEBQAABwgAAV+QB
        if (*value == ',')
            value++;
//base64解码结果,保存在decoded_packet
        packet_size = av_base64_decode(decoded_packet, base64packet,
                                       sizeof(decoded_packet));
        if (packet_size > 0) {
//这里进行了内存大小进行调整
            uint8_t *dest = av_realloc(*data_ptr,
                                       packet_size + sizeof(start_sequence) +
                                       *size_ptr +
                                      AV_INPUT_BUFFER_PADDING_SIZE);
//static const uint8_t start_sequence[] = { 'B', 'B', 'C', 'D' };不是很明白
            if (!dest) {
                av_log(s, AV_LOG_ERROR,
                       "Unable to allocate memory for extradata!\n");
                return AVERROR(ENOMEM);
            }
            *data_ptr = dest;

memcpy(dest + *size_ptr, start_sequence,
                   sizeof(start_sequence));
            memcpy(dest + *size_ptr + sizeof(start_sequence),
                   decoded_packet, packet_size);
            memset(dest + *size_ptr + sizeof(start_sequence) +
                   packet_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);

*size_ptr += sizeof(start_sequence) + packet_size;
        }
    }

return 0;
}

static int sdp_parse_fmtp_config_h264(AVFormatContext *s,
                                      AVStream *stream,
                                      PayloadContext *h264_data,
                                      const char *attr, const char *value)
{
    AVCodecParameters *par = stream->codecpar;

if (!strcmp(attr, "packetization-mode")) {
        av_log(s, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
        h264_data->packetization_mode = atoi(value);
        /*
         * Packetization Mode:
         * 0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
         * 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
         * 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A),
         *                      and 29 (FU-B) are allowed.
         */
        if (h264_data->packetization_mode > 1)
            av_log(s, AV_LOG_ERROR,
                   "Interleaved RTP mode is not supported yet.\n");
    } else if (!strcmp(attr, "profile-level-id")) {
        if (strlen(value) == 6)
            parse_profile_level_id(s, h264_data, value);
    } else if (!strcmp(attr, "sprop-parameter-sets")) {
        int ret;
        if (*value == 0 || value[strlen(value) - 1] == ',') {
            av_log(s, AV_LOG_WARNING, "Missing PPS in sprop-parameter-sets, ignoring\n");
            return 0;
        }
        par->extradata_size = 0;
        av_freep(&par->extradata);
//这一段代码主要是将value的值拷贝到par->extradata字符串中
        ret = ff_h264_parse_sprop_parameter_sets(s, &par->extradata,
                                                 &par->extradata_size, value);
        av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)\n",
               par->extradata, par->extradata_size);
        return ret;
    }
    return 0;
}

疑问
,aM48gA==这一段数据,并没有使用,是否意味着这只是读取了SPS,而没有读取到PPS,导致出现
non-existing PPS 0 referenced

函数的调用逻辑
sdp_read_header
  ----ff_sdp_parse
    ----sdp_parse_line
      -----parse_fmtp
        ----parse_sdp_a_line------>parse_h264_sdp_line
                        --------sdp_parse_fmtp_config_h264

参考
https://www.cnblogs.com/lihaiping/p/6612511.html

引用海康SDP信息
v=0
o=- 1515162567455825 1515162567455825 IN IP4 192.168.0.150
s=Media Presentation
e=NONE
b=AS:5050
t=0 0
a=control:rtsp://192.168.0.150:554/h264/ch1/main/av_stream/
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:5000
a=recvonly
a=x-dimensions:1920,1080
a=control:rtsp://192.168.0.150:554/h264/ch1/main/av_stream/trackID=1
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z0IAKpY1QPAET8s3AQEBQAABwgAAV+QB,aM48gA==
a=Media_header:MEDIAINFO=494D4B48010200000400000100000000000000000000000000000000000000000000000000000000;
a=appversion:1.0
SETUP rtsp://192.168.0.150:554/h264/ch1/main/av_stream/trackID=1 RTSP/1.0
CSeq: 5
Authorization: Digest username="admin", realm="IP Camera(77056)", nonce="a3a53f4dcb9e6ceca90de6d90c884d29", uri="rtsp://192.168.0.150:554/h264/ch1/main/av_stream/", response="32b6afa222b54c2518efff16ec1aa766"
User-Agent: LibVLC/2.2.4 (LIVE555 Streaming Media v2016.02.22)
Transport: RTP/AVP/TCP;unicast;interleaved=0-1

原文地址:http://blog.51cto.com/fengyuzaitu/2057783

时间: 2024-11-05 22:49:39

FFmpeg ff_h264_parse_sprop_parameter_sets函数剖析的相关文章

FFmpeg avio_alloc_context函数剖析

函数原型AVIOContext *avio_alloc_context(                  unsigned char *buffer,                  int buffer_size,                  int write_flag,                  void *opaque,                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_siz

FFmpeg av_probe_input_buffer函数剖析以及优化

函数调用关系av_probe_input_buffer调用av_probe_input_buffer2进行整一个码流格式的分析过程.其中调用avio_read进行码流数据的读取,将缓存数据保存在AVProbeData定义的buf里面,然后调用av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)函数去猜测码流格式,其中包裹最终的调用函数av_probe_input_format3. 优化方向如果知道AVInpu

FFmpeg init_input函数剖析

函数调用逻辑avformat_open_input       init_input            av_probe_input_buffer2 函数原型 static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options) 函数说明主要是调用av_probe_input_buffer2函数探测码流格式.AVFormatContext结构体flags变量,在经过avformat_al

FFmpeg mov_read_ftyp函数剖析

函数说明 读取文件格式,最小版本以及兼容格式,然后存储到metadata,metadata作为AVFormatContext成员变量,可以通过t = av_dict_get(pAVFormatContext->metadata, "major_brand", NULL, AV_DICT_IGNORE_SUFFIX);查看文件格式 /* read major brand, minor version and compatible brands and store them as m

FFmpeg avcodec_parameters_to_context函数剖析

函数说明    将AVCodecParameters结构体中码流参数拷贝到AVCodecContext结构体中,并且重新拷贝一份extradata内容,涉及到的视频的关键参数有format, width, height, codec_type等,这些参数在优化avformat_find_stream_info函数的时候,手动指定该参数通过InitDecoder函数解码统一指定H264,分辨率是1920*1080 int avcodec_parameters_to_context(AVCodecC

自执行匿名函数剖析

引入 在很多js代码中我们常常会看见这样一种写法: (function( window, undefined ) { // code })(window); 这种写法我们称之为自执行匿名函数(self-executing anonymous function). 正如它的名字一样,它是自己执行自己的,前一个括号是一个匿名函数,后一个括号代表立即执行. 函数和函数表达式的区别 语法 function keqing(){ //函数 alert('Hi~'); } var keqing = funct

ffmpeg.c函数结构简单分析(画图)

前一阵子研究转码的时候看了FFmpeg的源代码.由于ffmpeg.c的代码相对比较长,而且其中有相当一部分是AVFilter有关的代码(这一部分一直不太熟),因此之前学习FFmpeg的时候一直也没有好好看一下其源代码.最近正好看了看AVFilter的知识,顺便就看了下FFmpeg的源代码,在这里画图理一下它的结构.目前好多地方还没有弄明白,等到以后慢慢完善了. 先说明一下自己画的结构图的规则:图中仅画出了比较重要的函数之间的调用关系.粉红色的函数是FFmpeg编解码类库(libavcodec,l

power(乘幂)函数剖析

近来学习STL,看到power函数的实现感觉挺有趣,记录一下. 1. 一般情况下,我自己要实现乘幂函数会这样实现: int power(int x,size_t n) { int result = 1; while (n--) result *= x; return result; } 这样即使实现,这里的时间复杂度和n有关,时间复杂度为0(n). 2. 看了stl源码实现是这样: // Returns __x ** __n, where __n >= 0. _Note that "mul

STM32的GPIO使用的函数剖析

转载http://blog.csdn.net/wuwuhuizheyisheng/article/details/8239599 STM32的GPIO总结 作者:JCY 该文是自己学习了一段STM32后所写,是对STM32使用固件库编程最简单的一段程序,是对固件库函数的一部分进行解析.如有错误之处请指正,不胜感激. 一. GPIO_Init函数解析 1 1.参数GPIO_TypeDef 1 2.参数GPIO_InitStruct 2 3.函数代码详解 4 4.备注 6 一.GPIO_Init函数