From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> To: ffmpeg-devel@ffmpeg.org Cc: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> Subject: [FFmpeg-devel] [PATCH 32/44] avformat/utils: Move matching stream specificiers to avformat.c Date: Sat, 7 May 2022 13:28:18 +0200 Message-ID: <AS8PR01MB79440520713F28F53D0641B68FC49@AS8PR01MB7944.eurprd01.prod.exchangelabs.com> (raw) In-Reply-To: <AS8PR01MB794467A492C922D9DA178B408FC59@AS8PR01MB7944.eurprd01.prod.exchangelabs.com> It is not to call this with a muxer, so move it to avformat.c and not demux_utils.c. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavformat/avformat.c | 179 +++++++++++++++++++++++++++++++++++++++++ libavformat/utils.c | 179 ----------------------------------------- 2 files changed, 179 insertions(+), 179 deletions(-) diff --git a/libavformat/avformat.c b/libavformat/avformat.c index ac0e28a6a9..7fab0dd99d 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -21,9 +21,12 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" #include "libavutil/opt.h" +#include "libavutil/pixfmt.h" +#include "libavutil/samplefmt.h" #include "libavcodec/avcodec.h" #include "libavcodec/bsf.h" #include "libavcodec/packet_internal.h" @@ -257,6 +260,182 @@ void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned idx) } } +/** + * Matches a stream specifier (but ignores requested index). + * + * @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(const AVFormatContext *s, const AVStream *st, + const char *spec, const char **indexptr, + const 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); + + if (type != st->codecpar->codec_type) + match = 0; + if (nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + match = 0; + } else if (*spec == 'p' && *(spec + 1) == ':') { + int prog_id; + 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 (unsigned i = 0; i < s->nb_programs; i++) { + if (s->programs[i]->id != prog_id) + continue; + + for (unsigned 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; + } + } + } + } + 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) == ':') { + const 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') { + const AVCodecParameters *par = st->codecpar; + int val; + switch (par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + val = par->sample_rate && par->ch_layout.nb_channels; + if (par->format == AV_SAMPLE_FMT_NONE) + return 0; + break; + case AVMEDIA_TYPE_VIDEO: + val = par->width && par->height; + if (par->format == AV_PIX_FMT_NONE) + return 0; + break; + case AVMEDIA_TYPE_UNKNOWN: + val = 0; + break; + default: + val = 1; + break; + } + return match && (par->codec_id != AV_CODEC_ID_NONE && val != 0); + } else { + return AVERROR(EINVAL); + } + } + + return match; +} + +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, + const char *spec) +{ + int ret, index; + char *endptr; + const char *indexptr = NULL; + const AVProgram *p = NULL; + int nb_streams; + + ret = match_stream_specifier(s, st, spec, &indexptr, &p); + if (ret < 0) + goto error; + + 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; + } + + /* 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. */ + nb_streams = p ? p->nb_stream_indexes : s->nb_streams; + for (int i = 0; i < nb_streams && index >= 0; i++) { + const AVStream *candidate = s->streams[p ? p->stream_index[i] : i]; + ret = match_stream_specifier(s, candidate, spec, NULL, NULL); + if (ret < 0) + 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 avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, AVStream *ost, const AVStream *ist, enum AVTimebaseSource copy_tb) diff --git a/libavformat/utils.c b/libavformat/utils.c index f5d24e7a3a..ebee44f47d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -26,9 +26,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" -#include "libavutil/dict.h" #include "libavutil/internal.h" -#include "libavutil/pixfmt.h" #include "libavutil/thread.h" #include "libavutil/time.h" @@ -855,183 +853,6 @@ AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *f return fr; } -/** - * Matches a stream specifier (but ignores requested index). - * - * @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(const AVFormatContext *s, const AVStream *st, - const char *spec, const char **indexptr, - const 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); - - if (type != st->codecpar->codec_type) - match = 0; - if (nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - match = 0; - } else if (*spec == 'p' && *(spec + 1) == ':') { - int prog_id; - 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 (unsigned i = 0; i < s->nb_programs; i++) { - if (s->programs[i]->id != prog_id) - continue; - - for (unsigned 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; - } - } - } - } - 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) == ':') { - const 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') { - const AVCodecParameters *par = st->codecpar; - int val; - switch (par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - val = par->sample_rate && par->ch_layout.nb_channels; - if (par->format == AV_SAMPLE_FMT_NONE) - return 0; - break; - case AVMEDIA_TYPE_VIDEO: - val = par->width && par->height; - if (par->format == AV_PIX_FMT_NONE) - return 0; - break; - case AVMEDIA_TYPE_UNKNOWN: - val = 0; - break; - default: - val = 1; - break; - } - return match && (par->codec_id != AV_CODEC_ID_NONE && val != 0); - } else { - return AVERROR(EINVAL); - } - } - - return match; -} - - -int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, - const char *spec) -{ - int ret, index; - char *endptr; - const char *indexptr = NULL; - const AVProgram *p = NULL; - int nb_streams; - - ret = match_stream_specifier(s, st, spec, &indexptr, &p); - if (ret < 0) - goto error; - - 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; - } - - /* 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. */ - nb_streams = p ? p->nb_stream_indexes : s->nb_streams; - for (int i = 0; i < nb_streams && index >= 0; i++) { - const AVStream *candidate = s->streams[p ? p->stream_index[i] : i]; - ret = match_stream_specifier(s, candidate, spec, NULL, NULL); - if (ret < 0) - 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; -} - void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb) { avio_close(pb); -- 2.32.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2022-05-07 11:34 UTC|newest] Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-05-06 10:31 [FFmpeg-devel] [PATCH] lib*/version: Move library version functions into files of their own Andreas Rheinhardt 2022-05-06 11:09 ` Martin Storsjö 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 02/44] avformat/utils: Use av_realloc_array for reallocating array Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 03/44] avformat/internal: Move muxing-only functions to new mux.h header Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 04/44] avformat/mux: Move ff_choose_timebase to nutenc, its only user Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 05/44] avformat/mux: Move ff_choose_chroma_location to mxfenc, " Andreas Rheinhardt 2022-05-10 7:25 ` Tomas Härdin 2022-05-10 7:29 ` Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 06/44] avformat/utils: Move ff_stream_add_bitstream_filter to mux.c Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 07/44] avformat/utils: Move stream_options, avformat_new_stream to options.c Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 08/44] avformat/mux_utils: Move ff_format_shift_data to new file for mux utils Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 09/44] avformat/utils: Move ff_get_packet_palette() to rawutils.c Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 10/44] avformat/utils: Move creation-time functions to mux_utils Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 11/44] avformat/utils: Move ff_format_output_open() to mux_utils.c Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 12/44] avformat/utils: Move avformat_query_codec() " Andreas Rheinhardt 2022-05-07 11:27 ` [FFmpeg-devel] [PATCH 13/44] avformat/utils: Move av_stream_get_end_pts() " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 14/44] avformat/utils: Move ff_stream_encode_params_copy() " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 15/44] avformat/demux: Add new demux.h header Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 16/44] avformat/internal: Move definition of FFStream->info to demux.h Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 17/44] avformat/utils: Move parser functions to a new file, demux_utils.c Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 18/44] avdevice/v4l2*: Improve included headers Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 19/44] avformat/utils: Move avpriv_new_chapter to demux_utils.c Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 20/44] avformat/utils: Move av_format_inject_global_side_data " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 21/44] avformat/utils: Move avformat_queue_attached_pictures " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 22/44] avformat/utils: Move ff_add_attached_pic " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 23/44] avformat/utils: Move ff_add_param_change " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 24/44] avformat/utils: Move av_read_(play|pause) " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 25/44] avformat/utils: Move ff_generate_avci_extradata " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 26/44] avformat/internal: Make AVFormatContext* a logctx in ff_get_extradata Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 27/44] avformat/utils: Move ff_get_extradata to demux_utils.c Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 28/44] avformat/utils: Move freeing AVFormatContext to a new file avformat.c Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 29/44] avformat/utils: Move av_stream_*_side_data API to avformat.c Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 30/44] avformat/utils: Move adding AVProgram " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 31/44] avformat/utils: Move internal stream timebase stuff " Andreas Rheinhardt 2022-05-07 11:28 ` Andreas Rheinhardt [this message] 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 33/44] avformat/utils: Move guessing frame rate/SAR " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 34/44] avformat/utils: Move av_find_program_from_stream " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 35/44] avformat/utils: Move av_find_default_stream_index " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 36/44] avformat/utils: Move av_find_best_stream " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 37/44] avformat/asf: Move ASF GUIDs to a new file Andreas Rheinhardt 2022-05-07 11:59 ` [FFmpeg-devel] [PATCH v2 " Andreas Rheinhardt 2022-05-07 12:23 ` Soft Works 2022-05-07 12:28 ` Andreas Rheinhardt 2022-05-07 12:52 ` Soft Works 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 38/44] avformat/utils: Move ff_find_stream_index to demux_utils.c Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 39/44] avformat/utils: Move ff_is_intra_only to avformat.c Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 40/44] avformat/utils: Move ff_format_set_url " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 41/44] avformat/utils: Move ff_copy_whiteblacklists " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 42/44] avformat/utils: Move avpriv_set_pts_info() " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 43/44] avformat/utils: Move ff_stream_side_data_copy " Andreas Rheinhardt 2022-05-07 11:28 ` [FFmpeg-devel] [PATCH 44/44] avformat/utils: Move ff_format_io_close.* to options.c, avformat.c Andreas Rheinhardt 2022-05-09 19:14 ` [FFmpeg-devel] [PATCH] lib*/version: Move library version functions into files of their own Andreas Rheinhardt
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=AS8PR01MB79440520713F28F53D0641B68FC49@AS8PR01MB7944.eurprd01.prod.exchangelabs.com \ --to=andreas.rheinhardt@outlook.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git