2 * Copyright (c) 2008 Vitor Sessak
4 * This file is part of Libav.
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * memory buffer source filter
27 #include "vsrc_buffer.h"
28 #include "libavutil/imgutils.h"
35 enum PixelFormat pix_fmt
;
36 AVRational time_base
; ///< time_base to set in the output link
37 AVRational pixel_aspect
;
38 } BufferSourceContext
;
40 int av_vsrc_buffer_add_frame(AVFilterContext
*buffer_filter
, AVFrame
*frame
,
41 int64_t pts
, AVRational pixel_aspect
)
43 BufferSourceContext
*c
= buffer_filter
->priv
;
46 av_log(buffer_filter
, AV_LOG_ERROR
,
47 "Buffering several frames is not supported. "
48 "Please consume all available frames before adding a new one.\n"
53 memcpy(c
->frame
.data
, frame
->data
, sizeof(frame
->data
));
54 memcpy(c
->frame
.linesize
, frame
->linesize
, sizeof(frame
->linesize
));
55 c
->frame
.interlaced_frame
= frame
->interlaced_frame
;
56 c
->frame
.top_field_first
= frame
->top_field_first
;
57 c
->frame
.key_frame
= frame
->key_frame
;
58 c
->frame
.pict_type
= frame
->pict_type
;
60 c
->pixel_aspect
= pixel_aspect
;
66 static av_cold
int init(AVFilterContext
*ctx
, const char *args
, void *opaque
)
68 BufferSourceContext
*c
= ctx
->priv
;
69 char pix_fmt_str
[128];
73 (n
= sscanf(args
, "%d:%d:%127[^:]:%d:%d:%d:%d", &c
->w
, &c
->h
, pix_fmt_str
,
74 &c
->time_base
.num
, &c
->time_base
.den
,
75 &c
->pixel_aspect
.num
, &c
->pixel_aspect
.den
)) != 7) {
76 av_log(ctx
, AV_LOG_ERROR
, "Expected 7 arguments, but %d found in '%s'\n", n
, args
);
77 return AVERROR(EINVAL
);
79 if ((c
->pix_fmt
= av_get_pix_fmt(pix_fmt_str
)) == PIX_FMT_NONE
) {
81 c
->pix_fmt
= strtol(pix_fmt_str
, &tail
, 10);
82 if (*tail
|| c
->pix_fmt
< 0 || c
->pix_fmt
>= PIX_FMT_NB
) {
83 av_log(ctx
, AV_LOG_ERROR
, "Invalid pixel format string '%s'\n", pix_fmt_str
);
84 return AVERROR(EINVAL
);
88 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
);
92 static int query_formats(AVFilterContext
*ctx
)
94 BufferSourceContext
*c
= ctx
->priv
;
95 enum PixelFormat pix_fmts
[] = { c
->pix_fmt
, PIX_FMT_NONE
};
97 avfilter_set_common_formats(ctx
, avfilter_make_format_list(pix_fmts
));
101 static int config_props(AVFilterLink
*link
)
103 BufferSourceContext
*c
= link
->src
->priv
;
107 link
->sample_aspect_ratio
= c
->pixel_aspect
;
108 link
->time_base
= c
->time_base
;
113 static int request_frame(AVFilterLink
*link
)
115 BufferSourceContext
*c
= link
->src
->priv
;
116 AVFilterBufferRef
*picref
;
119 av_log(link
->src
, AV_LOG_ERROR
,
120 "request_frame() called with no available frame!\n");
124 /* This picture will be needed unmodified later for decoding the next
126 picref
= avfilter_get_video_buffer(link
, AV_PERM_WRITE
| AV_PERM_PRESERVE
|
130 av_image_copy(picref
->data
, picref
->linesize
,
131 c
->frame
.data
, c
->frame
.linesize
,
132 picref
->format
, link
->w
, link
->h
);
134 avfilter_copy_frame_props(picref
, &c
->frame
);
135 picref
->pts
= c
->pts
;
136 picref
->video
->pixel_aspect
= c
->pixel_aspect
;
137 avfilter_start_frame(link
, avfilter_ref_buffer(picref
, ~0));
138 avfilter_draw_slice(link
, 0, link
->h
, 1);
139 avfilter_end_frame(link
);
140 avfilter_unref_buffer(picref
);
147 static int poll_frame(AVFilterLink
*link
)
149 BufferSourceContext
*c
= link
->src
->priv
;
150 return !!(c
->has_frame
);
153 AVFilter avfilter_vsrc_buffer
= {
155 .description
= NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."),
156 .priv_size
= sizeof(BufferSourceContext
),
157 .query_formats
= query_formats
,
161 .inputs
= (AVFilterPad
[]) {{ .name
= NULL
}},
162 .outputs
= (AVFilterPad
[]) {{ .name
= "default",
163 .type
= AVMEDIA_TYPE_VIDEO
,
164 .request_frame
= request_frame
,
165 .poll_frame
= poll_frame
,
166 .config_props
= config_props
, },