avconv: decouple configuring filtergraphs and setting input parameters
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.
This commit is contained in:
		
							parent
							
								
									398f015f07
								
							
						
					
					
						commit
						722ec3eb35
					
				
							
								
								
									
										30
									
								
								avconv.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								avconv.c
									
									
									
									
									
								
							@ -147,6 +147,7 @@ static void avconv_cleanup(int ret)
 | 
				
			|||||||
        FilterGraph *fg = filtergraphs[i];
 | 
					        FilterGraph *fg = filtergraphs[i];
 | 
				
			||||||
        avfilter_graph_free(&fg->graph);
 | 
					        avfilter_graph_free(&fg->graph);
 | 
				
			||||||
        for (j = 0; j < fg->nb_inputs; j++) {
 | 
					        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]->name);
 | 
				
			||||||
            av_freep(&fg->inputs[j]);
 | 
					            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_channel_layout = decoded_frame->channel_layout;
 | 
				
			||||||
        ist->resample_channels       = avctx->channels;
 | 
					        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++)
 | 
					        for (i = 0; i < nb_filtergraphs; i++)
 | 
				
			||||||
            if (ist_in_filtergraph(filtergraphs[i], ist) &&
 | 
					            if (ist_in_filtergraph(filtergraphs[i], ist) &&
 | 
				
			||||||
                configure_filtergraph(filtergraphs[i]) < 0) {
 | 
					                configure_filtergraph(filtergraphs[i]) < 0) {
 | 
				
			||||||
@ -1279,6 +1290,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fail:
 | 
				
			||||||
    av_frame_unref(ist->filter_frame);
 | 
					    av_frame_unref(ist->filter_frame);
 | 
				
			||||||
    av_frame_unref(decoded_frame);
 | 
					    av_frame_unref(decoded_frame);
 | 
				
			||||||
    return err < 0 ? err : ret;
 | 
					    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_height  = decoded_frame->height;
 | 
				
			||||||
        ist->resample_pix_fmt = decoded_frame->format;
 | 
					        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++)
 | 
					        for (i = 0; i < nb_filtergraphs; i++)
 | 
				
			||||||
            if (ist_in_filtergraph(filtergraphs[i], ist) &&
 | 
					            if (ist_in_filtergraph(filtergraphs[i], ist) &&
 | 
				
			||||||
                configure_filtergraph(filtergraphs[i]) < 0) {
 | 
					                configure_filtergraph(filtergraphs[i]) < 0) {
 | 
				
			||||||
@ -2061,6 +2083,14 @@ static int transcode_init(void)
 | 
				
			|||||||
                 enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
 | 
					                 enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
 | 
				
			||||||
                 filtergraph_is_simple(ost->filter->graph)) {
 | 
					                 filtergraph_is_simple(ost->filter->graph)) {
 | 
				
			||||||
                    FilterGraph *fg = 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)) {
 | 
					                    if (configure_filtergraph(fg)) {
 | 
				
			||||||
                        av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
 | 
					                        av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
 | 
				
			||||||
                        exit_program(1);
 | 
					                        exit_program(1);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								avconv.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								avconv.h
									
									
									
									
									
								
							@ -199,6 +199,17 @@ typedef struct InputFilter {
 | 
				
			|||||||
    struct InputStream *ist;
 | 
					    struct InputStream *ist;
 | 
				
			||||||
    struct FilterGraph *graph;
 | 
					    struct FilterGraph *graph;
 | 
				
			||||||
    uint8_t            *name;
 | 
					    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;
 | 
					} InputFilter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct OutputFilter {
 | 
					typedef struct OutputFilter {
 | 
				
			||||||
@ -468,6 +479,9 @@ int filtergraph_is_simple(FilterGraph *fg);
 | 
				
			|||||||
int init_simple_filtergraph(InputStream *ist, OutputStream *ost);
 | 
					int init_simple_filtergraph(InputStream *ist, OutputStream *ost);
 | 
				
			||||||
int init_complex_filtergraph(FilterGraph *fg);
 | 
					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 avconv_parse_options(int argc, char **argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int vdpau_init(AVCodecContext *s);
 | 
					int vdpau_init(AVCodecContext *s);
 | 
				
			||||||
 | 
				
			|||||||
@ -97,6 +97,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost)
 | 
				
			|||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    fg->inputs[0]->ist   = ist;
 | 
					    fg->inputs[0]->ist   = ist;
 | 
				
			||||||
    fg->inputs[0]->graph = fg;
 | 
					    fg->inputs[0]->graph = fg;
 | 
				
			||||||
 | 
					    fg->inputs[0]->format = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GROW_ARRAY(ist->filters, ist->nb_filters);
 | 
					    GROW_ARRAY(ist->filters, ist->nb_filters);
 | 
				
			||||||
    ist->filters[ist->nb_filters - 1] = fg->inputs[0];
 | 
					    ist->filters[ist->nb_filters - 1] = fg->inputs[0];
 | 
				
			||||||
@ -172,6 +173,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
 | 
				
			|||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    fg->inputs[fg->nb_inputs - 1]->ist   = ist;
 | 
					    fg->inputs[fg->nb_inputs - 1]->ist   = ist;
 | 
				
			||||||
    fg->inputs[fg->nb_inputs - 1]->graph = fg;
 | 
					    fg->inputs[fg->nb_inputs - 1]->graph = fg;
 | 
				
			||||||
 | 
					    fg->inputs[fg->nb_inputs - 1]->format = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GROW_ARRAY(ist->filters, ist->nb_filters);
 | 
					    GROW_ARRAY(ist->filters, ist->nb_filters);
 | 
				
			||||||
    ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
 | 
					    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)
 | 
					    if (!par)
 | 
				
			||||||
        return AVERROR(ENOMEM);
 | 
					        return AVERROR(ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    par->sample_aspect_ratio = ist->st->sample_aspect_ratio.num ?
 | 
					    par->sample_aspect_ratio = ifilter->sample_aspect_ratio;
 | 
				
			||||||
                               ist->st->sample_aspect_ratio :
 | 
					    par->width               = ifilter->width;
 | 
				
			||||||
                               ist->dec_ctx->sample_aspect_ratio;
 | 
					    par->height              = ifilter->height;
 | 
				
			||||||
    par->width               = ist->dec_ctx->width;
 | 
					    par->format              = ifilter->format;
 | 
				
			||||||
    par->height              = ist->dec_ctx->height;
 | 
					 | 
				
			||||||
    par->format              = ist->hwaccel_retrieve_data ?
 | 
					 | 
				
			||||||
                               ist->hwaccel_retrieved_pix_fmt : ist->dec_ctx->pix_fmt;
 | 
					 | 
				
			||||||
    par->time_base           = tb;
 | 
					    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);
 | 
					    ret = av_buffersrc_parameters_set(ifilter->filter, par);
 | 
				
			||||||
    av_freep(&par);
 | 
					    av_freep(&par);
 | 
				
			||||||
@ -597,10 +596,10 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
 | 
				
			|||||||
    if (!par)
 | 
					    if (!par)
 | 
				
			||||||
        return AVERROR(ENOMEM);
 | 
					        return AVERROR(ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    par->time_base      = (AVRational){ 1, ist->dec_ctx->sample_rate };
 | 
					    par->time_base      = (AVRational){ 1, ifilter->sample_rate };
 | 
				
			||||||
    par->sample_rate    = ist->dec_ctx->sample_rate;
 | 
					    par->sample_rate    = ifilter->sample_rate;
 | 
				
			||||||
    par->format         = ist->dec_ctx->sample_fmt;
 | 
					    par->format         = ifilter->format;
 | 
				
			||||||
    par->channel_layout = ist->dec_ctx->channel_layout;
 | 
					    par->channel_layout = ifilter->channel_layout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = av_buffersrc_parameters_set(ifilter->filter, par);
 | 
					    ret = av_buffersrc_parameters_set(ifilter->filter, par);
 | 
				
			||||||
    av_freep(&par);
 | 
					    av_freep(&par);
 | 
				
			||||||
@ -751,6 +750,53 @@ int configure_filtergraph(FilterGraph *fg)
 | 
				
			|||||||
    return 0;
 | 
					    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 ist_in_filtergraph(FilterGraph *fg, InputStream *ist)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										24
									
								
								avconv_opt.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								avconv_opt.c
									
									
									
									
									
								
							@ -1498,12 +1498,28 @@ static int init_complex_filters(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int configure_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++)
 | 
					    for (i = 0; i < nb_filtergraphs; i++) {
 | 
				
			||||||
        if (!filtergraph_is_simple(filtergraphs[i]) &&
 | 
					        FilterGraph *fg = filtergraphs[i];
 | 
				
			||||||
            (ret = configure_filtergraph(filtergraphs[i])) < 0)
 | 
					
 | 
				
			||||||
 | 
					        if (filtergraph_is_simple(fg))
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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 ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user