From 7d948dc424c3620e351d27afdf933c99f9435467 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 9 Mar 2011 15:13:59 +0100 Subject: [PATCH] Support changing pixel formats on avfilter input. Fix issue2217 Signed-off-by: Michael Niedermayer --- ffmpeg.c | 5 ++-- libavfilter/vsrc_buffer.c | 53 +++++++++++++++++++++++++++++++++++++-- libavfilter/vsrc_buffer.h | 4 +++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index 5d89fc064d..fb4ec61ec5 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -1624,9 +1624,10 @@ static int output_packet(AVInputStream *ist, int ist_index, if (ist->st->sample_aspect_ratio.num) sar = ist->st->sample_aspect_ratio; else sar = ist->st->codec->sample_aspect_ratio; // add it to be filtered - av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, + av_vsrc_buffer_add_frame2(ost->input_video_filter, &picture, ist->pts, - sar); + sar, ist->st->codec->width, ist->st->codec->height, + ist->st->codec->pix_fmt, "0:0"); //TODO user setable params } } } diff --git a/libavfilter/vsrc_buffer.c b/libavfilter/vsrc_buffer.c index 7b9ae95074..226c48ea02 100644 --- a/libavfilter/vsrc_buffer.c +++ b/libavfilter/vsrc_buffer.c @@ -37,10 +37,13 @@ typedef struct { AVRational pixel_aspect; } BufferSourceContext; -int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, - int64_t pts, AVRational pixel_aspect) +int av_vsrc_buffer_add_frame2(AVFilterContext *buffer_filter, AVFrame *frame, + int64_t pts, AVRational pixel_aspect, int width, + int height, enum PixelFormat pix_fmt, + const char *sws_param) { BufferSourceContext *c = buffer_filter->priv; + int ret; if (c->has_frame) { av_log(buffer_filter, AV_LOG_ERROR, @@ -50,6 +53,42 @@ int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, //return -1; } + if(width != c->w || height != c->h || pix_fmt != c->pix_fmt){ + AVFilterContext *scale= buffer_filter->outputs[0]->dst; + AVFilterLink *link; + + av_log(buffer_filter, AV_LOG_INFO, "Changing filter graph input to accept %dx%d %d (%d %d)\n", + width,height,pix_fmt, c->pix_fmt, scale->outputs[0]->format); + + if(!scale || strcmp(scale->filter->name,"scale")){ + AVFilter *f= avfilter_get_by_name("scale"); + + av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n"); + if(avfilter_open(&scale, f, "Input equalizer") < 0) + return -1; + + if((ret=avfilter_init_filter(scale, sws_param, NULL))<0){ + avfilter_free(scale); + return ret; + } + + if((ret=avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0))<0){ + avfilter_free(scale); + return ret; + } + + scale->outputs[0]->format= c->pix_fmt; + } + + c->pix_fmt= scale->inputs[0]->format= pix_fmt; + c->w= scale->inputs[0]->w= width; + c->h= scale->inputs[0]->h= height; + + link= scale->outputs[0]; + if ((ret = link->srcpad->config_props(link)) < 0) + return ret; + } + memcpy(c->frame.data , frame->data , sizeof(frame->data)); memcpy(c->frame.linesize, frame->linesize, sizeof(frame->linesize)); c->frame.interlaced_frame= frame->interlaced_frame; @@ -61,6 +100,16 @@ int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, return 0; } +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, + int64_t pts, AVRational pixel_aspect) +{ + BufferSourceContext *c = buffer_filter->priv; + + return av_vsrc_buffer_add_frame2(buffer_filter, frame, + pts, pixel_aspect, c->w, + c->h, c->pix_fmt, ""); +} + static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) { BufferSourceContext *c = ctx->priv; diff --git a/libavfilter/vsrc_buffer.h b/libavfilter/vsrc_buffer.h index a77e42f36c..f6e024cd0b 100644 --- a/libavfilter/vsrc_buffer.h +++ b/libavfilter/vsrc_buffer.h @@ -25,3 +25,7 @@ int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, int64_t pts, AVRational pixel_aspect); +int av_vsrc_buffer_add_frame2(AVFilterContext *buffer_filter, AVFrame *frame, + int64_t pts, AVRational pixel_aspect, int width, + int height, enum PixelFormat pix_fmt, + const char *sws_param);