Libav 0.7.1
|
00001 /* 00002 * Copyright (c) 2008 Vitor Sessak 00003 * 00004 * This file is part of Libav. 00005 * 00006 * Libav is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * Libav is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with Libav; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00026 #include "avfilter.h" 00027 #include "vsrc_buffer.h" 00028 #include "libavutil/imgutils.h" 00029 00030 typedef struct { 00031 int64_t pts; 00032 AVFrame frame; 00033 int has_frame; 00034 int h, w; 00035 enum PixelFormat pix_fmt; 00036 AVRational time_base; 00037 AVRational pixel_aspect; 00038 } BufferSourceContext; 00039 00040 int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, 00041 int64_t pts, AVRational pixel_aspect) 00042 { 00043 BufferSourceContext *c = buffer_filter->priv; 00044 00045 if (c->has_frame) { 00046 av_log(buffer_filter, AV_LOG_ERROR, 00047 "Buffering several frames is not supported. " 00048 "Please consume all available frames before adding a new one.\n" 00049 ); 00050 //return -1; 00051 } 00052 00053 memcpy(c->frame.data , frame->data , sizeof(frame->data)); 00054 memcpy(c->frame.linesize, frame->linesize, sizeof(frame->linesize)); 00055 c->frame.interlaced_frame= frame->interlaced_frame; 00056 c->frame.top_field_first = frame->top_field_first; 00057 c->frame.key_frame = frame->key_frame; 00058 c->frame.pict_type = frame->pict_type; 00059 c->pts = pts; 00060 c->pixel_aspect = pixel_aspect; 00061 c->has_frame = 1; 00062 00063 return 0; 00064 } 00065 00066 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) 00067 { 00068 BufferSourceContext *c = ctx->priv; 00069 char pix_fmt_str[128]; 00070 int n = 0; 00071 00072 if (!args || 00073 (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d", &c->w, &c->h, pix_fmt_str, 00074 &c->time_base.num, &c->time_base.den, 00075 &c->pixel_aspect.num, &c->pixel_aspect.den)) != 7) { 00076 av_log(ctx, AV_LOG_ERROR, "Expected 7 arguments, but %d found in '%s'\n", n, args); 00077 return AVERROR(EINVAL); 00078 } 00079 if ((c->pix_fmt = av_get_pix_fmt(pix_fmt_str)) == PIX_FMT_NONE) { 00080 char *tail; 00081 c->pix_fmt = strtol(pix_fmt_str, &tail, 10); 00082 if (*tail || c->pix_fmt < 0 || c->pix_fmt >= PIX_FMT_NB) { 00083 av_log(ctx, AV_LOG_ERROR, "Invalid pixel format string '%s'\n", pix_fmt_str); 00084 return AVERROR(EINVAL); 00085 } 00086 } 00087 00088 av_log(ctx, AV_LOG_INFO, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name); 00089 return 0; 00090 } 00091 00092 static int query_formats(AVFilterContext *ctx) 00093 { 00094 BufferSourceContext *c = ctx->priv; 00095 enum PixelFormat pix_fmts[] = { c->pix_fmt, PIX_FMT_NONE }; 00096 00097 avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); 00098 return 0; 00099 } 00100 00101 static int config_props(AVFilterLink *link) 00102 { 00103 BufferSourceContext *c = link->src->priv; 00104 00105 link->w = c->w; 00106 link->h = c->h; 00107 link->sample_aspect_ratio = c->pixel_aspect; 00108 link->time_base = c->time_base; 00109 00110 return 0; 00111 } 00112 00113 static int request_frame(AVFilterLink *link) 00114 { 00115 BufferSourceContext *c = link->src->priv; 00116 AVFilterBufferRef *picref; 00117 00118 if (!c->has_frame) { 00119 av_log(link->src, AV_LOG_ERROR, 00120 "request_frame() called with no available frame!\n"); 00121 //return -1; 00122 } 00123 00124 /* This picture will be needed unmodified later for decoding the next 00125 * frame */ 00126 picref = avfilter_get_video_buffer(link, AV_PERM_WRITE | AV_PERM_PRESERVE | 00127 AV_PERM_REUSE2, 00128 link->w, link->h); 00129 00130 av_image_copy(picref->data, picref->linesize, 00131 c->frame.data, c->frame.linesize, 00132 picref->format, link->w, link->h); 00133 00134 picref->pts = c->pts; 00135 picref->video->pixel_aspect = c->pixel_aspect; 00136 picref->video->interlaced = c->frame.interlaced_frame; 00137 picref->video->top_field_first = c->frame.top_field_first; 00138 picref->video->key_frame = c->frame.key_frame; 00139 picref->video->pict_type = c->frame.pict_type; 00140 avfilter_start_frame(link, avfilter_ref_buffer(picref, ~0)); 00141 avfilter_draw_slice(link, 0, link->h, 1); 00142 avfilter_end_frame(link); 00143 avfilter_unref_buffer(picref); 00144 00145 c->has_frame = 0; 00146 00147 return 0; 00148 } 00149 00150 static int poll_frame(AVFilterLink *link) 00151 { 00152 BufferSourceContext *c = link->src->priv; 00153 return !!(c->has_frame); 00154 } 00155 00156 AVFilter avfilter_vsrc_buffer = { 00157 .name = "buffer", 00158 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."), 00159 .priv_size = sizeof(BufferSourceContext), 00160 .query_formats = query_formats, 00161 00162 .init = init, 00163 00164 .inputs = (AVFilterPad[]) {{ .name = NULL }}, 00165 .outputs = (AVFilterPad[]) {{ .name = "default", 00166 .type = AVMEDIA_TYPE_VIDEO, 00167 .request_frame = request_frame, 00168 .poll_frame = poll_frame, 00169 .config_props = config_props, }, 00170 { .name = NULL}}, 00171 };