fftools/ffmpeg_filter: take fallback parameters from decoder, not demuxer

When an input stream terminates and no frames were successfully decoded,
filtering code will currently configure the filtergraph using demuxer
stream parameters. Use decoder parameters instead, which should be more
reliable. Also, initialize them immediately when an input stream is
bound to a filtergraph input, so that these parameters are always
available (if at all) and filtering code does not need to reach into the
decoder at some arbitrary later point.
pull/389/head
Anton Khirnov 2 years ago
parent 48d8d3549a
commit c7c73a3250
  1. 18
      fftools/ffmpeg.c
  2. 8
      fftools/ffmpeg.h
  3. 7
      fftools/ffmpeg_demux.c
  4. 59
      fftools/ffmpeg_filter.c

@ -769,24 +769,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
first_report = 0; first_report = 0;
} }
int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par)
{
int ret;
// We never got any input. Set a fake format, which will
// come from libavformat.
ifilter->format = par->format;
ifilter->sample_rate = par->sample_rate;
ifilter->width = par->width;
ifilter->height = par->height;
ifilter->sample_aspect_ratio = par->sample_aspect_ratio;
ret = av_channel_layout_copy(&ifilter->ch_layout, &par->ch_layout);
if (ret < 0)
return ret;
return 0;
}
static void check_decode_result(InputStream *ist, int *got_output, int ret) static void check_decode_result(InputStream *ist, int *got_output, int ret)
{ {
if (*got_output || ret<0) if (*got_output || ret<0)

@ -788,7 +788,13 @@ void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub);
int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference); int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference);
int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb); int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb);
int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par); /**
* Set up fallback filtering parameters from a decoder context. They will only
* be used if no frames are ever sent on this input, otherwise the actual
* parameters are taken from the frame.
*/
int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec);
int ifilter_has_all_input_formats(FilterGraph *fg); int ifilter_has_all_input_formats(FilterGraph *fg);
/** /**

@ -586,10 +586,17 @@ void ist_output_add(InputStream *ist, OutputStream *ost)
void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple) void ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple)
{ {
int ret;
ist_use(ist, is_simple ? DECODING_FOR_OST : DECODING_FOR_FILTER); ist_use(ist, is_simple ? DECODING_FOR_OST : DECODING_FOR_FILTER);
GROW_ARRAY(ist->filters, ist->nb_filters); GROW_ARRAY(ist->filters, ist->nb_filters);
ist->filters[ist->nb_filters - 1] = ifilter; ist->filters[ist->nb_filters - 1] = ifilter;
// initialize fallback parameters for filtering
ret = ifilter_parameters_from_dec(ifilter, ist->dec_ctx);
if (ret < 0)
report_and_exit(ret);
} }
static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st, static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st,

@ -58,6 +58,19 @@ typedef struct InputFilterPriv {
AVRational time_base; AVRational time_base;
AVFifo *frame_queue; AVFifo *frame_queue;
// fallback parameters to use when no input is ever sent
struct {
int format;
int width;
int height;
AVRational sample_aspect_ratio;
int sample_rate;
AVChannelLayout ch_layout;
} fallback;
} InputFilterPriv; } InputFilterPriv;
static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter)
@ -225,6 +238,8 @@ static InputFilter *ifilter_alloc(FilterGraph *fg)
ifilter->graph = fg; ifilter->graph = fg;
ifilter->format = -1; ifilter->format = -1;
ifp->fallback.format = -1;
ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW);
if (!ifp->frame_queue) if (!ifp->frame_queue)
report_and_exit(AVERROR(ENOMEM)); report_and_exit(AVERROR(ENOMEM));
@ -260,6 +275,9 @@ void fg_free(FilterGraph **pfg)
avsubtitle_free(&sub); avsubtitle_free(&sub);
av_fifo_freep2(&ist->sub2video.sub_queue); av_fifo_freep2(&ist->sub2video.sub_queue);
} }
av_channel_layout_uninit(&ifp->fallback.ch_layout);
av_buffer_unref(&ifilter->hw_frames_ctx); av_buffer_unref(&ifilter->hw_frames_ctx);
av_freep(&ifilter->name); av_freep(&ifilter->name);
av_freep(&fg->inputs[j]); av_freep(&fg->inputs[j]);
@ -1361,6 +1379,29 @@ fail:
return ret; return ret;
} }
int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec)
{
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
if (dec->codec_type == AVMEDIA_TYPE_VIDEO) {
ifp->fallback.format = dec->pix_fmt;
ifp->fallback.width = dec->width;
ifp->fallback.height = dec->height;
ifp->fallback.sample_aspect_ratio = dec->sample_aspect_ratio;
} else {
int ret;
ifp->fallback.format = dec->sample_fmt;
ifp->fallback.sample_rate = dec->sample_rate;
ret = av_channel_layout_copy(&ifp->fallback.ch_layout, &dec->ch_layout);
if (ret < 0)
return ret;
}
return 0;
}
static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
{ {
AVFrameSideData *sd; AVFrameSideData *sd;
@ -1469,12 +1510,18 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb)
if (ret < 0) if (ret < 0)
return ret; return ret;
} else { } else {
// the filtergraph was never configured // the filtergraph was never configured, use the fallback parameters
if (ifilter->format < 0) { ifilter->format = ifp->fallback.format;
ret = ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par); ifilter->sample_rate = ifp->fallback.sample_rate;
if (ret < 0) ifilter->width = ifp->fallback.width;
return ret; ifilter->height = ifp->fallback.height;
} ifilter->sample_aspect_ratio = ifp->fallback.sample_aspect_ratio;
ret = av_channel_layout_copy(&ifilter->ch_layout,
&ifp->fallback.ch_layout);
if (ret < 0)
return ret;
if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) {
av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;

Loading…
Cancel
Save