diff options
Diffstat (limited to 'libavfilter/avfilter.c')
-rw-r--r-- | libavfilter/avfilter.c | 260 |
1 files changed, 215 insertions, 45 deletions
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index abeae14..63085dc 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -2,20 +2,20 @@ * filter layer * Copyright (c) 2007 Bobby Bingham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,6 +25,8 @@ #include "libavutil/rational.h" #include "libavutil/audioconvert.h" #include "libavutil/imgutils.h" +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" #include "avfilter.h" #include "internal.h" @@ -34,13 +36,22 @@ unsigned avfilter_version(void) { const char *avfilter_configuration(void) { - return LIBAV_CONFIGURATION; + return FFMPEG_CONFIGURATION; } const char *avfilter_license(void) { #define LICENSE_PREFIX "libavfilter license: " - return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; +} + +static void command_queue_pop(AVFilterContext *filter) +{ + AVFilterCommand *c= filter->command_queue; + av_freep(&c->arg); + av_freep(&c->command); + filter->command_queue= c->next; + av_free(c); } AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) @@ -69,14 +80,47 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) return ret; } +static void store_in_pool(AVFilterBufferRef *ref) +{ + int i; + AVFilterPool *pool= ref->buf->priv; + + av_assert0(ref->buf->data[0]); + + if (pool->count == POOL_SIZE) { + AVFilterBufferRef *ref1 = pool->pic[0]; + av_freep(&ref1->video); + av_freep(&ref1->audio); + av_freep(&ref1->buf->data[0]); + av_freep(&ref1->buf); + av_free(ref1); + memmove(&pool->pic[0], &pool->pic[1], sizeof(void*)*(POOL_SIZE-1)); + pool->count--; + pool->pic[POOL_SIZE-1] = NULL; + } + + for (i = 0; i < POOL_SIZE; i++) { + if (!pool->pic[i]) { + pool->pic[i] = ref; + pool->count++; + break; + } + } +} + void avfilter_unref_buffer(AVFilterBufferRef *ref) { if (!ref) return; - if (!(--ref->buf->refcount)) + if (!(--ref->buf->refcount)) { + if (!ref->buf->free) { + store_in_pool(ref); + return; + } ref->buf->free(ref->buf); - av_free(ref->video); - av_free(ref->audio); + } + av_freep(&ref->video); + av_freep(&ref->audio); av_free(ref); } @@ -131,6 +175,32 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, return 0; } +void avfilter_link_free(AVFilterLink **link) +{ + if (!*link) + return; + + if ((*link)->pool) { + int i; + for (i = 0; i < POOL_SIZE; i++) { + if ((*link)->pool->pic[i]) { + AVFilterBufferRef *picref = (*link)->pool->pic[i]; + /* free buffer: picrefs stored in the pool are not + * supposed to contain a free callback */ + av_freep(&picref->buf->data[0]); + av_freep(&picref->buf); + + av_freep(&picref->audio); + av_freep(&picref->video); + av_freep(&(*link)->pool->pic[i]); + } + } + (*link)->pool->count = 0; +// av_freep(&(*link)->pool); + } + av_freep(link); +} + int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) { @@ -158,6 +228,12 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, if (link->out_formats) avfilter_formats_changeref(&link->out_formats, &filt->outputs[filt_dstpad_idx]->out_formats); + if (link->out_chlayouts) + avfilter_formats_changeref(&link->out_chlayouts, + &filt->outputs[filt_dstpad_idx]->out_chlayouts); + if (link->out_packing) + avfilter_formats_changeref(&link->out_packing, + &filt->outputs[filt_dstpad_idx]->out_packing); return 0; } @@ -170,6 +246,8 @@ int avfilter_config_links(AVFilterContext *filter) for (i = 0; i < filter->input_count; i ++) { AVFilterLink *link = filter->inputs[i]; + AVFilterLink *inlink = link->src->input_count ? + link->src->inputs[0] : NULL; if (!link) continue; @@ -185,24 +263,55 @@ int avfilter_config_links(AVFilterContext *filter) if ((ret = avfilter_config_links(link->src)) < 0) return ret; - if (!(config_link = link->srcpad->config_props)) - config_link = avfilter_default_config_output_link; - if ((ret = config_link(link)) < 0) + if (!(config_link = link->srcpad->config_props)) { + if (link->src->input_count != 1) { + av_log(link->src, AV_LOG_ERROR, "Source filters and filters " + "with more than one input " + "must set config_props() " + "callbacks on all outputs\n"); + return AVERROR(EINVAL); + } + } else if ((ret = config_link(link)) < 0) return ret; - if (link->time_base.num == 0 && link->time_base.den == 0) - link->time_base = link->src && link->src->input_count ? - link->src->inputs[0]->time_base : AV_TIME_BASE_Q; - - if (link->sample_aspect_ratio.num == 0 && link->sample_aspect_ratio.den == 0) - link->sample_aspect_ratio = link->src->input_count ? - link->src->inputs[0]->sample_aspect_ratio : (AVRational){1,1}; - - if (link->sample_rate == 0 && link->src && link->src->input_count) - link->sample_rate = link->src->inputs[0]->sample_rate; - - if (link->channel_layout == 0 && link->src && link->src->input_count) - link->channel_layout = link->src->inputs[0]->channel_layout; + switch (link->type) { + case AVMEDIA_TYPE_VIDEO: + if (!link->time_base.num && !link->time_base.den) + link->time_base = inlink ? inlink->time_base : AV_TIME_BASE_Q; + + if (!link->sample_aspect_ratio.num && !link->sample_aspect_ratio.den) + link->sample_aspect_ratio = inlink ? + inlink->sample_aspect_ratio : (AVRational){1,1}; + + if (inlink) { + if (!link->w) + link->w = inlink->w; + if (!link->h) + link->h = inlink->h; + } else if (!link->w || !link->h) { + av_log(link->src, AV_LOG_ERROR, + "Video source filters must set their output link's " + "width and height\n"); + return AVERROR(EINVAL); + } + break; + + case AVMEDIA_TYPE_AUDIO: + if (inlink) { + if (!link->sample_rate) + link->sample_rate = inlink->sample_rate; + if (!link->time_base.num && !link->time_base.den) + link->time_base = inlink->time_base; + } else if (!link->sample_rate) { + av_log(link->src, AV_LOG_ERROR, + "Audio source filters must set their output link's " + "sample_rate\n"); + return AVERROR(EINVAL); + } + + if (!link->time_base.num && !link->time_base.den) + link->time_base = (AVRational) {1, link->sample_rate}; + } if ((config_link = link->dstpad->config_props)) if ((ret = config_link(link)) < 0) @@ -215,7 +324,6 @@ int avfilter_config_links(AVFilterContext *filter) return 0; } -#ifdef DEBUG static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms) { snprintf(buf, buf_size, "%s%s%s%s%s%s", @@ -227,7 +335,6 @@ static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms) perms & AV_PERM_NEG_LINESIZES ? "n" : ""); return buf; } -#endif static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) { @@ -240,7 +347,7 @@ static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) if (ref->video) { av_dlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c", - ref->video->pixel_aspect.num, ref->video->pixel_aspect.den, + ref->video->sample_aspect_ratio.num, ref->video->sample_aspect_ratio.den, ref->video->w, ref->video->h, !ref->video->interlaced ? 'P' : /* Progressive */ ref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ @@ -248,10 +355,9 @@ static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) av_get_picture_type_char(ref->video->pict_type)); } if (ref->audio) { - av_dlog(ctx, " cl:%"PRId64"d sn:%d s:%d sr:%d p:%d", + av_dlog(ctx, " cl:%"PRId64"d n:%d r:%d p:%d", ref->audio->channel_layout, ref->audio->nb_samples, - ref->audio->size, ref->audio->sample_rate, ref->audio->planar); } @@ -274,8 +380,8 @@ static void ff_dlog_link(void *ctx, AVFilterLink *link, int end) av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout); av_dlog(ctx, - "link[%p r:%"PRId64" cl:%s fmt:%-16s %-16s->%-16s]%s", - link, link->sample_rate, buf, + "link[%p r:%d cl:%s fmt:%-16s %-16s->%-16s]%s", + link, (int)link->sample_rate, buf, av_get_sample_fmt_name(link->format), link->src ? link->src->filter->name : "", link->dst ? link->dst->filter->name : "", @@ -308,7 +414,7 @@ AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int } AVFilterBufferRef * -avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int perms, +avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms, int w, int h, enum PixelFormat format) { AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer)); @@ -347,17 +453,16 @@ fail: return NULL; } -AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, - int64_t channel_layout, int planar) +AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, + int perms, int nb_samples) { AVFilterBufferRef *ret = NULL; if (link->dstpad->get_audio_buffer) - ret = link->dstpad->get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); + ret = link->dstpad->get_audio_buffer(link, perms, nb_samples); if (!ret) - ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); + ret = avfilter_default_get_audio_buffer(link, perms, nb_samples); if (ret) ret->type = AVMEDIA_TYPE_AUDIO; @@ -365,6 +470,48 @@ AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, return ret; } +AVFilterBufferRef * +avfilter_get_audio_buffer_ref_from_arrays(uint8_t *data[8], int linesize[8], int perms, + int nb_samples, enum AVSampleFormat sample_fmt, + int64_t channel_layout, int planar) +{ + AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer)); + AVFilterBufferRef *samplesref = av_mallocz(sizeof(AVFilterBufferRef)); + + if (!samples || !samplesref) + goto fail; + + samplesref->buf = samples; + samplesref->buf->free = ff_avfilter_default_free_buffer; + if (!(samplesref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps)))) + goto fail; + + samplesref->audio->nb_samples = nb_samples; + samplesref->audio->channel_layout = channel_layout; + samplesref->audio->planar = planar; + + /* make sure the buffer gets read permission or it's useless for output */ + samplesref->perms = perms | AV_PERM_READ; + + samples->refcount = 1; + samplesref->type = AVMEDIA_TYPE_AUDIO; + samplesref->format = sample_fmt; + + memcpy(samples->data, data, sizeof(samples->data)); + memcpy(samples->linesize, linesize, sizeof(samples->linesize)); + memcpy(samplesref->data, data, sizeof(samplesref->data)); + memcpy(samplesref->linesize, linesize, sizeof(samplesref->linesize)); + + return samplesref; + +fail: + if (samplesref && samplesref->audio) + av_freep(&samplesref->audio); + av_freep(&samplesref); + av_freep(&samples); + return NULL; +} + int avfilter_request_frame(AVFilterLink *link) { FF_DPRINTF_START(NULL, request_frame); ff_dlog_link(NULL, link, 1); @@ -401,6 +548,7 @@ void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) void (*start_frame)(AVFilterLink *, AVFilterBufferRef *); AVFilterPad *dst = link->dstpad; int perms = picref->perms; + AVFilterCommand *cmd= link->dst->command_queue; FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1); @@ -423,6 +571,15 @@ void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) else link->cur_buf = picref; + while(cmd && cmd->time <= picref->pts * av_q2d(link->time_base)){ + av_log(link->dst, AV_LOG_DEBUG, + "Processing command time:%f command:%s arg:%s\n", + cmd->time, cmd->command, cmd->arg); + avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags); + command_queue_pop(link->dst); + cmd= link->dst->command_queue; + } + start_frame(link, link->cur_buf); } @@ -484,10 +641,22 @@ void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) draw_slice(link, y, h, slice_dir); } +int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags) +{ + if(!strcmp(cmd, "ping")){ + av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name); + return 0; + }else if(filter->filter->process_command) { + return filter->filter->process_command(filter, cmd, arg, res, res_len, flags); + } + return AVERROR(ENOSYS); +} + void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) { void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); AVFilterPad *dst = link->dstpad; + int i; FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1); @@ -503,15 +672,13 @@ void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms); link->cur_buf = avfilter_default_get_audio_buffer(link, dst->min_perms, - samplesref->format, - samplesref->audio->size, - samplesref->audio->channel_layout, - samplesref->audio->planar); + samplesref->audio->nb_samples); link->cur_buf->pts = samplesref->pts; link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate; /* Copy actual data into new samples buffer */ - memcpy(link->cur_buf->data[0], samplesref->data[0], samplesref->audio->size); + for (i = 0; samplesref->data[i]; i++) + memcpy(link->cur_buf->data[i], samplesref->data[i], samplesref->linesize[0]); avfilter_unref_buffer(samplesref); } else @@ -651,7 +818,7 @@ void avfilter_free(AVFilterContext *filter) avfilter_formats_unref(&link->in_formats); avfilter_formats_unref(&link->out_formats); } - av_freep(&link); + avfilter_link_free(&link); } for (i = 0; i < filter->output_count; i++) { if ((link = filter->outputs[i])) { @@ -660,7 +827,7 @@ void avfilter_free(AVFilterContext *filter) avfilter_formats_unref(&link->in_formats); avfilter_formats_unref(&link->out_formats); } - av_freep(&link); + avfilter_link_free(&link); } av_freep(&filter->name); @@ -669,6 +836,9 @@ void avfilter_free(AVFilterContext *filter) av_freep(&filter->inputs); av_freep(&filter->outputs); av_freep(&filter->priv); + while(filter->command_queue){ + command_queue_pop(filter); + } av_free(filter); } |