diff mbox series

[FFmpeg-devel,4/4] ffmpeg: replace custom channel_layout code with an SpecifierOpt based one

Message ID 20220318224748.44929-1-jamrial@gmail.com
State New
Headers show
Series [FFmpeg-devel,1/3] avformat/slndec: add support to set channel layout | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_aarch64_jetson success Make finished
andriy/make_fate_aarch64_jetson success Make fate finished
andriy/make_armv7_RPi4 success Make finished
andriy/make_fate_armv7_RPi4 success Make fate finished

Commit Message

James Almer March 18, 2022, 10:47 p.m. UTC
This is cleaner and allows fine tuning which stream the option is applied to.

Signed-off-by: James Almer <jamrial@gmail.com>
---
 fftools/ffmpeg.h     |  2 ++
 fftools/ffmpeg_opt.c | 84 ++++++++++++++++++--------------------------
 2 files changed, 36 insertions(+), 50 deletions(-)

Comments

Michael Niedermayer March 19, 2022, 6:29 p.m. UTC | #1
On Fri, Mar 18, 2022 at 07:47:48PM -0300, James Almer wrote:
> This is cleaner and allows fine tuning which stream the option is applied to.
> 
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  fftools/ffmpeg.h     |  2 ++
>  fftools/ffmpeg_opt.c | 84 ++++++++++++++++++--------------------------
>  2 files changed, 36 insertions(+), 50 deletions(-)

Not sure its intended or not but
This changes the output of

./ffmpeg -channel_layout 3.0 -ac 3 -f u8 -i /dev/zero -t 1 /tmp/file-old.wav

thx

[...]
James Almer March 20, 2022, 6:03 p.m. UTC | #2
On 3/19/2022 3:29 PM, Michael Niedermayer wrote:
> On Fri, Mar 18, 2022 at 07:47:48PM -0300, James Almer wrote:
>> This is cleaner and allows fine tuning which stream the option is applied to.
>>
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>   fftools/ffmpeg.h     |  2 ++
>>   fftools/ffmpeg_opt.c | 84 ++++++++++++++++++--------------------------
>>   2 files changed, 36 insertions(+), 50 deletions(-)
> 
> Not sure its intended or not but
> This changes the output of
> 
No, it's probably not intended.

> ./ffmpeg -channel_layout 3.0 -ac 3 -f u8 -i /dev/zero -t 1 /tmp/file-old.wav

I assume (since i can't test) that a 2.1 layout is being set instead, if 
any.
Guess i need to change how and with what priority "channels" and 
"ch_layout" in pcm demuxer are parsed.

> 
> thx
> 
> [...]
> 
> 
> _______________________________________________
> 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".
diff mbox series

Patch

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 6a19dc9c7c..1e14bf9fa9 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -96,6 +96,8 @@  typedef struct OptionsContext {
 
     SpecifierOpt *codec_names;
     int        nb_codec_names;
+    SpecifierOpt *audio_ch_layouts;
+    int        nb_audio_ch_layouts;
     SpecifierOpt *audio_channels;
     int        nb_audio_channels;
     SpecifierOpt *audio_sample_rate;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 70e6502f22..f5c759c6d1 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -55,6 +55,7 @@ 
 
 static const char *const opt_name_codec_names[]               = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL};
 static const char *const opt_name_audio_channels[]            = {"ac", NULL};
+static const char *const opt_name_audio_ch_layouts[]          = {"channel_layout", NULL};
 static const char *const opt_name_audio_sample_rate[]         = {"ar", NULL};
 static const char *const opt_name_frame_rates[]               = {"r", NULL};
 static const char *const opt_name_max_frame_rates[]           = {"fpsmax", NULL};
@@ -1124,6 +1125,15 @@  static int open_input_file(OptionsContext *o, const char *filename)
             av_dict_set_int(&o->g->format_opts, "channels", o->audio_channels[o->nb_audio_channels - 1].u.i, 0);
         }
     }
+    if (o->nb_audio_ch_layouts) {
+        const AVClass *priv_class;
+        if (file_iformat && (priv_class = file_iformat->priv_class) &&
+            av_opt_find(&priv_class, "ch_layout", NULL, 0,
+                        AV_OPT_SEARCH_FAKE_OBJ)) {
+            av_dict_set(&o->g->format_opts, "ch_layout", o->audio_ch_layouts[o->nb_audio_ch_layouts - 1].u.str, 0);
+        }
+
+    }
     if (o->nb_frame_rates) {
         const AVClass *priv_class;
         /* set the format-level framerate option;
@@ -1946,6 +1956,7 @@  static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
 
     if (!ost->stream_copy) {
         int channels = 0;
+        char *layout = NULL;
         char *sample_fmt = NULL;
 
         MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st);
@@ -1954,6 +1965,27 @@  static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
             audio_enc->ch_layout.nb_channels = channels;
         }
 
+        MATCH_PER_STREAM_OPT(audio_ch_layouts, str, layout, oc, st);
+        if (layout) {
+            if (av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) {
+#if FF_API_OLD_CHANNEL_LAYOUT
+                uint64_t mask;
+                AV_NOWARN_DEPRECATED({
+                mask = av_get_channel_layout(layout);
+                })
+                if (!mask) {
+#endif
+                    av_log(NULL, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout);
+                    exit_program(1);
+#if FF_API_OLD_CHANNEL_LAYOUT
+                }
+                av_log(NULL, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n",
+                       layout);
+                av_channel_layout_from_mask(&audio_enc->ch_layout, mask);
+#endif
+            }
+        }
+
         MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st);
         if (sample_fmt &&
             (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) {
@@ -3235,54 +3267,6 @@  static int opt_timecode(void *optctx, const char *opt, const char *arg)
     return ret;
 }
 
-static int opt_channel_layout(void *optctx, const char *opt, const char *arg)
-{
-    OptionsContext *o = optctx;
-    char layout_str[32];
-    char *stream_str;
-    char *ac_str;
-    int ret, ac_str_size;
-    AVChannelLayout layout = { 0 };
-
-    ret = av_channel_layout_from_string(&layout, arg);
-    if (ret < 0) {
-#if FF_API_OLD_CHANNEL_LAYOUT
-        uint64_t mask;
-        AV_NOWARN_DEPRECATED({
-        mask = av_get_channel_layout(arg);
-        })
-        if (!mask) {
-#endif
-        av_log(NULL, AV_LOG_ERROR, "Unknown channel layout: %s\n", arg);
-        return AVERROR(EINVAL);
-#if FF_API_OLD_CHANNEL_LAYOUT
-        }
-        av_log(NULL, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n",
-               arg);
-        av_channel_layout_from_mask(&layout, mask);
-#endif
-    }
-
-    ret = opt_default_new(o, opt, arg);
-    if (ret < 0)
-        return ret;
-
-    /* set 'ac' option based on channel layout */
-    snprintf(layout_str, sizeof(layout_str), "%d", layout.nb_channels);
-    stream_str = strchr(opt, ':');
-    ac_str_size = 3 + (stream_str ? strlen(stream_str) : 0);
-    ac_str = av_mallocz(ac_str_size);
-    if (!ac_str)
-        return AVERROR(ENOMEM);
-    av_strlcpy(ac_str, "ac", 3);
-    if (stream_str)
-        av_strlcat(ac_str, stream_str, ac_str_size);
-    ret = parse_option(o, ac_str, layout_str, options);
-    av_free(ac_str);
-
-    return ret;
-}
-
 static int opt_audio_qscale(void *optctx, const char *opt, const char *arg)
 {
     OptionsContext *o = optctx;
@@ -3827,8 +3811,8 @@  const OptionDef options[] = {
     { "sample_fmt",     OPT_AUDIO | HAS_ARG  | OPT_EXPERT | OPT_SPEC |
                         OPT_STRING | OPT_INPUT | OPT_OUTPUT,                       { .off = OFFSET(sample_fmts) },
         "set sample format", "format" },
-    { "channel_layout", OPT_AUDIO | HAS_ARG  | OPT_EXPERT | OPT_PERFILE |
-                        OPT_INPUT | OPT_OUTPUT,                                    { .func_arg = opt_channel_layout },
+    { "channel_layout", OPT_AUDIO | HAS_ARG  | OPT_EXPERT | OPT_SPEC |
+                        OPT_STRING | OPT_INPUT | OPT_OUTPUT,                       { .off = OFFSET(audio_ch_layouts) },
         "set channel layout", "layout" },
     { "af",             OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_filters },
         "set audio filters", "filter_graph" },