| Index: source/patched-ffmpeg-mt/libavfilter/avfilter.c
|
| ===================================================================
|
| --- source/patched-ffmpeg-mt/libavfilter/avfilter.c (revision 59334)
|
| +++ source/patched-ffmpeg-mt/libavfilter/avfilter.c (working copy)
|
| @@ -21,8 +21,9 @@
|
|
|
| /* #define DEBUG */
|
|
|
| -#include "libavcodec/imgconvert.h"
|
| +#include "libavcodec/audioconvert.c"
|
| #include "libavutil/pixdesc.h"
|
| +#include "libavcore/imgutils.h"
|
| #include "avfilter.h"
|
| #include "internal.h"
|
|
|
| @@ -48,7 +49,24 @@
|
| AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
|
| {
|
| AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef));
|
| + if (!ret)
|
| + return NULL;
|
| *ret = *ref;
|
| + if (ref->type == AVMEDIA_TYPE_VIDEO) {
|
| + ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps));
|
| + if (!ret->video) {
|
| + av_free(ret);
|
| + return NULL;
|
| + }
|
| + *ret->video = *ref->video;
|
| + } else if (ref->type == AVMEDIA_TYPE_AUDIO) {
|
| + ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps));
|
| + if (!ret->audio) {
|
| + av_free(ret);
|
| + return NULL;
|
| + }
|
| + *ret->audio = *ref->audio;
|
| + }
|
| ret->perms &= pmask;
|
| ret->buf->refcount ++;
|
| return ret;
|
| @@ -56,8 +74,10 @@
|
|
|
| void avfilter_unref_buffer(AVFilterBufferRef *ref)
|
| {
|
| - if(!(--ref->buf->refcount))
|
| + if (!(--ref->buf->refcount))
|
| ref->buf->free(ref->buf);
|
| + av_free(ref->video);
|
| + av_free(ref->audio);
|
| av_free(ref);
|
| }
|
|
|
| @@ -76,10 +96,10 @@
|
| memcpy(*pads+idx, newpad, sizeof(AVFilterPad));
|
| (*links)[idx] = NULL;
|
|
|
| - (*count) ++;
|
| - for(i = idx+1; i < *count; i ++)
|
| - if(*links[i])
|
| - (*(unsigned *)((uint8_t *) *links[i] + padidx_off)) ++;
|
| + (*count)++;
|
| + for (i = idx+1; i < *count; i++)
|
| + if (*links[i])
|
| + (*(unsigned *)((uint8_t *) *links[i] + padidx_off))++;
|
| }
|
|
|
| int avfilter_link(AVFilterContext *src, unsigned srcpad,
|
| @@ -87,8 +107,8 @@
|
| {
|
| AVFilterLink *link;
|
|
|
| - if(src->output_count <= srcpad || dst->input_count <= dstpad ||
|
| - src->outputs[srcpad] || dst->inputs[dstpad])
|
| + if (src->output_count <= srcpad || dst->input_count <= dstpad ||
|
| + src->outputs[srcpad] || dst->inputs[dstpad])
|
| return -1;
|
|
|
| src->outputs[srcpad] =
|
| @@ -113,7 +133,7 @@
|
| filt->name, link->src->name, link->dst->name);
|
|
|
| link->dst->inputs[link->dstpad] = NULL;
|
| - if(avfilter_link(filt, out, link->dst, link->dstpad)) {
|
| + if (avfilter_link(filt, out, link->dst, link->dstpad)) {
|
| /* failed to link output filter to new filter */
|
| link->dst->inputs[link->dstpad] = link;
|
| return -1;
|
| @@ -126,7 +146,7 @@
|
|
|
| /* if any information on supported media formats already exists on the
|
| * link, we need to preserve that */
|
| - if(link->out_formats)
|
| + if (link->out_formats)
|
| avfilter_formats_changeref(&link->out_formats,
|
| &filt->outputs[out]->out_formats);
|
|
|
| @@ -138,12 +158,12 @@
|
| int (*config_link)(AVFilterLink *);
|
| unsigned i;
|
|
|
| - for(i = 0; i < filter->input_count; i ++) {
|
| + for (i = 0; i < filter->input_count; i ++) {
|
| AVFilterLink *link = filter->inputs[i];
|
|
|
| - if(!link) continue;
|
| + if (!link) continue;
|
|
|
| - switch(link->init_state) {
|
| + switch (link->init_state) {
|
| case AVLINK_INIT:
|
| continue;
|
| case AVLINK_STARTINIT:
|
| @@ -152,16 +172,16 @@
|
| case AVLINK_UNINIT:
|
| link->init_state = AVLINK_STARTINIT;
|
|
|
| - if(avfilter_config_links(link->src))
|
| + if (avfilter_config_links(link->src))
|
| return -1;
|
|
|
| - if(!(config_link = link_spad(link).config_props))
|
| + if (!(config_link = link_spad(link).config_props))
|
| config_link = avfilter_default_config_output_link;
|
| - if(config_link(link))
|
| + if (config_link(link))
|
| return -1;
|
|
|
| - if((config_link = link_dpad(link).config_props))
|
| - if(config_link(link))
|
| + if ((config_link = link_dpad(link).config_props))
|
| + if (config_link(link))
|
| return -1;
|
|
|
| link->init_state = AVLINK_INIT;
|
| @@ -171,16 +191,43 @@
|
| return 0;
|
| }
|
|
|
| -void ff_dprintf_picref(void *ctx, AVFilterBufferRef *picref, int end)
|
| +char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms)
|
| {
|
| + snprintf(buf, buf_size, "%s%s%s%s%s",
|
| + perms & AV_PERM_READ ? "r" : "",
|
| + perms & AV_PERM_WRITE ? "w" : "",
|
| + perms & AV_PERM_PRESERVE ? "p" : "",
|
| + perms & AV_PERM_REUSE ? "r" : "",
|
| + perms & AV_PERM_REUSE2 ? "R" : "");
|
| + return buf;
|
| +}
|
| +
|
| +void ff_dprintf_ref(void *ctx, AVFilterBufferRef *ref, int end)
|
| +{
|
| + av_unused char buf[16];
|
| dprintf(ctx,
|
| - "picref[%p data[%p, %p, %p, %p] linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64" a:%d/%d s:%dx%d]%s",
|
| - picref,
|
| - picref->data [0], picref->data [1], picref->data [2], picref->data [3],
|
| - picref->linesize[0], picref->linesize[1], picref->linesize[2], picref->linesize[3],
|
| - picref->pts, picref->pos,
|
| - picref->pixel_aspect.num, picref->pixel_aspect.den, picref->w, picref->h,
|
| - end ? "\n" : "");
|
| + "ref[%p buf:%p refcount:%d perms:%s data:%p linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64,
|
| + ref, ref->buf, ref->buf->refcount, ff_get_ref_perms_string(buf, sizeof(buf), ref->perms), ref->data[0],
|
| + ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3],
|
| + ref->pts, ref->pos);
|
| +
|
| + if (ref->video) {
|
| + dprintf(ctx, " a:%d/%d s:%dx%d i:%c",
|
| + ref->video->pixel_aspect.num, ref->video->pixel_aspect.den,
|
| + ref->video->w, ref->video->h,
|
| + !ref->video->interlaced ? 'P' : /* Progressive */
|
| + ref->video->top_field_first ? 'T' : 'B'); /* Top / Bottom */
|
| + }
|
| + if (ref->audio) {
|
| + dprintf(ctx, " cl:%"PRId64"d sn:%d s:%d sr:%d p:%d",
|
| + ref->audio->channel_layout,
|
| + ref->audio->samples_nb,
|
| + ref->audio->size,
|
| + ref->audio->sample_rate,
|
| + ref->audio->planar);
|
| + }
|
| +
|
| + dprintf(ctx, "]%s", end ? "\n" : "");
|
| }
|
|
|
| void ff_dprintf_link(void *ctx, AVFilterLink *link, int end)
|
| @@ -198,40 +245,63 @@
|
| {
|
| AVFilterBufferRef *ret = NULL;
|
|
|
| - FF_DPRINTF_START(NULL, get_video_buffer); ff_dprintf_link(NULL, link, 0); dprintf(NULL, " perms:%d w:%d h:%d\n", perms, w, h);
|
| + av_unused char buf[16];
|
| + FF_DPRINTF_START(NULL, get_video_buffer); ff_dprintf_link(NULL, link, 0);
|
| + dprintf(NULL, " perms:%s w:%d h:%d\n", ff_get_ref_perms_string(buf, sizeof(buf), perms), w, h);
|
|
|
| - if(link_dpad(link).get_video_buffer)
|
| + if (link_dpad(link).get_video_buffer)
|
| ret = link_dpad(link).get_video_buffer(link, perms, w, h);
|
|
|
| - if(!ret)
|
| + if (!ret)
|
| ret = avfilter_default_get_video_buffer(link, perms, w, h);
|
|
|
| - FF_DPRINTF_START(NULL, get_video_buffer); ff_dprintf_link(NULL, link, 0); dprintf(NULL, " returning "); ff_dprintf_picref(NULL, ret, 1);
|
| + if (ret)
|
| + ret->type = AVMEDIA_TYPE_VIDEO;
|
|
|
| + FF_DPRINTF_START(NULL, get_video_buffer); ff_dprintf_link(NULL, link, 0); dprintf(NULL, " returning "); ff_dprintf_ref(NULL, ret, 1);
|
| +
|
| return ret;
|
| }
|
|
|
| +AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms,
|
| + enum SampleFormat sample_fmt, int size,
|
| + int64_t channel_layout, int planar)
|
| +{
|
| + AVFilterBufferRef *ret = NULL;
|
| +
|
| + if (link_dpad(link).get_audio_buffer)
|
| + ret = link_dpad(link).get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar);
|
| +
|
| + if (!ret)
|
| + ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar);
|
| +
|
| + if (ret)
|
| + ret->type = AVMEDIA_TYPE_AUDIO;
|
| +
|
| + return ret;
|
| +}
|
| +
|
| int avfilter_request_frame(AVFilterLink *link)
|
| {
|
| FF_DPRINTF_START(NULL, request_frame); ff_dprintf_link(NULL, link, 1);
|
|
|
| - if(link_spad(link).request_frame)
|
| + if (link_spad(link).request_frame)
|
| return link_spad(link).request_frame(link);
|
| - else if(link->src->inputs[0])
|
| + else if (link->src->inputs[0])
|
| return avfilter_request_frame(link->src->inputs[0]);
|
| else return -1;
|
| }
|
|
|
| int avfilter_poll_frame(AVFilterLink *link)
|
| {
|
| - int i, min=INT_MAX;
|
| + int i, min = INT_MAX;
|
|
|
| - if(link_spad(link).poll_frame)
|
| + if (link_spad(link).poll_frame)
|
| return link_spad(link).poll_frame(link);
|
|
|
| - for (i=0; i<link->src->input_count; i++) {
|
| + for (i = 0; i < link->src->input_count; i++) {
|
| int val;
|
| - if(!link->src->inputs[i])
|
| + if (!link->src->inputs[i])
|
| return -1;
|
| val = avfilter_poll_frame(link->src->inputs[i]);
|
| min = FFMIN(min, val);
|
| @@ -247,22 +317,20 @@
|
| void (*start_frame)(AVFilterLink *, AVFilterBufferRef *);
|
| AVFilterPad *dst = &link_dpad(link);
|
|
|
| - FF_DPRINTF_START(NULL, start_frame); ff_dprintf_link(NULL, link, 0); dprintf(NULL, " "); ff_dprintf_picref(NULL, picref, 1);
|
| + FF_DPRINTF_START(NULL, start_frame); ff_dprintf_link(NULL, link, 0); dprintf(NULL, " "); ff_dprintf_ref(NULL, picref, 1);
|
|
|
| - if(!(start_frame = dst->start_frame))
|
| + if (!(start_frame = dst->start_frame))
|
| start_frame = avfilter_default_start_frame;
|
|
|
| /* prepare to copy the picture if it has insufficient permissions */
|
| - if((dst->min_perms & picref->perms) != dst->min_perms ||
|
| - dst->rej_perms & picref->perms) {
|
| - /*
|
| - av_log(link->dst, AV_LOG_INFO,
|
| + if ((dst->min_perms & picref->perms) != dst->min_perms ||
|
| + dst->rej_perms & picref->perms) {
|
| + av_log(link->dst, AV_LOG_DEBUG,
|
| "frame copy needed (have perms %x, need %x, reject %x)\n",
|
| picref->perms,
|
| link_dpad(link).min_perms, link_dpad(link).rej_perms);
|
| - */
|
|
|
| - link->cur_buf = avfilter_default_get_video_buffer(link, dst->min_perms, link->w, link->h);
|
| + link->cur_buf = avfilter_get_video_buffer(link, dst->min_perms, link->w, link->h);
|
| link->src_buf = picref;
|
| avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf);
|
| }
|
| @@ -276,18 +344,17 @@
|
| {
|
| void (*end_frame)(AVFilterLink *);
|
|
|
| - if(!(end_frame = link_dpad(link).end_frame))
|
| + if (!(end_frame = link_dpad(link).end_frame))
|
| end_frame = avfilter_default_end_frame;
|
|
|
| end_frame(link);
|
|
|
| /* unreference the source picture if we're feeding the destination filter
|
| * a copied version dues to permission issues */
|
| - if(link->src_buf) {
|
| + if (link->src_buf) {
|
| avfilter_unref_buffer(link->src_buf);
|
| link->src_buf = NULL;
|
| }
|
| -
|
| }
|
|
|
| void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
|
| @@ -299,11 +366,11 @@
|
| FF_DPRINTF_START(NULL, draw_slice); ff_dprintf_link(NULL, link, 0); dprintf(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir);
|
|
|
| /* copy the slice if needed for permission reasons */
|
| - if(link->src_buf) {
|
| + if (link->src_buf) {
|
| vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
|
|
|
| - for(i = 0; i < 4; i ++) {
|
| - if(link->src_buf->data[i]) {
|
| + for (i = 0; i < 4; i++) {
|
| + if (link->src_buf->data[i]) {
|
| src[i] = link->src_buf-> data[i] +
|
| (y >> (i==0 ? 0 : vsub)) * link->src_buf-> linesize[i];
|
| dst[i] = link->cur_buf->data[i] +
|
| @@ -312,25 +379,59 @@
|
| src[i] = dst[i] = NULL;
|
| }
|
|
|
| - for(i = 0; i < 4; i ++) {
|
| + for (i = 0; i < 4; i++) {
|
| int planew =
|
| - ff_get_plane_bytewidth(link->format, link->cur_buf->w, i);
|
| + av_image_get_linesize(link->format, link->cur_buf->video->w, i);
|
|
|
| - if(!src[i]) continue;
|
| + if (!src[i]) continue;
|
|
|
| - for(j = 0; j < h >> (i==0 ? 0 : vsub); j ++) {
|
| + for (j = 0; j < h >> (i==0 ? 0 : vsub); j++) {
|
| memcpy(dst[i], src[i], planew);
|
| - src[i] += link->src_buf ->linesize[i];
|
| + src[i] += link->src_buf->linesize[i];
|
| dst[i] += link->cur_buf->linesize[i];
|
| }
|
| }
|
| }
|
|
|
| - if(!(draw_slice = link_dpad(link).draw_slice))
|
| + if (!(draw_slice = link_dpad(link).draw_slice))
|
| draw_slice = avfilter_default_draw_slice;
|
| draw_slice(link, y, h, slice_dir);
|
| }
|
|
|
| +void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
| +{
|
| + void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
|
| + AVFilterPad *dst = &link_dpad(link);
|
| +
|
| + if (!(filter_samples = dst->filter_samples))
|
| + filter_samples = avfilter_default_filter_samples;
|
| +
|
| + /* prepare to copy the samples if the buffer has insufficient permissions */
|
| + if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
|
| + dst->rej_perms & samplesref->perms) {
|
| +
|
| + av_log(link->dst, AV_LOG_DEBUG,
|
| + "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n",
|
| + samplesref->perms, link_dpad(link).min_perms, link_dpad(link).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);
|
| + 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);
|
| +
|
| + avfilter_unref_buffer(samplesref);
|
| + } else
|
| + link->cur_buf = samplesref;
|
| +
|
| + filter_samples(link, link->cur_buf);
|
| +}
|
| +
|
| #define MAX_REGISTERED_AVFILTERS_NB 64
|
|
|
| static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1];
|
| @@ -389,12 +490,13 @@
|
| LIBAVUTIL_VERSION_INT,
|
| };
|
|
|
| -AVFilterContext *avfilter_open(AVFilter *filter, const char *inst_name)
|
| +int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name)
|
| {
|
| AVFilterContext *ret;
|
| + *filter_ctx = NULL;
|
|
|
| if (!filter)
|
| - return 0;
|
| + return AVERROR(EINVAL);
|
|
|
| ret = av_mallocz(sizeof(AVFilterContext));
|
|
|
| @@ -417,18 +519,19 @@
|
| ret->outputs = av_mallocz(sizeof(AVFilterLink*) * ret->output_count);
|
| }
|
|
|
| - return ret;
|
| + *filter_ctx = ret;
|
| + return 0;
|
| }
|
|
|
| void avfilter_destroy(AVFilterContext *filter)
|
| {
|
| int i;
|
|
|
| - if(filter->filter->uninit)
|
| + if (filter->filter->uninit)
|
| filter->filter->uninit(filter);
|
|
|
| - for(i = 0; i < filter->input_count; i ++) {
|
| - if(filter->inputs[i]) {
|
| + for (i = 0; i < filter->input_count; i++) {
|
| + if (filter->inputs[i]) {
|
| if (filter->inputs[i]->src)
|
| filter->inputs[i]->src->outputs[filter->inputs[i]->srcpad] = NULL;
|
| avfilter_formats_unref(&filter->inputs[i]->in_formats);
|
| @@ -436,8 +539,8 @@
|
| }
|
| av_freep(&filter->inputs[i]);
|
| }
|
| - for(i = 0; i < filter->output_count; i ++) {
|
| - if(filter->outputs[i]) {
|
| + for (i = 0; i < filter->output_count; i++) {
|
| + if (filter->outputs[i]) {
|
| if (filter->outputs[i]->dst)
|
| filter->outputs[i]->dst->inputs[filter->outputs[i]->dstpad] = NULL;
|
| avfilter_formats_unref(&filter->outputs[i]->in_formats);
|
| @@ -459,7 +562,7 @@
|
| {
|
| int ret=0;
|
|
|
| - if(filter->filter->init)
|
| + if (filter->filter->init)
|
| ret = filter->filter->init(filter, args, opaque);
|
| return ret;
|
| }
|
|
|