X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=3d764c18d644387b442f092133e2fd03f94c1a8f;hb=3b5b977c9f96e2c3803317ad75253801bc571791;hp=d113a16c8091e5397dee96714d92d5e073d13def;hpb=1811b7d1f5330e04a48b1d6425cf1ef6ed776ed1;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index d113a16c809..3d764c18d64 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -357,7 +357,7 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st, { 0 } }; int score; - AVInputFormat *fmt = av_probe_input_format3(pd, 1, &score); + const AVInputFormat *fmt = av_probe_input_format3(pd, 1, &score); if (fmt) { int i; @@ -535,7 +535,7 @@ FF_ENABLE_DEPRECATION_WARNINGS int avformat_open_input(AVFormatContext **ps, const char *filename, - AVInputFormat *fmt, AVDictionary **options) + ff_const59 AVInputFormat *fmt, AVDictionary **options) { AVFormatContext *s = *ps; int i, ret = 0; @@ -1402,8 +1402,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, st->cur_dts = pkt->dts; if (s->debug & FF_FDEBUG_TS) - av_log(s, AV_LOG_DEBUG, "OUTdelayed:%d/%d pts:%s, dts:%s cur_dts:%s\n", - presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts)); + av_log(s, AV_LOG_DEBUG, "OUTdelayed:%d/%d pts:%s, dts:%s cur_dts:%s st:%d (%d)\n", + presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), st->index, st->id); /* update flags */ if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA || is_intra_only(st->codecpar->codec_id)) @@ -2163,7 +2163,7 @@ static int64_t ff_read_timestamp(AVFormatContext *s, int stream_index, int64_t * int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags) { - AVInputFormat *avif = s->iformat; + const AVInputFormat *avif = s->iformat; int64_t av_uninit(pos_min), av_uninit(pos_max), pos, pos_limit; int64_t ts_min, ts_max, ts; int index; @@ -5100,178 +5100,208 @@ AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *f /** * Matches a stream specifier (but ignores requested index). * - * @param index set if a specific index is requested from the matching streams + * @param indexptr set to point to the requested stream index if there is one * * @return <0 on error * 0 if st is NOT a matching stream * >0 if st is a matching stream */ static int match_stream_specifier(AVFormatContext *s, AVStream *st, - const char *spec, int *index) -{ - if (*spec <= '9' && *spec >= '0') { /* opt:index */ - if (index) - *index = strtol(spec, NULL, 0); - return 1; - } else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' || - *spec == 't' || *spec == 'V') { /* opt:[vasdtV] */ - enum AVMediaType type; - int nopic = 0; + const char *spec, const char **indexptr, AVProgram **p) +{ + int match = 1; /* Stores if the specifier matches so far. */ + while (*spec) { + if (*spec <= '9' && *spec >= '0') { /* opt:index */ + if (indexptr) + *indexptr = spec; + return match; + } else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' || + *spec == 't' || *spec == 'V') { /* opt:[vasdtV] */ + enum AVMediaType type; + int nopic = 0; + + switch (*spec++) { + 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; + case 't': type = AVMEDIA_TYPE_ATTACHMENT; break; + case 'V': type = AVMEDIA_TYPE_VIDEO; nopic = 1; break; + default: av_assert0(0); + } + if (*spec && *spec++ != ':') /* If we are not at the end, then another specifier must follow. */ + return AVERROR(EINVAL); - switch (*spec++) { - 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; - case 't': type = AVMEDIA_TYPE_ATTACHMENT; break; - case 'V': type = AVMEDIA_TYPE_VIDEO; nopic = 1; break; - default: av_assert0(0); - } #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS - if (type != st->codecpar->codec_type - && (st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN || st->codec->codec_type != type)) - return 0; -FF_ENABLE_DEPRECATION_WARNINGS + if (type != st->codecpar->codec_type + && (st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN || st->codec->codec_type != type)) + match = 0; + FF_ENABLE_DEPRECATION_WARNINGS #else - if (type != st->codecpar->codec_type) - return 0; + if (type != st->codecpar->codec_type) + match = 0; #endif - if (nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - return 0; - if (*spec++ == ':') /* possibly followed by another specifier */ - return match_stream_specifier(s, st, spec, index); - return 1; - } else if (*spec == 'p' && *(spec + 1) == ':') { - int prog_id, i, j; - char *endptr; - spec += 2; - prog_id = strtol(spec, &endptr, 0); - for (i = 0; i < s->nb_programs; i++) { - if (s->programs[i]->id != prog_id) - continue; + if (nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + match = 0; + } else if (*spec == 'p' && *(spec + 1) == ':') { + int prog_id, i, j; + int found = 0; + char *endptr; + spec += 2; + prog_id = strtol(spec, &endptr, 0); + /* Disallow empty id and make sure that if we are not at the end, then another specifier must follow. */ + if (spec == endptr || (*endptr && *endptr++ != ':')) + return AVERROR(EINVAL); + spec = endptr; + if (match) { + for (i = 0; i < s->nb_programs; i++) { + if (s->programs[i]->id != prog_id) + continue; - for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) { - if (st->index == s->programs[i]->stream_index[j]) { - if (*endptr++ == ':') { // p::.... - return match_stream_specifier(s, st, endptr, index); - } else { - return 1; + for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) { + if (st->index == s->programs[i]->stream_index[j]) { + found = 1; + if (p) + *p = s->programs[i]; + i = s->nb_programs; + break; + } } } } - } - return 0; - } else if (*spec == '#' || - (*spec == 'i' && *(spec + 1) == ':')) { - int stream_id; - char *endptr; - spec += 1 + (*spec == 'i'); - stream_id = strtol(spec, &endptr, 0); - if (!*endptr) - return stream_id == st->id; - } else if (*spec == 'm' && *(spec + 1) == ':') { - AVDictionaryEntry *tag; - char *key, *val; - int ret; - - spec += 2; - val = strchr(spec, ':'); - - key = val ? av_strndup(spec, val - spec) : av_strdup(spec); - if (!key) - return AVERROR(ENOMEM); - - tag = av_dict_get(st->metadata, key, NULL, 0); - if (tag) { - if (!val || !strcmp(tag->value, val + 1)) - ret = 1; - else - ret = 0; - } else - ret = 0; - - av_freep(&key); - return ret; - } else if (*spec == 'u') { - AVCodecParameters *par = st->codecpar; + if (!found) + match = 0; + } else if (*spec == '#' || + (*spec == 'i' && *(spec + 1) == ':')) { + int stream_id; + char *endptr; + spec += 1 + (*spec == 'i'); + stream_id = strtol(spec, &endptr, 0); + if (spec == endptr || *endptr) /* Disallow empty id and make sure we are at the end. */ + return AVERROR(EINVAL); + return match && (stream_id == st->id); + } else if (*spec == 'm' && *(spec + 1) == ':') { + AVDictionaryEntry *tag; + char *key, *val; + int ret; + + if (match) { + spec += 2; + val = strchr(spec, ':'); + + key = val ? av_strndup(spec, val - spec) : av_strdup(spec); + if (!key) + return AVERROR(ENOMEM); + + tag = av_dict_get(st->metadata, key, NULL, 0); + if (tag) { + if (!val || !strcmp(tag->value, val + 1)) + ret = 1; + else + ret = 0; + } else + ret = 0; + + av_freep(&key); + } + return match && ret; + } else if (*spec == 'u' && *(spec + 1) == '\0') { + AVCodecParameters *par = st->codecpar; #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS - AVCodecContext *codec = st->codec; + AVCodecContext *codec = st->codec; FF_ENABLE_DEPRECATION_WARNINGS #endif - int val; - switch (par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - val = par->sample_rate && par->channels; + int val; + switch (par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + val = par->sample_rate && par->channels; #if FF_API_LAVF_AVCTX - val = val || (codec->sample_rate && codec->channels); + val = val || (codec->sample_rate && codec->channels); #endif - if (par->format == AV_SAMPLE_FMT_NONE + if (par->format == AV_SAMPLE_FMT_NONE #if FF_API_LAVF_AVCTX - && codec->sample_fmt == AV_SAMPLE_FMT_NONE + && codec->sample_fmt == AV_SAMPLE_FMT_NONE #endif - ) - return 0; - break; - case AVMEDIA_TYPE_VIDEO: - val = par->width && par->height; + ) + return 0; + break; + case AVMEDIA_TYPE_VIDEO: + val = par->width && par->height; #if FF_API_LAVF_AVCTX - val = val || (codec->width && codec->height); + val = val || (codec->width && codec->height); #endif - if (par->format == AV_PIX_FMT_NONE + if (par->format == AV_PIX_FMT_NONE #if FF_API_LAVF_AVCTX - && codec->pix_fmt == AV_PIX_FMT_NONE + && codec->pix_fmt == AV_PIX_FMT_NONE #endif - ) - return 0; - break; - case AVMEDIA_TYPE_UNKNOWN: - val = 0; - break; - default: - val = 1; - break; - } + ) + return 0; + break; + case AVMEDIA_TYPE_UNKNOWN: + val = 0; + break; + default: + val = 1; + break; + } #if FF_API_LAVF_AVCTX - return (par->codec_id != AV_CODEC_ID_NONE || codec->codec_id != AV_CODEC_ID_NONE) && val != 0; + return match && ((par->codec_id != AV_CODEC_ID_NONE || codec->codec_id != AV_CODEC_ID_NONE) && val != 0); #else - return par->codec_id != AV_CODEC_ID_NONE && val != 0; + return match && (par->codec_id != AV_CODEC_ID_NONE && val != 0); #endif - } else if (!*spec) /* empty specifier, matches everything */ - return 1; + } else { + return AVERROR(EINVAL); + } + } - return AVERROR(EINVAL); + return match; } int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) { - int ret; - int index = -1; + int ret, index; + char *endptr; + const char *indexptr = NULL; + AVProgram *p = NULL; + int nb_streams; - /* This is not really needed but saves us a loop for simple stream index specifiers. */ - if (*spec <= '9' && *spec >= '0') /* opt:index */ - return strtol(spec, NULL, 0) == st->index; + ret = match_stream_specifier(s, st, spec, &indexptr, &p); + if (ret < 0) + goto error; - ret = match_stream_specifier(s, st, spec, &index); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); + if (!indexptr) return ret; + + index = strtol(indexptr, &endptr, 0); + if (*endptr) { /* We can't have anything after the requested index. */ + ret = AVERROR(EINVAL); + goto error; } - if (!ret || index < 0) - return ret; + + /* This is not really needed but saves us a loop for simple stream index specifiers. */ + if (spec == indexptr) + return (index == st->index); /* If we requested a matching stream index, we have to ensure st is that. */ - for (int i = 0; i < s->nb_streams && index >= 0; i++) { - int ret = match_stream_specifier(s, s->streams[i], spec, NULL); + nb_streams = p ? p->nb_stream_indexes : s->nb_streams; + for (int i = 0; i < nb_streams && index >= 0; i++) { + AVStream *candidate = p ? s->streams[p->stream_index[i]] : s->streams[i]; + ret = match_stream_specifier(s, candidate, spec, NULL, NULL); if (ret < 0) - return ret; - if (ret > 0 && index-- == 0 && st == s->streams[i]) + goto error; + if (ret > 0 && index-- == 0 && st == candidate) return 1; } return 0; + +error: + if (ret == AVERROR(EINVAL)) + av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); + return ret; } int ff_generate_avci_extradata(AVStream *st)