diff mbox series

[FFmpeg-devel,4/8] fftools/ffmpeg_demux: set options on codec parameters rather than decoder

Message ID 20240105164251.28935-4-anton@khirnov.net
State Accepted
Commit 2ee1c6ffb22aacb90f6513defc4b06948703e77f
Headers show
Series [FFmpeg-devel,1/8] fftools/ffmpeg_demux: replace abort() by av_assert0(0) | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Anton Khirnov Jan. 5, 2024, 4:42 p.m. UTC
This avoids the requirement to always have a decoder context.
---
 fftools/ffmpeg_demux.c | 43 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 22 deletions(-)

Comments

Stefano Sabatini Jan. 6, 2024, 11:31 a.m. UTC | #1
On date Friday 2024-01-05 17:42:47 +0100, Anton Khirnov wrote:
> This avoids the requirement to always have a decoder context.
> ---
>  fftools/ffmpeg_demux.c | 43 +++++++++++++++++++++---------------------
>  1 file changed, 21 insertions(+), 22 deletions(-)
> 
> diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
> index cacdc76a71..892094c512 100644
> --- a/fftools/ffmpeg_demux.c
> +++ b/fftools/ffmpeg_demux.c
> @@ -899,19 +899,18 @@ static int choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream
>      }
>  }
>  
> -static int guess_input_channel_layout(InputStream *ist, int guess_layout_max)
> +static int guess_input_channel_layout(InputStream *ist, AVCodecParameters *par,
> +                                      int guess_layout_max)
>  {
> -    AVCodecContext *dec = ist->dec_ctx;
> -
> -    if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
> +    if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
>          char layout_name[256];
>  
> -        if (dec->ch_layout.nb_channels > guess_layout_max)
> +        if (par->ch_layout.nb_channels > guess_layout_max)
>              return 0;
> -        av_channel_layout_default(&dec->ch_layout, dec->ch_layout.nb_channels);
> -        if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
> +        av_channel_layout_default(&par->ch_layout, par->ch_layout.nb_channels);
> +        if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
>              return 0;
> -        av_channel_layout_describe(&dec->ch_layout, layout_name, sizeof(layout_name));
> +        av_channel_layout_describe(&par->ch_layout, layout_name, sizeof(layout_name));
>          av_log(ist, AV_LOG_WARNING, "Guessed Channel Layout: %s\n", layout_name);
>      }
>      return 1;
> @@ -1145,16 +1144,6 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>          ist->user_set_discard = ist->st->discard;
>      }
>  
> -    ist->dec_ctx = avcodec_alloc_context3(ist->dec);
> -    if (!ist->dec_ctx)
> -        return AVERROR(ENOMEM);
> -
> -    ret = avcodec_parameters_to_context(ist->dec_ctx, par);
> -    if (ret < 0) {
> -        av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n");
> -        return ret;
> -    }
> -
>      if (o->bitexact)
>          av_dict_set(&ist->decoder_opts, "flags", "+bitexact", AV_DICT_MULTIKEY);
>  
> @@ -1181,7 +1170,7 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>      case AVMEDIA_TYPE_AUDIO: {
>          int guess_layout_max = INT_MAX;
>          MATCH_PER_STREAM_OPT(guess_layout_max, i, guess_layout_max, ic, st);
> -        guess_input_channel_layout(ist, guess_layout_max);
> +        guess_input_channel_layout(ist, par, guess_layout_max);
>          break;
>      }
>      case AVMEDIA_TYPE_DATA:
> @@ -1190,7 +1179,7 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>          MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
>          MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
>          if (canvas_size) {
> -            ret = av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height,
> +            ret = av_parse_video_size(&par->width, &par->height,
>                                        canvas_size);
>              if (ret < 0) {
>                  av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
> @@ -1201,8 +1190,8 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>          /* Compute the size of the canvas for the subtitles stream.
>             If the subtitles codecpar has set a size, use it. Otherwise use the
>             maximum dimensions of the video streams in the same file. */
> -        ist->sub2video.w = ist->dec_ctx->width;
> -        ist->sub2video.h = ist->dec_ctx->height;
> +        ist->sub2video.w = par->width;
> +        ist->sub2video.h = par->height;
>          if (!(ist->sub2video.w && ist->sub2video.h)) {
>              for (int j = 0; j < ic->nb_streams; j++) {
>                  AVCodecParameters *par1 = ic->streams[j]->codecpar;
> @@ -1226,6 +1215,16 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>      default: av_assert0(0);
>      }
>  
> +    ist->dec_ctx = avcodec_alloc_context3(ist->dec);
> +    if (!ist->dec_ctx)
> +        return AVERROR(ENOMEM);
> +
> +    ret = avcodec_parameters_to_context(ist->dec_ctx, par);
> +    if (ret < 0) {
> +        av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n");
> +        return ret;
> +    }
> +

LGTM.
James Almer Jan. 6, 2024, 2:22 p.m. UTC | #2
On 1/5/2024 1:42 PM, Anton Khirnov wrote:
> This avoids the requirement to always have a decoder context.
> ---
>   fftools/ffmpeg_demux.c | 43 +++++++++++++++++++++---------------------
>   1 file changed, 21 insertions(+), 22 deletions(-)
> 
> diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
> index cacdc76a71..892094c512 100644
> --- a/fftools/ffmpeg_demux.c
> +++ b/fftools/ffmpeg_demux.c
> @@ -899,19 +899,18 @@ static int choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream
>       }
>   }
>   
> -static int guess_input_channel_layout(InputStream *ist, int guess_layout_max)
> +static int guess_input_channel_layout(InputStream *ist, AVCodecParameters *par,
> +                                      int guess_layout_max)
>   {
> -    AVCodecContext *dec = ist->dec_ctx;
> -
> -    if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
> +    if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
>           char layout_name[256];
>   
> -        if (dec->ch_layout.nb_channels > guess_layout_max)
> +        if (par->ch_layout.nb_channels > guess_layout_max)
>               return 0;
> -        av_channel_layout_default(&dec->ch_layout, dec->ch_layout.nb_channels);
> -        if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
> +        av_channel_layout_default(&par->ch_layout, par->ch_layout.nb_channels);
> +        if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
>               return 0;
> -        av_channel_layout_describe(&dec->ch_layout, layout_name, sizeof(layout_name));
> +        av_channel_layout_describe(&par->ch_layout, layout_name, sizeof(layout_name));
>           av_log(ist, AV_LOG_WARNING, "Guessed Channel Layout: %s\n", layout_name);
>       }
>       return 1;
> @@ -1145,16 +1144,6 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>           ist->user_set_discard = ist->st->discard;
>       }
>   
> -    ist->dec_ctx = avcodec_alloc_context3(ist->dec);
> -    if (!ist->dec_ctx)
> -        return AVERROR(ENOMEM);
> -
> -    ret = avcodec_parameters_to_context(ist->dec_ctx, par);
> -    if (ret < 0) {
> -        av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n");
> -        return ret;
> -    }
> -
>       if (o->bitexact)
>           av_dict_set(&ist->decoder_opts, "flags", "+bitexact", AV_DICT_MULTIKEY);
>   
> @@ -1181,7 +1170,7 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>       case AVMEDIA_TYPE_AUDIO: {
>           int guess_layout_max = INT_MAX;
>           MATCH_PER_STREAM_OPT(guess_layout_max, i, guess_layout_max, ic, st);
> -        guess_input_channel_layout(ist, guess_layout_max);
> +        guess_input_channel_layout(ist, par, guess_layout_max);
>           break;
>       }
>       case AVMEDIA_TYPE_DATA:
> @@ -1190,7 +1179,7 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>           MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
>           MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
>           if (canvas_size) {
> -            ret = av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height,
> +            ret = av_parse_video_size(&par->width, &par->height,
>                                         canvas_size);
>               if (ret < 0) {
>                   av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
> @@ -1201,8 +1190,8 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>           /* Compute the size of the canvas for the subtitles stream.
>              If the subtitles codecpar has set a size, use it. Otherwise use the
>              maximum dimensions of the video streams in the same file. */
> -        ist->sub2video.w = ist->dec_ctx->width;
> -        ist->sub2video.h = ist->dec_ctx->height;
> +        ist->sub2video.w = par->width;
> +        ist->sub2video.h = par->height;
>           if (!(ist->sub2video.w && ist->sub2video.h)) {
>               for (int j = 0; j < ic->nb_streams; j++) {
>                   AVCodecParameters *par1 = ic->streams[j]->codecpar;
> @@ -1226,6 +1215,16 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>       default: av_assert0(0);
>       }
>   
> +    ist->dec_ctx = avcodec_alloc_context3(ist->dec);
> +    if (!ist->dec_ctx)
> +        return AVERROR(ENOMEM);
> +
> +    ret = avcodec_parameters_to_context(ist->dec_ctx, par);
> +    if (ret < 0) {
> +        av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n");
> +        return ret;
> +    }
> +
>       ist->par = avcodec_parameters_alloc();
>       if (!ist->par)
>           return AVERROR(ENOMEM);

This does not fix the issue of the guessed channel layout not being 
present on the output stream, but might be a change in the right direction.

before:

> $ ./ffmpeg -i ~/samples/wav/200828-005.wav out.wav
> [aist#0:0/pcm_s16le @ 00000252b1d2d420] Guessed Channel Layout: stereo
> Input #0, wav, from '../samples/wav/200828-005.wav':
>   Duration: 00:00:12.80, bitrate: 1536 kb/s
>   Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 2 channels, s16, 1536 kb/s
> Stream mapping:
>   Stream #0:0 -> #0:0 (pcm_s16le (native) -> pcm_s16le (native))
> Press [q] to stop, [?] for help
> Output #0, wav, to 'out.wav':
>   Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s16, 1536 kb/s
> 
> 
> $ ./ffmpeg -i out.wav
> [aist#0:0/pcm_s16le @ 000001d616b1d3e0] Guessed Channel Layout: stereo
>   Duration: 00:00:12.80, bitrate: 1536 kb/s
>   Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, 2 channels, s16, 1536 kb/s

After:

> $ ./ffmpeg -i ../samples/wav/200828-005.wav out.wav
> [aist#0:0/pcm_s16le @ 0000024603c9d420] Guessed Channel Layout: stereo
> Input #0, wav, from '../samples/wav/200828-005.wav':
>   Duration: 00:00:12.80, bitrate: 1536 kb/
>   Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s16, 1536 kb/s
> Stream mapping:
>   Stream #0:0 -> #0:0 (pcm_s16le (native) -> pcm_s16le (native))
> Press [q] to stop, [?] for help
> Output #0, wav, to 'out.wav':
>   Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s16, 1536 kb/s
> 
> $ ./ffmpeg -i out.wav
> [aist#0:0/pcm_s16le @ 000001a1467ed3e0] Guessed Channel Layout: stereo
>   Duration: 00:00:12.80, bitrate: 1536 kb/s
>   Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s16, 1536 kb/s

So the printed output shows the guessed layout for the input stream, but 
the written output stream is still unspec.
Anton Khirnov Jan. 16, 2024, 7:49 p.m. UTC | #3
Quoting James Almer (2024-01-06 15:22:10)
> This does not fix the issue of the guessed channel layout not being 
> present on the output stream,

Well, it wasn't supposed to fix anything. This patch exists as a
prerequisite for the next one.
James Almer Jan. 16, 2024, 10:37 p.m. UTC | #4
On 1/16/2024 4:49 PM, Anton Khirnov wrote:
> Quoting James Almer (2024-01-06 15:22:10)
>> This does not fix the issue of the guessed channel layout not being
>> present on the output stream,
> 
> Well, it wasn't supposed to fix anything. This patch exists as a
> prerequisite for the next one.

I know, hence the "but might be a change in the right direction." part 
followed by the changed output you removed from the quote :p
diff mbox series

Patch

diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index cacdc76a71..892094c512 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -899,19 +899,18 @@  static int choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream
     }
 }
 
-static int guess_input_channel_layout(InputStream *ist, int guess_layout_max)
+static int guess_input_channel_layout(InputStream *ist, AVCodecParameters *par,
+                                      int guess_layout_max)
 {
-    AVCodecContext *dec = ist->dec_ctx;
-
-    if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+    if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
         char layout_name[256];
 
-        if (dec->ch_layout.nb_channels > guess_layout_max)
+        if (par->ch_layout.nb_channels > guess_layout_max)
             return 0;
-        av_channel_layout_default(&dec->ch_layout, dec->ch_layout.nb_channels);
-        if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+        av_channel_layout_default(&par->ch_layout, par->ch_layout.nb_channels);
+        if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
             return 0;
-        av_channel_layout_describe(&dec->ch_layout, layout_name, sizeof(layout_name));
+        av_channel_layout_describe(&par->ch_layout, layout_name, sizeof(layout_name));
         av_log(ist, AV_LOG_WARNING, "Guessed Channel Layout: %s\n", layout_name);
     }
     return 1;
@@ -1145,16 +1144,6 @@  static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
         ist->user_set_discard = ist->st->discard;
     }
 
-    ist->dec_ctx = avcodec_alloc_context3(ist->dec);
-    if (!ist->dec_ctx)
-        return AVERROR(ENOMEM);
-
-    ret = avcodec_parameters_to_context(ist->dec_ctx, par);
-    if (ret < 0) {
-        av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n");
-        return ret;
-    }
-
     if (o->bitexact)
         av_dict_set(&ist->decoder_opts, "flags", "+bitexact", AV_DICT_MULTIKEY);
 
@@ -1181,7 +1170,7 @@  static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
     case AVMEDIA_TYPE_AUDIO: {
         int guess_layout_max = INT_MAX;
         MATCH_PER_STREAM_OPT(guess_layout_max, i, guess_layout_max, ic, st);
-        guess_input_channel_layout(ist, guess_layout_max);
+        guess_input_channel_layout(ist, par, guess_layout_max);
         break;
     }
     case AVMEDIA_TYPE_DATA:
@@ -1190,7 +1179,7 @@  static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
         MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
         MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
         if (canvas_size) {
-            ret = av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height,
+            ret = av_parse_video_size(&par->width, &par->height,
                                       canvas_size);
             if (ret < 0) {
                 av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
@@ -1201,8 +1190,8 @@  static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
         /* Compute the size of the canvas for the subtitles stream.
            If the subtitles codecpar has set a size, use it. Otherwise use the
            maximum dimensions of the video streams in the same file. */
-        ist->sub2video.w = ist->dec_ctx->width;
-        ist->sub2video.h = ist->dec_ctx->height;
+        ist->sub2video.w = par->width;
+        ist->sub2video.h = par->height;
         if (!(ist->sub2video.w && ist->sub2video.h)) {
             for (int j = 0; j < ic->nb_streams; j++) {
                 AVCodecParameters *par1 = ic->streams[j]->codecpar;
@@ -1226,6 +1215,16 @@  static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
     default: av_assert0(0);
     }
 
+    ist->dec_ctx = avcodec_alloc_context3(ist->dec);
+    if (!ist->dec_ctx)
+        return AVERROR(ENOMEM);
+
+    ret = avcodec_parameters_to_context(ist->dec_ctx, par);
+    if (ret < 0) {
+        av_log(ist, AV_LOG_ERROR, "Error initializing the decoder context.\n");
+        return ret;
+    }
+
     ist->par = avcodec_parameters_alloc();
     if (!ist->par)
         return AVERROR(ENOMEM);