AVFilterBufferRef *avfilter_get_video_buffer_ref_from_frame(const AVFrame *frame, int perms) { AVFilterBufferRef *picref = avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize, perms, frame->width, frame->height, frame->format); if (!picref) return NULL; avfilter_copy_frame_props(picref, frame); return picref; }
static int compat_read(AVFilterContext *ctx, AVFilterBufferRef **pbuf, int nb_samples) { AVFilterBufferRef *buf; AVFrame *frame; int ret; if (!pbuf) return ff_poll_frame(ctx->inputs[0]); frame = av_frame_alloc(); if (!frame) return AVERROR(ENOMEM); if (!nb_samples) ret = av_buffersink_get_frame(ctx, frame); else ret = av_buffersink_get_samples(ctx, frame, nb_samples); if (ret < 0) goto fail; if (ctx->inputs[0]->type == AVMEDIA_TYPE_VIDEO) { buf = avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize, AV_PERM_READ, frame->width, frame->height, frame->format); } else { buf = avfilter_get_audio_buffer_ref_from_arrays(frame->extended_data, frame->linesize[0], AV_PERM_READ, frame->nb_samples, frame->format, frame->channel_layout); } if (!buf) { ret = AVERROR(ENOMEM); goto fail; } avfilter_copy_frame_props(buf, frame); buf->buf->priv = frame; buf->buf->free = compat_free_buffer; *pbuf = buf; return 0; fail: av_frame_free(&frame); return ret; }
/* TODO: set the buffer's priv member to a context structure for the whole * filter chain. This will allow for a buffer pool instead of the constant * alloc & free cycle currently implemented. */ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h) { int linesize[4]; uint8_t *data[4]; int i; AVFilterBufferRef *picref = NULL; AVFilterPool *pool = link->pool; if (pool) { for (i = 0; i < POOL_SIZE; i++) { picref = pool->pic[i]; if (picref && picref->buf->format == link->format && picref->buf->w == w && picref->buf->h == h) { AVFilterBuffer *pic = picref->buf; pool->pic[i] = NULL; pool->count--; picref->video->w = w; picref->video->h = h; picref->perms = perms | AV_PERM_READ; picref->format = link->format; pic->refcount = 1; memcpy(picref->data, pic->data, sizeof(picref->data)); memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize)); pool->refcount++; return picref; } } } else { pool = link->pool = av_mallocz(sizeof(AVFilterPool)); pool->refcount = 1; } // align: +2 is needed for swscaler, +16 to be SIMD-friendly if ((i = av_image_alloc(data, linesize, w, h, link->format, 32)) < 0) return NULL; picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize, perms, w, h, link->format); if (!picref) { av_free(data[0]); return NULL; } memset(data[0], 128, i); picref->buf->priv = pool; picref->buf->free = NULL; pool->refcount++; return picref; }
/* TODO: set the buffer's priv member to a context structure for the whole * filter chain. This will allow for a buffer pool instead of the constant * alloc & free cycle currently implemented. */ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h) { int linesize[4]; uint8_t *data[4]; AVFilterBufferRef *picref = NULL; // +2 is needed for swscaler, +16 to be SIMD-friendly if (av_image_alloc(data, linesize, w, h, link->format, 16) < 0) return NULL; picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize, perms, w, h, link->format); if (!picref) { av_free(data[0]); return NULL; } return picref; }
static AVFilterBufferRef *mpi_to_bufref(mp_image_t *mpi, enum AVPixelFormat fmt, AVRational sar) { AVFilterBufferRef *buf; int perms = AV_PERM_READ; if ((mpi->flags & MP_IMGFLAG_ALLOCATED)) perms |= AV_PERM_REUSE2; if (!(mpi->flags & MP_IMGFLAG_PRESERVE)) perms |= AV_PERM_WRITE; buf = avfilter_get_video_buffer_ref_from_arrays(mpi->planes, mpi->stride, perms, mpi->w, mpi->h, fmt); buf->video->sample_aspect_ratio = sar; buf->buf->priv = mpi; buf->buf->free = buf_mpi_free; return buf; }