X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Frtpdec_h264.c;h=401d6f632c08618ec13dbdf76f77789d32d88cd0;hb=bfe92dfe60f601b3f20a918ffcc0acdf40a5955c;hp=ee1a993547ccf26eba32165615d59e532a78674d;hpb=fe208ca54b0d3b6bbe1c660d371bb2cc6cf40ffc;p=ffmpeg diff --git a/libavformat/rtpdec_h264.c b/libavformat/rtpdec_h264.c index ee1a993547c..401d6f632c0 100644 --- a/libavformat/rtpdec_h264.c +++ b/libavformat/rtpdec_h264.c @@ -1,5 +1,5 @@ /* - * RTP H264 Protocol (RFC3984) + * RTP H.264 Protocol (RFC3984) * Copyright (c) 2006 Ryan Martell * * This file is part of Libav. @@ -39,8 +39,6 @@ #include "libavutil/avstring.h" #include "avformat.h" -#include "network.h" - #include "rtpdec.h" #include "rtpdec_formats.h" @@ -68,7 +66,7 @@ static const uint8_t start_sequence[] = { 0, 0, 0, 1 }; static void parse_profile_level_id(AVFormatContext *s, PayloadContext *h264_data, - char *value) + const char *value) { char buffer[3]; // 6 characters=3 bytes, in hex. @@ -121,7 +119,7 @@ int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s, uint8_t *dest = av_realloc(*data_ptr, packet_size + sizeof(start_sequence) + *size_ptr + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!dest) { av_log(s, AV_LOG_ERROR, "Unable to allocate memory for extradata!\n"); @@ -134,7 +132,7 @@ int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s, memcpy(dest + *size_ptr + sizeof(start_sequence), decoded_packet, packet_size); memset(dest + *size_ptr + sizeof(start_sequence) + - packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + packet_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); *size_ptr += sizeof(start_sequence) + packet_size; } @@ -146,9 +144,9 @@ int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s, static int sdp_parse_fmtp_config_h264(AVFormatContext *s, AVStream *stream, PayloadContext *h264_data, - char *attr, char *value) + const char *attr, const char *value) { - AVCodecContext *codec = stream->codec; + AVCodecParameters *par = stream->codecpar; if (!strcmp(attr, "packetization-mode")) { av_log(s, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value)); @@ -168,17 +166,39 @@ static int sdp_parse_fmtp_config_h264(AVFormatContext *s, parse_profile_level_id(s, h264_data, value); } else if (!strcmp(attr, "sprop-parameter-sets")) { int ret; - codec->extradata_size = 0; - av_freep(&codec->extradata); - ret = ff_h264_parse_sprop_parameter_sets(s, &codec->extradata, - &codec->extradata_size, value); + par->extradata_size = 0; + av_freep(&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", - codec->extradata, codec->extradata_size); + par->extradata, par->extradata_size); return ret; } return 0; } +void ff_h264_parse_framesize(AVCodecParameters *par, const char *p) +{ + char buf1[50]; + char *dst = buf1; + + // remove the protocol identifier + while (*p && *p == ' ') + p++; // strip spaces. + while (*p && *p != ' ') + p++; // eat protocol identifier + while (*p && *p == ' ') + p++; // strip trailing spaces. + while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) + *dst++ = *p++; + *dst = '\0'; + + // a='framesize:96 320-240' + // set our parameters + par->width = atoi(buf1); + par->height = atoi(p + 1); // skip the - +} + int ff_h264_handle_aggregated_packet(AVFormatContext *ctx, AVPacket *pkt, const uint8_t *buf, int len, int skip_between, int *nal_counters, @@ -237,15 +257,35 @@ int ff_h264_handle_aggregated_packet(AVFormatContext *ctx, AVPacket *pkt, return 0; } +int ff_h264_handle_frag_packet(AVPacket *pkt, const uint8_t *buf, int len, + int start_bit, const uint8_t *nal_header, + int nal_header_len) +{ + int ret; + int tot_len = len; + int pos = 0; + if (start_bit) + tot_len += sizeof(start_sequence) + nal_header_len; + if ((ret = av_new_packet(pkt, tot_len)) < 0) + return ret; + if (start_bit) { + memcpy(pkt->data + pos, start_sequence, sizeof(start_sequence)); + pos += sizeof(start_sequence); + memcpy(pkt->data + pos, nal_header, nal_header_len); + pos += nal_header_len; + } + memcpy(pkt->data + pos, buf, len); + return 0; +} + static int h264_handle_packet_fu_a(AVFormatContext *ctx, AVPacket *pkt, const uint8_t *buf, int len, int *nal_counters, int nal_mask) { uint8_t fu_indicator, fu_header, start_bit, nal_type, nal; - int ret; if (len < 3) { - av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H264 RTP packet\n"); + av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H.264 RTP packet\n"); return AVERROR_INVALIDDATA; } @@ -259,22 +299,9 @@ static int h264_handle_packet_fu_a(AVFormatContext *ctx, AVPacket *pkt, buf += 2; len -= 2; - if (start_bit) { - if (nal_counters) - nal_counters[nal_type & nal_mask]++; - /* copy in the start sequence, and the reconstructed nal */ - if ((ret = av_new_packet(pkt, sizeof(start_sequence) + sizeof(nal) + len)) < 0) - return ret; - memcpy(pkt->data, start_sequence, sizeof(start_sequence)); - pkt->data[sizeof(start_sequence)] = nal; - memcpy(pkt->data + sizeof(start_sequence) + sizeof(nal), buf, len); - } else { - if ((ret = av_new_packet(pkt, len)) < 0) - return ret; - memcpy(pkt->data, buf, len); - } - - return 0; + if (start_bit && nal_counters) + nal_counters[nal_type & nal_mask]++; + return ff_h264_handle_frag_packet(pkt, buf, len, start_bit, &nal, 1); } // return 0 on packet, no more left, 1 on packet, 1 on partial packet @@ -288,14 +315,14 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, int result = 0; if (!len) { - av_log(ctx, AV_LOG_ERROR, "Empty H264 RTP packet\n"); + av_log(ctx, AV_LOG_ERROR, "Empty H.264 RTP packet\n"); return AVERROR_INVALIDDATA; } nal = buf[0]; type = nal & 0x1f; - /* Simplify the case (these are all the nal types used internally by - * the h264 codec). */ + /* Simplify the case (these are all the NAL types used internally by + * the H.264 codec). */ if (type >= 1 && type <= 23) type = 1; switch (type) { @@ -320,10 +347,8 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, case 26: // MTAP-16 case 27: // MTAP-24 case 29: // FU-B - av_log(ctx, AV_LOG_ERROR, - "Unhandled type (%d) (See RFC for implementation details)\n", - type); - result = AVERROR(ENOSYS); + avpriv_report_missing_feature(ctx, "RTP H.264 NAL unit type %d", type); + result = AVERROR_PATCHWELCOME; break; case 28: // FU-A (fragmented nal) @@ -344,12 +369,7 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, return result; } -static PayloadContext *h264_new_context(void) -{ - return av_mallocz(sizeof(PayloadContext) + FF_INPUT_BUFFER_PADDING_SIZE); -} - -static void h264_free_context(PayloadContext *data) +static void h264_close_context(PayloadContext *data) { #ifdef DEBUG int ii; @@ -360,51 +380,21 @@ static void h264_free_context(PayloadContext *data) data->packet_types_received[ii], ii); } #endif - - av_free(data); -} - -static av_cold int h264_init(AVFormatContext *s, int st_index, - PayloadContext *data) -{ - if (st_index < 0) - return 0; - s->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; - return 0; } static int parse_h264_sdp_line(AVFormatContext *s, int st_index, PayloadContext *h264_data, const char *line) { AVStream *stream; - AVCodecContext *codec; const char *p = line; if (st_index < 0) return 0; stream = s->streams[st_index]; - codec = stream->codec; if (av_strstart(p, "framesize:", &p)) { - char buf1[50]; - char *dst = buf1; - - // remove the protocol identifier - while (*p && *p == ' ') - p++; // strip spaces. - while (*p && *p != ' ') - p++; // eat protocol identifier - while (*p && *p == ' ') - p++; // strip trailing spaces. - while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) - *dst++ = *p++; - *dst = '\0'; - - // a='framesize:96 320-240' - // set our parameters - codec->width = atoi(buf1); - codec->height = atoi(p + 1); // skip the - + ff_h264_parse_framesize(stream->codecpar, p); } else if (av_strstart(p, "fmtp:", &p)) { return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264); } else if (av_strstart(p, "cliprect:", &p)) { @@ -418,9 +408,9 @@ RTPDynamicProtocolHandler ff_h264_dynamic_handler = { .enc_name = "H264", .codec_type = AVMEDIA_TYPE_VIDEO, .codec_id = AV_CODEC_ID_H264, - .init = h264_init, + .need_parsing = AVSTREAM_PARSE_FULL, + .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = parse_h264_sdp_line, - .alloc = h264_new_context, - .free = h264_free_context, - .parse_packet = h264_handle_packet + .close = h264_close_context, + .parse_packet = h264_handle_packet, };