diff mbox series

[FFmpeg-devel] ffmpeg: add option recast_media

Message ID 20210702100305.1692-1-ffmpeg@gyani.pro
State Accepted
Headers show
Series [FFmpeg-devel] ffmpeg: add option recast_media
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Gyan Doshi July 2, 2021, 10:03 a.m. UTC
Allows forcing decoders of different media type.
Needed to decode media data muxed as data streams.
---
 doc/ffmpeg.texi      | 5 +++++
 fftools/ffmpeg_opt.c | 7 ++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

Comments

Gyan Doshi July 8, 2021, 3:57 a.m. UTC | #1
Plan to push in a couple of days.

On 2021-07-02 15:33, Gyan Doshi wrote:
> Allows forcing decoders of different media type.
> Needed to decode media data muxed as data streams.
> ---
>   doc/ffmpeg.texi      | 5 +++++
>   fftools/ffmpeg_opt.c | 7 ++++++-
>   2 files changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
> index 7827291755..c1065086e5 100644
> --- a/doc/ffmpeg.texi
> +++ b/doc/ffmpeg.texi
> @@ -449,6 +449,11 @@ output file already exists.
>   Set number of times input stream shall be looped. Loop 0 means no loop,
>   loop -1 means infinite loop.
>   
> +@item -recast_media (@emph{global})
> +Enable to allow forcing a decoder of a different media type than
> +the one detected or designated by the demuxer. Useful for decoding
> +media data muxed as data streams.
> +
>   @item -c[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
>   @itemx -codec[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
>   Select an encoder (when used before an output file) or a decoder (when used
> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
> index a63bed54cf..76a220c21c 100644
> --- a/fftools/ffmpeg_opt.c
> +++ b/fftools/ffmpeg_opt.c
> @@ -186,6 +186,7 @@ static int input_sync;
>   static int input_stream_potentially_available = 0;
>   static int ignore_unknown_streams = 0;
>   static int copy_unknown_streams = 0;
> +static int recast_media = 0;
>   static int find_stream_info = 1;
>   
>   static void uninit_options(OptionsContext *o)
> @@ -759,7 +760,7 @@ static const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type,
>           av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name);
>           exit_program(1);
>       }
> -    if (codec->type != type) {
> +    if (codec->type != type && !recast_media) {
>           av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);
>           exit_program(1);
>       }
> @@ -774,6 +775,8 @@ static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVSt
>       if (codec_name) {
>           const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
>           st->codecpar->codec_id = codec->id;
> +        if (recast_media && st->codecpar->codec_type != codec->type)
> +            st->codecpar->codec_type = codec->type;
>           return codec;
>       } else
>           return avcodec_find_decoder(st->codecpar->codec_id);
> @@ -3429,6 +3432,8 @@ const OptionDef options[] = {
>           "Ignore unknown stream types" },
>       { "copy_unknown",   OPT_BOOL | OPT_EXPERT,                       {              &copy_unknown_streams },
>           "Copy unknown stream types" },
> +    { "recast_media",   OPT_BOOL | OPT_EXPERT,                       {              &recast_media },
> +        "recast stream type in order to force a decoder of different media type" },
>       { "c",              HAS_ARG | OPT_STRING | OPT_SPEC |
>                           OPT_INPUT | OPT_OUTPUT,                      { .off       = OFFSET(codec_names) },
>           "codec name", "codec" },
Gyan Doshi July 11, 2021, 6:25 a.m. UTC | #2
Pushed as 79ebdbb9b9da0a86b277e3f85981196c781af398

On 2021-07-08 09:27, Gyan Doshi wrote:
> Plan to push in a couple of days.
>
> On 2021-07-02 15:33, Gyan Doshi wrote:
>> Allows forcing decoders of different media type.
>> Needed to decode media data muxed as data streams.
>> ---
>>   doc/ffmpeg.texi      | 5 +++++
>>   fftools/ffmpeg_opt.c | 7 ++++++-
>>   2 files changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
>> index 7827291755..c1065086e5 100644
>> --- a/doc/ffmpeg.texi
>> +++ b/doc/ffmpeg.texi
>> @@ -449,6 +449,11 @@ output file already exists.
>>   Set number of times input stream shall be looped. Loop 0 means no 
>> loop,
>>   loop -1 means infinite loop.
>>   +@item -recast_media (@emph{global})
>> +Enable to allow forcing a decoder of a different media type than
>> +the one detected or designated by the demuxer. Useful for decoding
>> +media data muxed as data streams.
>> +
>>   @item -c[:@var{stream_specifier}] @var{codec} 
>> (@emph{input/output,per-stream})
>>   @itemx -codec[:@var{stream_specifier}] @var{codec} 
>> (@emph{input/output,per-stream})
>>   Select an encoder (when used before an output file) or a decoder 
>> (when used
>> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
>> index a63bed54cf..76a220c21c 100644
>> --- a/fftools/ffmpeg_opt.c
>> +++ b/fftools/ffmpeg_opt.c
>> @@ -186,6 +186,7 @@ static int input_sync;
>>   static int input_stream_potentially_available = 0;
>>   static int ignore_unknown_streams = 0;
>>   static int copy_unknown_streams = 0;
>> +static int recast_media = 0;
>>   static int find_stream_info = 1;
>>     static void uninit_options(OptionsContext *o)
>> @@ -759,7 +760,7 @@ static const AVCodec *find_codec_or_die(const 
>> char *name, enum AVMediaType type,
>>           av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", 
>> codec_string, name);
>>           exit_program(1);
>>       }
>> -    if (codec->type != type) {
>> +    if (codec->type != type && !recast_media) {
>>           av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", 
>> codec_string, name);
>>           exit_program(1);
>>       }
>> @@ -774,6 +775,8 @@ static const AVCodec 
>> *choose_decoder(OptionsContext *o, AVFormatContext *s, AVSt
>>       if (codec_name) {
>>           const AVCodec *codec = find_codec_or_die(codec_name, 
>> st->codecpar->codec_type, 0);
>>           st->codecpar->codec_id = codec->id;
>> +        if (recast_media && st->codecpar->codec_type != codec->type)
>> +            st->codecpar->codec_type = codec->type;
>>           return codec;
>>       } else
>>           return avcodec_find_decoder(st->codecpar->codec_id);
>> @@ -3429,6 +3432,8 @@ const OptionDef options[] = {
>>           "Ignore unknown stream types" },
>>       { "copy_unknown",   OPT_BOOL | 
>> OPT_EXPERT,                       { &copy_unknown_streams },
>>           "Copy unknown stream types" },
>> +    { "recast_media",   OPT_BOOL | OPT_EXPERT,                       
>> { &recast_media },
>> +        "recast stream type in order to force a decoder of different 
>> media type" },
>>       { "c",              HAS_ARG | OPT_STRING | OPT_SPEC |
>>                           OPT_INPUT | 
>> OPT_OUTPUT,                      { .off       = OFFSET(codec_names) },
>>           "codec name", "codec" },
>
> _______________________________________________
> 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".
Anton Khirnov July 13, 2021, 7:44 a.m. UTC | #3
Quoting Gyan Doshi (2021-07-02 12:03:05)
> Allows forcing decoders of different media type.
> Needed to decode media data muxed as data streams.
> ---
>  doc/ffmpeg.texi      | 5 +++++
>  fftools/ffmpeg_opt.c | 7 ++++++-
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
> index 7827291755..c1065086e5 100644
> --- a/doc/ffmpeg.texi
> +++ b/doc/ffmpeg.texi
> @@ -449,6 +449,11 @@ output file already exists.
>  Set number of times input stream shall be looped. Loop 0 means no loop,
>  loop -1 means infinite loop.
>  
> +@item -recast_media (@emph{global})
> +Enable to allow forcing a decoder of a different media type than
> +the one detected or designated by the demuxer. Useful for decoding
> +media data muxed as data streams.
> +
>  @item -c[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
>  @itemx -codec[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
>  Select an encoder (when used before an output file) or a decoder (when used
> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
> index a63bed54cf..76a220c21c 100644
> --- a/fftools/ffmpeg_opt.c
> +++ b/fftools/ffmpeg_opt.c
> @@ -186,6 +186,7 @@ static int input_sync;
>  static int input_stream_potentially_available = 0;
>  static int ignore_unknown_streams = 0;
>  static int copy_unknown_streams = 0;
> +static int recast_media = 0;
>  static int find_stream_info = 1;
>  
>  static void uninit_options(OptionsContext *o)
> @@ -759,7 +760,7 @@ static const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type,
>          av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name);
>          exit_program(1);
>      }
> -    if (codec->type != type) {
> +    if (codec->type != type && !recast_media) {
>          av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);
>          exit_program(1);
>      }
> @@ -774,6 +775,8 @@ static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVSt
>      if (codec_name) {
>          const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
>          st->codecpar->codec_id = codec->id;
> +        if (recast_media && st->codecpar->codec_type != codec->type)
> +            st->codecpar->codec_type = codec->type;

The caller is not allowed to modify this struct for demuxing. This might
confuse demuxers that expect the values they put there to remain
Gyan Doshi July 13, 2021, 9:12 a.m. UTC | #4
On 2021-07-13 13:14, Anton Khirnov wrote:
> Quoting Gyan Doshi (2021-07-02 12:03:05)
>> Allows forcing decoders of different media type.
>> Needed to decode media data muxed as data streams.
>> ---
>>   doc/ffmpeg.texi      | 5 +++++
>>   fftools/ffmpeg_opt.c | 7 ++++++-
>>   2 files changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
>> index 7827291755..c1065086e5 100644
>> --- a/doc/ffmpeg.texi
>> +++ b/doc/ffmpeg.texi
>> @@ -449,6 +449,11 @@ output file already exists.
>>   Set number of times input stream shall be looped. Loop 0 means no loop,
>>   loop -1 means infinite loop.
>>   
>> +@item -recast_media (@emph{global})
>> +Enable to allow forcing a decoder of a different media type than
>> +the one detected or designated by the demuxer. Useful for decoding
>> +media data muxed as data streams.
>> +
>>   @item -c[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
>>   @itemx -codec[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
>>   Select an encoder (when used before an output file) or a decoder (when used
>> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
>> index a63bed54cf..76a220c21c 100644
>> --- a/fftools/ffmpeg_opt.c
>> +++ b/fftools/ffmpeg_opt.c
>> @@ -186,6 +186,7 @@ static int input_sync;
>>   static int input_stream_potentially_available = 0;
>>   static int ignore_unknown_streams = 0;
>>   static int copy_unknown_streams = 0;
>> +static int recast_media = 0;
>>   static int find_stream_info = 1;
>>   
>>   static void uninit_options(OptionsContext *o)
>> @@ -759,7 +760,7 @@ static const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type,
>>           av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name);
>>           exit_program(1);
>>       }
>> -    if (codec->type != type) {
>> +    if (codec->type != type && !recast_media) {
>>           av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);
>>           exit_program(1);
>>       }
>> @@ -774,6 +775,8 @@ static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVSt
>>       if (codec_name) {
>>           const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
>>           st->codecpar->codec_id = codec->id;
>> +        if (recast_media && st->codecpar->codec_type != codec->type)
>> +            st->codecpar->codec_type = codec->type;
> The caller is not allowed to modify this struct for demuxing. This might
> confuse demuxers that expect the values they put there to remain

choose_decoder() is called from within add_input_streams().

Near the end of this parent function, we have

     ret = avcodec_parameters_from_context(par, ist->dec_ctx);

where par is

     AVCodecParameters *par = st->codecpar;


avcodec_parameters_from_context(), starts with
{
     codec_parameters_reset(par);   -->  sets codec_type to 
AVMEDIA_TYPE_UNKNOWN

     par->codec_type = codec->codec_type;
     ...
}

So it's already being done. I did an immediate recast to avoid some 
temporary variables as the media type is used in a few switch blocks 
after the decoder is set.
But that way also works for me, if you insist.

Regards,
Gyan




>
Anton Khirnov July 13, 2021, 4:25 p.m. UTC | #5
Quoting Gyan Doshi (2021-07-13 11:12:19)
> 
> 
> On 2021-07-13 13:14, Anton Khirnov wrote:
> > Quoting Gyan Doshi (2021-07-02 12:03:05)
> >> Allows forcing decoders of different media type.
> >> Needed to decode media data muxed as data streams.
> >> ---
> >>   doc/ffmpeg.texi      | 5 +++++
> >>   fftools/ffmpeg_opt.c | 7 ++++++-
> >>   2 files changed, 11 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
> >> index 7827291755..c1065086e5 100644
> >> --- a/doc/ffmpeg.texi
> >> +++ b/doc/ffmpeg.texi
> >> @@ -449,6 +449,11 @@ output file already exists.
> >>   Set number of times input stream shall be looped. Loop 0 means no loop,
> >>   loop -1 means infinite loop.
> >>   
> >> +@item -recast_media (@emph{global})
> >> +Enable to allow forcing a decoder of a different media type than
> >> +the one detected or designated by the demuxer. Useful for decoding
> >> +media data muxed as data streams.
> >> +
> >>   @item -c[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
> >>   @itemx -codec[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
> >>   Select an encoder (when used before an output file) or a decoder (when used
> >> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
> >> index a63bed54cf..76a220c21c 100644
> >> --- a/fftools/ffmpeg_opt.c
> >> +++ b/fftools/ffmpeg_opt.c
> >> @@ -186,6 +186,7 @@ static int input_sync;
> >>   static int input_stream_potentially_available = 0;
> >>   static int ignore_unknown_streams = 0;
> >>   static int copy_unknown_streams = 0;
> >> +static int recast_media = 0;
> >>   static int find_stream_info = 1;
> >>   
> >>   static void uninit_options(OptionsContext *o)
> >> @@ -759,7 +760,7 @@ static const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type,
> >>           av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name);
> >>           exit_program(1);
> >>       }
> >> -    if (codec->type != type) {
> >> +    if (codec->type != type && !recast_media) {
> >>           av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);
> >>           exit_program(1);
> >>       }
> >> @@ -774,6 +775,8 @@ static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVSt
> >>       if (codec_name) {
> >>           const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
> >>           st->codecpar->codec_id = codec->id;
> >> +        if (recast_media && st->codecpar->codec_type != codec->type)
> >> +            st->codecpar->codec_type = codec->type;
> > The caller is not allowed to modify this struct for demuxing. This might
> > confuse demuxers that expect the values they put there to remain
> 
> choose_decoder() is called from within add_input_streams().
> 
> Near the end of this parent function, we have
> 
>      ret = avcodec_parameters_from_context(par, ist->dec_ctx);
> 
> where par is
> 
>      AVCodecParameters *par = st->codecpar;
> 
> 
> avcodec_parameters_from_context(), starts with
> {
>      codec_parameters_reset(par);   -->  sets codec_type to 
> AVMEDIA_TYPE_UNKNOWN
> 
>      par->codec_type = codec->codec_type;
>      ...
> }
> 
> So it's already being done. I did an immediate recast to avoid some 
> temporary variables as the media type is used in a few switch blocks 
> after the decoder is set.
> But that way also works for me, if you insist.

Okay, I still consider this API abuse, but since it was there before it
is not your responsibility to fix it. Guess I'll add it to my todo list.
James Almer July 13, 2021, 7:05 p.m. UTC | #6
On 7/13/2021 6:12 AM, Gyan Doshi wrote:
> 
> 
> On 2021-07-13 13:14, Anton Khirnov wrote:
>> Quoting Gyan Doshi (2021-07-02 12:03:05)
>>> Allows forcing decoders of different media type.
>>> Needed to decode media data muxed as data streams.
>>> ---
>>>   doc/ffmpeg.texi      | 5 +++++
>>>   fftools/ffmpeg_opt.c | 7 ++++++-
>>>   2 files changed, 11 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
>>> index 7827291755..c1065086e5 100644
>>> --- a/doc/ffmpeg.texi
>>> +++ b/doc/ffmpeg.texi
>>> @@ -449,6 +449,11 @@ output file already exists.
>>>   Set number of times input stream shall be looped. Loop 0 means no 
>>> loop,
>>>   loop -1 means infinite loop.
>>> +@item -recast_media (@emph{global})
>>> +Enable to allow forcing a decoder of a different media type than
>>> +the one detected or designated by the demuxer. Useful for decoding
>>> +media data muxed as data streams.
>>> +
>>>   @item -c[:@var{stream_specifier}] @var{codec} 
>>> (@emph{input/output,per-stream})
>>>   @itemx -codec[:@var{stream_specifier}] @var{codec} 
>>> (@emph{input/output,per-stream})
>>>   Select an encoder (when used before an output file) or a decoder 
>>> (when used
>>> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
>>> index a63bed54cf..76a220c21c 100644
>>> --- a/fftools/ffmpeg_opt.c
>>> +++ b/fftools/ffmpeg_opt.c
>>> @@ -186,6 +186,7 @@ static int input_sync;
>>>   static int input_stream_potentially_available = 0;
>>>   static int ignore_unknown_streams = 0;
>>>   static int copy_unknown_streams = 0;
>>> +static int recast_media = 0;
>>>   static int find_stream_info = 1;
>>>   static void uninit_options(OptionsContext *o)
>>> @@ -759,7 +760,7 @@ static const AVCodec *find_codec_or_die(const 
>>> char *name, enum AVMediaType type,
>>>           av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", 
>>> codec_string, name);
>>>           exit_program(1);
>>>       }
>>> -    if (codec->type != type) {
>>> +    if (codec->type != type && !recast_media) {
>>>           av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", 
>>> codec_string, name);
>>>           exit_program(1);
>>>       }
>>> @@ -774,6 +775,8 @@ static const AVCodec 
>>> *choose_decoder(OptionsContext *o, AVFormatContext *s, AVSt
>>>       if (codec_name) {
>>>           const AVCodec *codec = find_codec_or_die(codec_name, 
>>> st->codecpar->codec_type, 0);
>>>           st->codecpar->codec_id = codec->id;
>>> +        if (recast_media && st->codecpar->codec_type != codec->type)
>>> +            st->codecpar->codec_type = codec->type;
>> The caller is not allowed to modify this struct for demuxing. This might
>> confuse demuxers that expect the values they put there to remain
> 
> choose_decoder() is called from within add_input_streams().
> 
> Near the end of this parent function, we have
> 
>      ret = avcodec_parameters_from_context(par, ist->dec_ctx);
> 
> where par is
> 
>      AVCodecParameters *par = st->codecpar;
> 
> 
> avcodec_parameters_from_context(), starts with
> {
>      codec_parameters_reset(par);   -->  sets codec_type to 
> AVMEDIA_TYPE_UNKNOWN
> 
>      par->codec_type = codec->codec_type;
>      ...
> }

ist->dec_ctx is initialized as a copy of par, and its codec_type is 
never changed.
In fact, for video, copying back to par doesn't seem needed to begin 
with. And it could be looked how to remove it for audio and subtitles, 
where channel_layout and dimensions respectively may be changed.

> 
> So it's already being done. I did an immediate recast to avoid some 
> temporary variables as the media type is used in a few switch blocks 
> after the decoder is set.
> But that way also works for me, if you insist.
> 
> Regards,
> Gyan
> 
> 
> 
> 
>>
> 
> _______________________________________________
> 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".
Gyan Doshi July 14, 2021, 9:05 a.m. UTC | #7
On 2021-07-14 00:35, James Almer wrote:
> On 7/13/2021 6:12 AM, Gyan Doshi wrote:
>>
>>
>> On 2021-07-13 13:14, Anton Khirnov wrote:
>>> Quoting Gyan Doshi (2021-07-02 12:03:05)
>>>> Allows forcing decoders of different media type.
>>>> Needed to decode media data muxed as data streams.
>>>> ---
>>>>   doc/ffmpeg.texi      | 5 +++++
>>>>   fftools/ffmpeg_opt.c | 7 ++++++-
>>>>   2 files changed, 11 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
>>>> index 7827291755..c1065086e5 100644
>>>> --- a/doc/ffmpeg.texi
>>>> +++ b/doc/ffmpeg.texi
>>>> @@ -449,6 +449,11 @@ output file already exists.
>>>>   Set number of times input stream shall be looped. Loop 0 means no 
>>>> loop,
>>>>   loop -1 means infinite loop.
>>>> +@item -recast_media (@emph{global})
>>>> +Enable to allow forcing a decoder of a different media type than
>>>> +the one detected or designated by the demuxer. Useful for decoding
>>>> +media data muxed as data streams.
>>>> +
>>>>   @item -c[:@var{stream_specifier}] @var{codec} 
>>>> (@emph{input/output,per-stream})
>>>>   @itemx -codec[:@var{stream_specifier}] @var{codec} 
>>>> (@emph{input/output,per-stream})
>>>>   Select an encoder (when used before an output file) or a decoder 
>>>> (when used
>>>> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
>>>> index a63bed54cf..76a220c21c 100644
>>>> --- a/fftools/ffmpeg_opt.c
>>>> +++ b/fftools/ffmpeg_opt.c
>>>> @@ -186,6 +186,7 @@ static int input_sync;
>>>>   static int input_stream_potentially_available = 0;
>>>>   static int ignore_unknown_streams = 0;
>>>>   static int copy_unknown_streams = 0;
>>>> +static int recast_media = 0;
>>>>   static int find_stream_info = 1;
>>>>   static void uninit_options(OptionsContext *o)
>>>> @@ -759,7 +760,7 @@ static const AVCodec *find_codec_or_die(const 
>>>> char *name, enum AVMediaType type,
>>>>           av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", 
>>>> codec_string, name);
>>>>           exit_program(1);
>>>>       }
>>>> -    if (codec->type != type) {
>>>> +    if (codec->type != type && !recast_media) {
>>>>           av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", 
>>>> codec_string, name);
>>>>           exit_program(1);
>>>>       }
>>>> @@ -774,6 +775,8 @@ static const AVCodec 
>>>> *choose_decoder(OptionsContext *o, AVFormatContext *s, AVSt
>>>>       if (codec_name) {
>>>>           const AVCodec *codec = find_codec_or_die(codec_name, 
>>>> st->codecpar->codec_type, 0);
>>>>           st->codecpar->codec_id = codec->id;
>>>> +        if (recast_media && st->codecpar->codec_type != codec->type)
>>>> +            st->codecpar->codec_type = codec->type;
>>> The caller is not allowed to modify this struct for demuxing. This 
>>> might
>>> confuse demuxers that expect the values they put there to remain
>>
>> choose_decoder() is called from within add_input_streams().
>>
>> Near the end of this parent function, we have
>>
>>      ret = avcodec_parameters_from_context(par, ist->dec_ctx);
>>
>> where par is
>>
>>      AVCodecParameters *par = st->codecpar;
>>
>>
>> avcodec_parameters_from_context(), starts with
>> {
>>      codec_parameters_reset(par);   -->  sets codec_type to 
>> AVMEDIA_TYPE_UNKNOWN
>>
>>      par->codec_type = codec->codec_type;
>>      ...
>> }
>
> ist->dec_ctx is initialized as a copy of par, and its codec_type is 
> never changed.
> In fact, for video, copying back to par doesn't seem needed to begin 
> with. And it could be looked how to remove it for audio and subtitles, 
> where channel_layout and dimensions respectively may be changed.

Well, the underlying point is that the info available to the demuxer may 
be wrong and/or incomplete.

Whatever sanitary correction is made here,  fftools should be free to 
apply automatic or user-requested adjustment for onward processing. 
Unless it's easier to make allowances inside lavf.

Regards,
Gyan
diff mbox series

Patch

diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 7827291755..c1065086e5 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -449,6 +449,11 @@  output file already exists.
 Set number of times input stream shall be looped. Loop 0 means no loop,
 loop -1 means infinite loop.
 
+@item -recast_media (@emph{global})
+Enable to allow forcing a decoder of a different media type than
+the one detected or designated by the demuxer. Useful for decoding
+media data muxed as data streams.
+
 @item -c[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
 @itemx -codec[:@var{stream_specifier}] @var{codec} (@emph{input/output,per-stream})
 Select an encoder (when used before an output file) or a decoder (when used
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index a63bed54cf..76a220c21c 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -186,6 +186,7 @@  static int input_sync;
 static int input_stream_potentially_available = 0;
 static int ignore_unknown_streams = 0;
 static int copy_unknown_streams = 0;
+static int recast_media = 0;
 static int find_stream_info = 1;
 
 static void uninit_options(OptionsContext *o)
@@ -759,7 +760,7 @@  static const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type,
         av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name);
         exit_program(1);
     }
-    if (codec->type != type) {
+    if (codec->type != type && !recast_media) {
         av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);
         exit_program(1);
     }
@@ -774,6 +775,8 @@  static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVSt
     if (codec_name) {
         const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
         st->codecpar->codec_id = codec->id;
+        if (recast_media && st->codecpar->codec_type != codec->type)
+            st->codecpar->codec_type = codec->type;
         return codec;
     } else
         return avcodec_find_decoder(st->codecpar->codec_id);
@@ -3429,6 +3432,8 @@  const OptionDef options[] = {
         "Ignore unknown stream types" },
     { "copy_unknown",   OPT_BOOL | OPT_EXPERT,                       {              &copy_unknown_streams },
         "Copy unknown stream types" },
+    { "recast_media",   OPT_BOOL | OPT_EXPERT,                       {              &recast_media },
+        "recast stream type in order to force a decoder of different media type" },
     { "c",              HAS_ARG | OPT_STRING | OPT_SPEC |
                         OPT_INPUT | OPT_OUTPUT,                      { .off       = OFFSET(codec_names) },
         "codec name", "codec" },