Currently, calling configure_filtergraph() will pull in the input parameters from the corresponding decoder context. This has the following disadvantages: - the decoded frame is a more proper source for this information - a filter accessing decoder data breaks proper layering Add functions for explicitly sending the input stream parameters to a filtergraph input - currently from a frame and a decoder. The decoder one will be dropped in future commits after some more restructuring.tags/n3.3
| @@ -147,6 +147,7 @@ static void avconv_cleanup(int ret) | |||
| FilterGraph *fg = filtergraphs[i]; | |||
| avfilter_graph_free(&fg->graph); | |||
| for (j = 0; j < fg->nb_inputs; j++) { | |||
| av_buffer_unref(&fg->inputs[j]->hw_frames_ctx); | |||
| av_freep(&fg->inputs[j]->name); | |||
| av_freep(&fg->inputs[j]); | |||
| } | |||
| @@ -1252,6 +1253,16 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) | |||
| ist->resample_channel_layout = decoded_frame->channel_layout; | |||
| ist->resample_channels = avctx->channels; | |||
| for (i = 0; i < ist->nb_filters; i++) { | |||
| err = ifilter_parameters_from_frame(ist->filters[i], decoded_frame); | |||
| if (err < 0) { | |||
| av_log(NULL, AV_LOG_ERROR, | |||
| "Error reconfiguring input stream %d:%d filter %d\n", | |||
| ist->file_index, ist->st->index, i); | |||
| goto fail; | |||
| } | |||
| } | |||
| for (i = 0; i < nb_filtergraphs; i++) | |||
| if (ist_in_filtergraph(filtergraphs[i], ist) && | |||
| configure_filtergraph(filtergraphs[i]) < 0) { | |||
| @@ -1279,6 +1290,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) | |||
| break; | |||
| } | |||
| fail: | |||
| av_frame_unref(ist->filter_frame); | |||
| av_frame_unref(decoded_frame); | |||
| return err < 0 ? err : ret; | |||
| @@ -1336,6 +1348,16 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) | |||
| ist->resample_height = decoded_frame->height; | |||
| ist->resample_pix_fmt = decoded_frame->format; | |||
| for (i = 0; i < ist->nb_filters; i++) { | |||
| err = ifilter_parameters_from_frame(ist->filters[i], decoded_frame); | |||
| if (err < 0) { | |||
| av_log(NULL, AV_LOG_ERROR, | |||
| "Error reconfiguring input stream %d:%d filter %d\n", | |||
| ist->file_index, ist->st->index, i); | |||
| goto fail; | |||
| } | |||
| } | |||
| for (i = 0; i < nb_filtergraphs; i++) | |||
| if (ist_in_filtergraph(filtergraphs[i], ist) && | |||
| configure_filtergraph(filtergraphs[i]) < 0) { | |||
| @@ -2061,6 +2083,14 @@ static int transcode_init(void) | |||
| enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) && | |||
| filtergraph_is_simple(ost->filter->graph)) { | |||
| FilterGraph *fg = ost->filter->graph; | |||
| ret = ifilter_parameters_from_decoder(fg->inputs[0], | |||
| dec_ctx); | |||
| if (ret < 0) { | |||
| av_log(NULL, AV_LOG_FATAL, "Error initializing filter input\n"); | |||
| exit_program(1); | |||
| } | |||
| if (configure_filtergraph(fg)) { | |||
| av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n"); | |||
| exit_program(1); | |||
| @@ -199,6 +199,17 @@ typedef struct InputFilter { | |||
| struct InputStream *ist; | |||
| struct FilterGraph *graph; | |||
| uint8_t *name; | |||
| // parameters configured for this input | |||
| int format; | |||
| int width, height; | |||
| AVRational sample_aspect_ratio; | |||
| int sample_rate; | |||
| uint64_t channel_layout; | |||
| AVBufferRef *hw_frames_ctx; | |||
| } InputFilter; | |||
| typedef struct OutputFilter { | |||
| @@ -468,6 +479,9 @@ int filtergraph_is_simple(FilterGraph *fg); | |||
| int init_simple_filtergraph(InputStream *ist, OutputStream *ost); | |||
| int init_complex_filtergraph(FilterGraph *fg); | |||
| int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); | |||
| int ifilter_parameters_from_decoder(InputFilter *ifilter, const AVCodecContext *avctx); | |||
| int avconv_parse_options(int argc, char **argv); | |||
| int vdpau_init(AVCodecContext *s); | |||
| @@ -97,6 +97,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) | |||
| exit(1); | |||
| fg->inputs[0]->ist = ist; | |||
| fg->inputs[0]->graph = fg; | |||
| fg->inputs[0]->format = -1; | |||
| GROW_ARRAY(ist->filters, ist->nb_filters); | |||
| ist->filters[ist->nb_filters - 1] = fg->inputs[0]; | |||
| @@ -172,6 +173,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) | |||
| exit(1); | |||
| fg->inputs[fg->nb_inputs - 1]->ist = ist; | |||
| fg->inputs[fg->nb_inputs - 1]->graph = fg; | |||
| fg->inputs[fg->nb_inputs - 1]->format = -1; | |||
| GROW_ARRAY(ist->filters, ist->nb_filters); | |||
| ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1]; | |||
| @@ -505,15 +507,12 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, | |||
| if (!par) | |||
| return AVERROR(ENOMEM); | |||
| par->sample_aspect_ratio = ist->st->sample_aspect_ratio.num ? | |||
| ist->st->sample_aspect_ratio : | |||
| ist->dec_ctx->sample_aspect_ratio; | |||
| par->width = ist->dec_ctx->width; | |||
| par->height = ist->dec_ctx->height; | |||
| par->format = ist->hwaccel_retrieve_data ? | |||
| ist->hwaccel_retrieved_pix_fmt : ist->dec_ctx->pix_fmt; | |||
| par->sample_aspect_ratio = ifilter->sample_aspect_ratio; | |||
| par->width = ifilter->width; | |||
| par->height = ifilter->height; | |||
| par->format = ifilter->format; | |||
| par->time_base = tb; | |||
| par->hw_frames_ctx = ist->hw_frames_ctx; | |||
| par->hw_frames_ctx = ifilter->hw_frames_ctx; | |||
| ret = av_buffersrc_parameters_set(ifilter->filter, par); | |||
| av_freep(&par); | |||
| @@ -597,10 +596,10 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, | |||
| if (!par) | |||
| return AVERROR(ENOMEM); | |||
| par->time_base = (AVRational){ 1, ist->dec_ctx->sample_rate }; | |||
| par->sample_rate = ist->dec_ctx->sample_rate; | |||
| par->format = ist->dec_ctx->sample_fmt; | |||
| par->channel_layout = ist->dec_ctx->channel_layout; | |||
| par->time_base = (AVRational){ 1, ifilter->sample_rate }; | |||
| par->sample_rate = ifilter->sample_rate; | |||
| par->format = ifilter->format; | |||
| par->channel_layout = ifilter->channel_layout; | |||
| ret = av_buffersrc_parameters_set(ifilter->filter, par); | |||
| av_freep(&par); | |||
| @@ -751,6 +750,53 @@ int configure_filtergraph(FilterGraph *fg) | |||
| return 0; | |||
| } | |||
| int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) | |||
| { | |||
| av_buffer_unref(&ifilter->hw_frames_ctx); | |||
| ifilter->format = frame->format; | |||
| ifilter->width = frame->width; | |||
| ifilter->height = frame->height; | |||
| ifilter->sample_aspect_ratio = frame->sample_aspect_ratio; | |||
| ifilter->sample_rate = frame->sample_rate; | |||
| ifilter->channel_layout = frame->channel_layout; | |||
| if (frame->hw_frames_ctx) { | |||
| ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx); | |||
| if (!ifilter->hw_frames_ctx) | |||
| return AVERROR(ENOMEM); | |||
| } | |||
| return 0; | |||
| } | |||
| int ifilter_parameters_from_decoder(InputFilter *ifilter, const AVCodecContext *avctx) | |||
| { | |||
| av_buffer_unref(&ifilter->hw_frames_ctx); | |||
| if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) | |||
| ifilter->format = avctx->pix_fmt; | |||
| else | |||
| ifilter->format = avctx->sample_fmt; | |||
| ifilter->width = avctx->width; | |||
| ifilter->height = avctx->height; | |||
| ifilter->sample_aspect_ratio = avctx->sample_aspect_ratio; | |||
| ifilter->sample_rate = avctx->sample_rate; | |||
| ifilter->channel_layout = avctx->channel_layout; | |||
| if (avctx->hw_frames_ctx) { | |||
| ifilter->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx); | |||
| if (!ifilter->hw_frames_ctx) | |||
| return AVERROR(ENOMEM); | |||
| } | |||
| return 0; | |||
| } | |||
| int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) | |||
| { | |||
| int i; | |||
| @@ -1498,12 +1498,28 @@ static int init_complex_filters(void) | |||
| static int configure_complex_filters(void) | |||
| { | |||
| int i, ret = 0; | |||
| int i, j, ret = 0; | |||
| for (i = 0; i < nb_filtergraphs; i++) { | |||
| FilterGraph *fg = filtergraphs[i]; | |||
| if (filtergraph_is_simple(fg)) | |||
| continue; | |||
| for (i = 0; i < nb_filtergraphs; i++) | |||
| if (!filtergraph_is_simple(filtergraphs[i]) && | |||
| (ret = configure_filtergraph(filtergraphs[i])) < 0) | |||
| for (j = 0; j < fg->nb_inputs; j++) { | |||
| ret = ifilter_parameters_from_decoder(fg->inputs[j], | |||
| fg->inputs[j]->ist->dec_ctx); | |||
| if (ret < 0) { | |||
| av_log(NULL, AV_LOG_ERROR, | |||
| "Error initializing filtergraph %d input %d\n", i, j); | |||
| return ret; | |||
| } | |||
| } | |||
| ret = configure_filtergraph(filtergraphs[i]); | |||
| if (ret < 0) | |||
| return ret; | |||
| } | |||
| return 0; | |||
| } | |||