Originally committed as revision 23039 to svn://svn.ffmpeg.org/ffmpeg/trunk
Showing the changes to libavfilter/vsrc_buffer.c (1 of 2 files). Show all
Unified · Split
| @@ -0,0 +1,140 @@ | ||
| 1 | +/* | |
| 2 | + * Memory buffer source filter | |
| 3 | + * Copyright (c) 2008 Vitor Sessak | |
| 4 | + * | |
| 5 | + * This file is part of FFmpeg. | |
| 6 | + * | |
| 7 | + * FFmpeg is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2.1 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * FFmpeg is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with FFmpeg; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include "avfilter.h" | |
| 23 | +#include "vsrc_buffer.h" | |
| 24 | + | |
| 25 | +typedef struct { | |
| 26 | + int64_t pts; | |
| 27 | + AVFrame frame; | |
| 28 | + int has_frame; | |
| 29 | + int h, w, pix_fmt; | |
| 30 | + AVRational pixel_aspect; | |
| 31 | +} BufferSourceContext; | |
| 32 | + | |
| 33 | + | |
| 34 | +int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, | |
| 35 | + int64_t pts, AVRational pixel_aspect) | |
| 36 | +{ | |
| 37 | + BufferSourceContext *c = buffer_filter->priv; | |
| 38 | + | |
| 39 | + if (c->has_frame) { | |
| 40 | + av_log(buffer_filter, AV_LOG_ERROR, | |
| 41 | + "Buffering several frames is not supported. " | |
| 42 | + "Please consume all available frames before adding a new one.\n" | |
| 43 | + ); | |
| 44 | + //return -1; | |
| 45 | + } | |
| 46 | + | |
| 47 | + memcpy(c->frame.data , frame->data , sizeof(frame->data)); | |
| 48 | + memcpy(c->frame.linesize, frame->linesize, sizeof(frame->linesize)); | |
| 49 | + c->pts = pts; | |
| 50 | + c->pixel_aspect = pixel_aspect; | |
| 51 | + c->has_frame = 1; | |
| 52 | + | |
| 53 | + return 0; | |
| 54 | +} | |
| 55 | + | |
| 56 | +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) | |
| 57 | +{ | |
| 58 | + BufferSourceContext *c = ctx->priv; | |
| 59 | + | |
| 60 | + if(args && sscanf(args, "%d:%d:%d", &c->w, &c->h, &c->pix_fmt) == 3) | |
| 61 | + return 0; | |
| 62 | + | |
| 63 | + av_log(ctx, AV_LOG_ERROR, "init() expected 3 arguments:'%s'\n", args); | |
| 64 | + return -1; | |
| 65 | +} | |
| 66 | + | |
| 67 | +static int query_formats(AVFilterContext *ctx) | |
| 68 | +{ | |
| 69 | + BufferSourceContext *c = ctx->priv; | |
| 70 | + enum PixelFormat pix_fmts[] = { c->pix_fmt, PIX_FMT_NONE }; | |
| 71 | + | |
| 72 | + avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); | |
| 73 | + return 0; | |
| 74 | +} | |
| 75 | + | |
| 76 | +static int config_props(AVFilterLink *link) | |
| 77 | +{ | |
| 78 | + BufferSourceContext *c = link->src->priv; | |
| 79 | + | |
| 80 | + link->w = c->w; | |
| 81 | + link->h = c->h; | |
| 82 | + | |
| 83 | + return 0; | |
| 84 | +} | |
| 85 | + | |
| 86 | + | |
| 87 | +static int request_frame(AVFilterLink *link) | |
| 88 | +{ | |
| 89 | + BufferSourceContext *c = link->src->priv; | |
| 90 | + AVFilterPicRef *picref; | |
| 91 | + | |
| 92 | + if (!c->has_frame) { | |
| 93 | + av_log(link->src, AV_LOG_ERROR, | |
| 94 | + "request_frame() called with no available frame!\n"); | |
| 95 | + //return -1; | |
| 96 | + } | |
| 97 | + | |
| 98 | + /* This picture will be needed unmodified later for decoding the next | |
| 99 | + * frame */ | |
| 100 | + picref = avfilter_get_video_buffer(link, AV_PERM_WRITE | AV_PERM_PRESERVE | | |
| 101 | + AV_PERM_REUSE2, | |
| 102 | + link->w, link->h); | |
| 103 | + | |
| 104 | + av_picture_copy((AVPicture *)&picref->data, (AVPicture *)&c->frame, | |
| 105 | + picref->pic->format, link->w, link->h); | |
| 106 | + | |
| 107 | + picref->pts = c->pts; | |
| 108 | + picref->pixel_aspect = c->pixel_aspect; | |
| 109 | + avfilter_start_frame(link, avfilter_ref_pic(picref, ~0)); | |
| 110 | + avfilter_draw_slice(link, 0, link->h, 1); | |
| 111 | + avfilter_end_frame(link); | |
| 112 | + avfilter_unref_pic(picref); | |
| 113 | + | |
| 114 | + c->has_frame = 0; | |
| 115 | + | |
| 116 | + return 0; | |
| 117 | +} | |
| 118 | + | |
| 119 | +static int poll_frame(AVFilterLink *link) | |
| 120 | +{ | |
| 121 | + BufferSourceContext *c = link->src->priv; | |
| 122 | + return !!(c->has_frame); | |
| 123 | +} | |
| 124 | + | |
| 125 | +AVFilter avfilter_vsrc_buffer = | |
| 126 | +{ | |
| 127 | + .name = "buffer", | |
| 128 | + .priv_size = sizeof(BufferSourceContext), | |
| 129 | + .query_formats = query_formats, | |
| 130 | + | |
| 131 | + .init = init, | |
| 132 | + | |
| 133 | + .inputs = (AVFilterPad[]) {{ .name = NULL }}, | |
| 134 | + .outputs = (AVFilterPad[]) {{ .name = "default", | |
| 135 | + .type = AVMEDIA_TYPE_VIDEO, | |
| 136 | + .request_frame = request_frame, | |
| 137 | + .poll_frame = poll_frame, | |
| 138 | + .config_props = config_props, }, | |
| 139 | + { .name = NULL}}, | |
| 140 | +}; | |