X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=733c6d65dc4ed4b060e654f981ca8d0dfa0a1b1f;hb=bbe95ebdadff24127a7c1c9ccf1e7b71aac96cf8;hp=74e615f86ec808d165bbc0d14e5cb060037d5f5b;hpb=ea3672b7d67c432724bdbc8de0221f869b6a04c6;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index 74e615f86ec..733c6d65dc4 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -444,8 +444,9 @@ static int init_input(AVFormatContext *s, const char *filename, s, 0, s->format_probesize); } -static int add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, - AVPacketList **plast_pktl, int ref) +int ff_packet_list_put(AVPacketList **packet_buffer, + AVPacketList **plast_pktl, + AVPacket *pkt, int flags) { AVPacketList *pktl = av_mallocz(sizeof(AVPacketList)); int ret; @@ -453,12 +454,15 @@ static int add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, if (!pktl) return AVERROR(ENOMEM); - if (ref) { + if (flags & FF_PACKETLIST_FLAG_REF_PACKET) { if ((ret = av_packet_ref(&pktl->pkt, pkt)) < 0) { av_free(pktl); return ret; } } else { + // TODO: Adapt callers in this file so the line below can use + // av_packet_move_ref() to effectively move the reference + // to the list. pktl->pkt = *pkt; } @@ -485,9 +489,10 @@ int avformat_queue_attached_pictures(AVFormatContext *s) continue; } - ret = add_to_pktbuf(&s->internal->raw_packet_buffer, - &s->streams[i]->attached_pic, - &s->internal->raw_packet_buffer_end, 1); + ret = ff_packet_list_put(&s->internal->raw_packet_buffer, + &s->internal->raw_packet_buffer_end, + &s->streams[i]->attached_pic, + FF_PACKETLIST_FLAG_REF_PACKET); if (ret < 0) return ret; } @@ -560,7 +565,11 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, goto fail; } +#if FF_API_FORMAT_FILENAME +FF_DISABLE_DEPRECATION_WARNINGS av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename)); +FF_ENABLE_DEPRECATION_WARNINGS +#endif if ((ret = init_input(s, filename, &tmp)) < 0) goto fail; s->probe_score = ret; @@ -863,13 +872,9 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) continue; } - if (!pkt->buf) { - AVPacket tmp = { 0 }; - ret = av_packet_ref(&tmp, pkt); - if (ret < 0) - return ret; - *pkt = tmp; - } + err = av_packet_make_refcounted(pkt); + if (err < 0) + return err; if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) && (pkt->flags & AV_PKT_FLAG_CORRUPT)) { @@ -909,8 +914,9 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) if (!pktl && st->request_probe <= 0) return ret; - err = add_to_pktbuf(&s->internal->raw_packet_buffer, pkt, - &s->internal->raw_packet_buffer_end, 0); + err = ff_packet_list_put(&s->internal->raw_packet_buffer, + &s->internal->raw_packet_buffer_end, + pkt, 0); if (err) return err; s->internal->raw_packet_buffer_remaining_size -= pkt->size; @@ -929,6 +935,7 @@ static int determinable_frame_size(AVCodecContext *avctx) case AV_CODEC_ID_MP1: case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: + case AV_CODEC_ID_CODEC2: return 1; } @@ -1122,6 +1129,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, if (st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE || + st->cur_dts < INT_MIN + RELATIVE_TS_BASE || is_relative(dts)) return; @@ -1153,7 +1161,9 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, } if (st->start_time == AV_NOPTS_VALUE) { - st->start_time = pts; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || !(pkt->flags & AV_PKT_FLAG_DISCARD)) { + st->start_time = pts; + } if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate) st->start_time += av_rescale_q(st->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base); } @@ -1405,14 +1415,17 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif } -static void free_packet_buffer(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) +void ff_packet_list_free(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) { - while (*pkt_buf) { - AVPacketList *pktl = *pkt_buf; - *pkt_buf = pktl->next; + AVPacketList *tmp = *pkt_buf; + + while (tmp) { + AVPacketList *pktl = tmp; + tmp = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); } + *pkt_buf = NULL; *pkt_buf_end = NULL; } @@ -1497,8 +1510,9 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) compute_pkt_fields(s, st, st->parser, &out_pkt, next_dts, next_pts); - ret = add_to_pktbuf(&s->internal->parse_queue, &out_pkt, - &s->internal->parse_queue_end, 1); + ret = ff_packet_list_put(&s->internal->parse_queue, + &s->internal->parse_queue_end, + &out_pkt, FF_PACKETLIST_FLAG_REF_PACKET); av_packet_unref(&out_pkt); if (ret < 0) goto fail; @@ -1515,9 +1529,9 @@ fail: return ret; } -static int read_from_packet_buffer(AVPacketList **pkt_buffer, - AVPacketList **pkt_buffer_end, - AVPacket *pkt) +int ff_packet_list_get(AVPacketList **pkt_buffer, + AVPacketList **pkt_buffer_end, + AVPacket *pkt) { AVPacketList *pktl; av_assert0(*pkt_buffer); @@ -1663,7 +1677,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } if (!got_packet && s->internal->parse_queue) - ret = read_from_packet_buffer(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt); + ret = ff_packet_list_get(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt); if (ret >= 0) { AVStream *st = s->streams[pkt->stream_index]; @@ -1742,7 +1756,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) if (!genpts) { ret = s->internal->packet_buffer - ? read_from_packet_buffer(&s->internal->packet_buffer, + ? ff_packet_list_get(&s->internal->packet_buffer, &s->internal->packet_buffer_end, pkt) : read_frame_internal(s, pkt); if (ret < 0) @@ -1791,7 +1805,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) st = s->streams[next_pkt->stream_index]; if (!(next_pkt->pts == AV_NOPTS_VALUE && st->discard < AVDISCARD_ALL && next_pkt->dts != AV_NOPTS_VALUE && !eof)) { - ret = read_from_packet_buffer(&s->internal->packet_buffer, + ret = ff_packet_list_get(&s->internal->packet_buffer, &s->internal->packet_buffer_end, pkt); goto return_packet; } @@ -1806,8 +1820,9 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) return ret; } - ret = add_to_pktbuf(&s->internal->packet_buffer, pkt, - &s->internal->packet_buffer_end, 1); + ret = ff_packet_list_put(&s->internal->packet_buffer, + &s->internal->packet_buffer_end, + pkt, FF_PACKETLIST_FLAG_REF_PACKET); av_packet_unref(pkt); if (ret < 0) return ret; @@ -1834,9 +1849,9 @@ static void flush_packet_queue(AVFormatContext *s) { if (!s->internal) return; - free_packet_buffer(&s->internal->parse_queue, &s->internal->parse_queue_end); - free_packet_buffer(&s->internal->packet_buffer, &s->internal->packet_buffer_end); - free_packet_buffer(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end); + ff_packet_list_free(&s->internal->parse_queue, &s->internal->parse_queue_end); + ff_packet_list_free(&s->internal->packet_buffer, &s->internal->packet_buffer_end); + ff_packet_list_free(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end); s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; } @@ -2061,7 +2076,7 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance) int64_t pos_delta = 0; int64_t skip = 0; //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable - const char *proto = avio_find_protocol_name(s->filename); + const char *proto = avio_find_protocol_name(s->url); if (!proto) { av_log(s, AV_LOG_INFO, @@ -2634,7 +2649,7 @@ static void update_stream_timings(AVFormatContext *ic) else if (start_time > start_time_text) av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream starttime %f\n", start_time_text / (float)AV_TIME_BASE); - if (end_time == INT64_MIN || (end_time < end_time_text && end_time_text - end_time < AV_TIME_BASE)) { + if (end_time == INT64_MIN || (end_time < end_time_text && end_time_text - (uint64_t)end_time < AV_TIME_BASE)) { end_time = end_time_text; } else if (end_time < end_time_text) { av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream endtime %f\n", end_time_text / (float)AV_TIME_BASE); @@ -3238,23 +3253,20 @@ static int tb_unreliable(AVCodecContext *c) int ff_alloc_extradata(AVCodecParameters *par, int size) { - int ret; + av_freep(&par->extradata); + par->extradata_size = 0; - if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { - par->extradata = NULL; - par->extradata_size = 0; + if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) return AVERROR(EINVAL); - } + par->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); - if (par->extradata) { - memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); - par->extradata_size = size; - ret = 0; - } else { - par->extradata_size = 0; - ret = AVERROR(ENOMEM); - } - return ret; + if (!par->extradata) + return AVERROR(ENOMEM); + + memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + par->extradata_size = size; + + return 0; } int ff_get_extradata(AVFormatContext *s, AVCodecParameters *par, AVIOContext *pb, int size) @@ -3739,8 +3751,9 @@ FF_ENABLE_DEPRECATION_WARNINGS pkt = &pkt1; if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { - ret = add_to_pktbuf(&ic->internal->packet_buffer, pkt, - &ic->internal->packet_buffer_end, 0); + ret = ff_packet_list_put(&ic->internal->packet_buffer, + &ic->internal->packet_buffer_end, + pkt, 0); if (ret < 0) goto find_stream_info_err; } @@ -3776,7 +3789,7 @@ FF_ENABLE_DEPRECATION_WARNINGS if (st->info->fps_last_dts != AV_NOPTS_VALUE && st->info->fps_last_dts_idx > st->info->fps_first_dts_idx && (pkt->dts - st->info->fps_last_dts) / 1000 > - (st->info->fps_last_dts - st->info->fps_first_dts) / + (st->info->fps_last_dts - (uint64_t)st->info->fps_first_dts) / (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) { av_log(ic, AV_LOG_WARNING, "DTS discontinuity in stream %d: packet %d with DTS " @@ -5058,11 +5071,94 @@ FF_ENABLE_DEPRECATION_WARNINGS if (s->programs[i]->id != prog_id) continue; - if (*endptr++ == ':') { - int stream_idx = strtol(endptr, NULL, 0); - return stream_idx >= 0 && - stream_idx < s->programs[i]->nb_stream_indexes && - st->index == s->programs[i]->stream_index[stream_idx]; + if (*endptr++ == ':') { // p::.... + if ( *endptr == 'a' || *endptr == 'v' || + *endptr == 's' || *endptr == 'd') { // p::[:] + enum AVMediaType type; + + switch (*endptr++) { + case 'v': type = AVMEDIA_TYPE_VIDEO; break; + case 'a': type = AVMEDIA_TYPE_AUDIO; break; + case 's': type = AVMEDIA_TYPE_SUBTITLE; break; + case 'd': type = AVMEDIA_TYPE_DATA; break; + default: av_assert0(0); + } + if (*endptr++ == ':') { // p::: + int stream_idx = strtol(endptr, NULL, 0), type_counter = 0; + for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) { + int stream_index = s->programs[i]->stream_index[j]; + if (st->index == s->programs[i]->stream_index[j]) { +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + return type_counter == stream_idx && + (type == st->codecpar->codec_type || + type == st->codec->codec_type); +FF_ENABLE_DEPRECATION_WARNINGS +#else + return type_counter == stream_idx && + type == st->codecpar->codec_type; +#endif + } +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + if (type == s->streams[stream_index]->codecpar->codec_type || + type == s->streams[stream_index]->codec->codec_type) + type_counter++; +FF_ENABLE_DEPRECATION_WARNINGS +#else + if (type == s->streams[stream_index]->codecpar->codec_type) + type_counter++; +#endif + } + return 0; + } else { // p:: + for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) + if (st->index == s->programs[i]->stream_index[j]) { +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + return type == st->codecpar->codec_type || + type == st->codec->codec_type; +FF_ENABLE_DEPRECATION_WARNINGS +#else + return type == st->codecpar->codec_type; +#endif + } + return 0; + } + + } else if ( *endptr == 'm') { // p::m: + AVDictionaryEntry *tag; + char *key, *val; + int ret = 0; + + if (*(++endptr) != ':') { + av_log(s, AV_LOG_ERROR, "Invalid stream specifier syntax, missing ':' sign after :m.\n"); + return AVERROR(EINVAL); + } + + val = strchr(++endptr, ':'); + key = val ? av_strndup(endptr, val - endptr) : av_strdup(endptr); + if (!key) + return AVERROR(ENOMEM); + + for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) + if (st->index == s->programs[i]->stream_index[j]) { + tag = av_dict_get(st->metadata, key, NULL, 0); + if (tag && (!val || !strcmp(tag->value, val + 1))) + ret = 1; + + break; + } + + av_freep(&key); + return ret; + + } else { // p:: + int stream_idx = strtol(endptr, NULL, 0); + return stream_idx >= 0 && + stream_idx < s->programs[i]->nb_stream_indexes && + st->index == s->programs[i]->stream_index[stream_idx]; + } } for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) @@ -5648,5 +5744,9 @@ void ff_format_set_url(AVFormatContext *s, char *url) av_assert0(url); av_freep(&s->url); s->url = url; +#if FF_API_FORMAT_FILENAME +FF_DISABLE_DEPRECATION_WARNINGS av_strlcpy(s->filename, url, sizeof(s->filename)); +FF_ENABLE_DEPRECATION_WARNINGS +#endif }