h264 sdp file parse notes

本文详细介绍了如何解析AVStream、PayloadContext、属性和值之间的H264配置参数,包括packetization-mode、profile-level-id和sprop-parameter-sets等关键属性的解析方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

static int sdp_parse_fmtp_config_h264(AVStream *stream,
                                      PayloadContext *h264_data,
                                      char *attr, char *value)
{
    AVCodecContext *codec = stream->codec;
    assert(codec->codec_id == AV_CODEC_ID_H264);
    assert(h264_data != NULL);


    if (!strcmp(attr, "packetization-mode")) {  // parse packetation-mode in fmtp, please see notes below, it is clear that ffmpeg not support interleaved mode.
        av_log(codec, 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(codec, AV_LOG_ERROR,
                   "Interleaved RTP mode is not supported yet.\n");
    } else if (!strcmp(attr, "profile-level-id")) {  // parse profile and level of h264
        if (strlen(value) == 6) {
            char buffer[3];
            // 6 characters=3 bytes, in hex.
            uint8_t profile_idc;
            uint8_t profile_iop;
            uint8_t level_idc;


            buffer[0]   = value[0];
            buffer[1]   = value[1];
            buffer[2]   = '\0';
            profile_idc = strtol(buffer, NULL, 16);
            buffer[0]   = value[2];
            buffer[1]   = value[3];
            profile_iop = strtol(buffer, NULL, 16);
            buffer[0]   = value[4];
            buffer[1]   = value[5];
            level_idc   = strtol(buffer, NULL, 16);


            av_log(codec, AV_LOG_DEBUG,
                   "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
                   profile_idc, profile_iop, level_idc);
            h264_data->profile_idc = profile_idc;
            h264_data->profile_iop = profile_iop;
            h264_data->level_idc   = level_idc;
        }
    } else if (!strcmp(attr, "sprop-parameter-sets")) {  // parse sps of h264
        codec->extradata_size = 0;
        av_freep(&codec->extradata);


        while (*value) {
            char base64packet[1024];
            uint8_t decoded_packet[1024];
            int packet_size;
            char *dst = base64packet;


            while (*value && *value != ','
                   && (dst - base64packet) < sizeof(base64packet) - 1) {
                *dst++ = *value++;
            }
            *dst++ = '\0';


            if (*value == ',')
                value++;


            packet_size = av_base64_decode(decoded_packet, base64packet,
                                           sizeof(decoded_packet));
            if (packet_size > 0) {
                uint8_t *dest = av_malloc(packet_size + sizeof(start_sequence) +
                                          codec->extradata_size +
                                          FF_INPUT_BUFFER_PADDING_SIZE);
                if (!dest) {
                    av_log(codec, AV_LOG_ERROR,
                           "Unable to allocate memory for extradata!\n");
                    return AVERROR(ENOMEM);
                }
                if (codec->extradata_size) {
                    memcpy(dest, codec->extradata, codec->extradata_size);
                    av_free(codec->extradata);
                }


                memcpy(dest + codec->extradata_size, start_sequence,
                       sizeof(start_sequence));
                memcpy(dest + codec->extradata_size + sizeof(start_sequence),
                       decoded_packet, packet_size);
                memset(dest + codec->extradata_size + sizeof(start_sequence) +
                       packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);


                codec->extradata       = dest;
                codec->extradata_size += sizeof(start_sequence) + packet_size;
            }
        }
        av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!\n",
               codec->extradata, codec->extradata_size);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值