Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavfilter
vsrc_buffer.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2008 Vitor Sessak
3
*
4
* This file is part of Libav.
5
*
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.
10
*
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.
15
*
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
19
*/
20
26
#include "
avfilter.h
"
27
#include "
buffersrc.h
"
28
#include "
vsrc_buffer.h
"
29
#include "
libavutil/imgutils.h
"
30
31
typedef
struct
{
32
AVFilterBufferRef
*
buf
;
33
int
h,
w
;
34
enum
PixelFormat
pix_fmt
;
35
AVRational
time_base
;
36
AVRational
pixel_aspect
;
37
}
BufferSourceContext
;
38
39
#define CHECK_PARAM_CHANGE(s, c, width, height, format)\
40
if (c->w != width || c->h != height || c->pix_fmt != format) {\
41
av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
42
return AVERROR(EINVAL);\
43
}
44
45
int
av_vsrc_buffer_add_frame
(
AVFilterContext
*buffer_filter,
AVFrame
*frame,
46
int64_t pts,
AVRational
pixel_aspect
)
47
{
48
BufferSourceContext
*c = buffer_filter->
priv
;
49
50
if
(c->
buf
) {
51
av_log
(buffer_filter,
AV_LOG_ERROR
,
52
"Buffering several frames is not supported. "
53
"Please consume all available frames before adding a new one.\n"
54
);
55
//return -1;
56
}
57
58
CHECK_PARAM_CHANGE
(buffer_filter, c, frame->
width
, frame->
height
, frame->
format
);
59
60
c->
buf
=
avfilter_get_video_buffer
(buffer_filter->
outputs
[0],
AV_PERM_WRITE
,
61
c->
w
, c->
h
);
62
av_image_copy
(c->
buf
->
data
, c->
buf
->
linesize
, frame->
data
, frame->
linesize
,
63
c->
pix_fmt
, c->
w
, c->
h
);
64
65
avfilter_copy_frame_props
(c->
buf
, frame);
66
c->
buf
->
pts
= pts;
67
c->
buf
->
video
->
pixel_aspect
=
pixel_aspect
;
68
69
return
0;
70
}
71
72
int
av_buffersrc_buffer
(
AVFilterContext
*s,
AVFilterBufferRef
*buf)
73
{
74
BufferSourceContext
*c = s->
priv
;
75
76
if
(c->
buf
) {
77
av_log
(s,
AV_LOG_ERROR
,
78
"Buffering several frames is not supported. "
79
"Please consume all available frames before adding a new one.\n"
80
);
81
return
AVERROR
(EINVAL);
82
}
83
84
CHECK_PARAM_CHANGE
(s, c, buf->
video
->
w
, buf->
video
->
h
, buf->
format
);
85
86
c->
buf
= buf;
87
88
return
0;
89
}
90
91
static
av_cold
int
init
(
AVFilterContext
*ctx,
const
char
*args,
void
*opaque)
92
{
93
BufferSourceContext
*c = ctx->
priv
;
94
char
pix_fmt_str[128];
95
int
n = 0;
96
97
if
(!args ||
98
(n = sscanf(args,
"%d:%d:%127[^:]:%d:%d:%d:%d"
, &c->
w
, &c->
h
, pix_fmt_str,
99
&c->
time_base
.
num
, &c->
time_base
.
den
,
100
&c->
pixel_aspect
.
num
, &c->
pixel_aspect
.
den
)) != 7) {
101
av_log
(ctx,
AV_LOG_ERROR
,
"Expected 7 arguments, but %d found in '%s'\n"
, n, args);
102
return
AVERROR
(EINVAL);
103
}
104
if
((c->
pix_fmt
=
av_get_pix_fmt
(pix_fmt_str)) ==
PIX_FMT_NONE
) {
105
char
*tail;
106
c->
pix_fmt
= strtol(pix_fmt_str, &tail, 10);
107
if
(*tail || c->
pix_fmt
< 0 || c->
pix_fmt
>=
PIX_FMT_NB
) {
108
av_log
(ctx,
AV_LOG_ERROR
,
"Invalid pixel format string '%s'\n"
, pix_fmt_str);
109
return
AVERROR
(EINVAL);
110
}
111
}
112
113
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
);
114
return
0;
115
}
116
117
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
118
{
119
BufferSourceContext
*s = ctx->
priv
;
120
if
(s->
buf
)
121
avfilter_unref_buffer
(s->
buf
);
122
s->
buf
=
NULL
;
123
}
124
125
static
int
query_formats
(
AVFilterContext
*ctx)
126
{
127
BufferSourceContext
*c = ctx->
priv
;
128
enum
PixelFormat
pix_fmts[] = { c->
pix_fmt
,
PIX_FMT_NONE
};
129
130
avfilter_set_common_formats
(ctx,
avfilter_make_format_list
(pix_fmts));
131
return
0;
132
}
133
134
static
int
config_props
(
AVFilterLink
*link)
135
{
136
BufferSourceContext
*c = link->
src
->
priv
;
137
138
link->
w
= c->
w
;
139
link->
h
= c->
h
;
140
link->
sample_aspect_ratio
= c->
pixel_aspect
;
141
link->
time_base
= c->
time_base
;
142
143
return
0;
144
}
145
146
static
int
request_frame
(
AVFilterLink
*link)
147
{
148
BufferSourceContext
*c = link->
src
->
priv
;
149
150
if
(!c->
buf
) {
151
av_log
(link->
src
,
AV_LOG_ERROR
,
152
"request_frame() called with no available frame!\n"
);
153
//return -1;
154
}
155
156
avfilter_start_frame
(link,
avfilter_ref_buffer
(c->
buf
, ~0));
157
avfilter_draw_slice
(link, 0, link->
h
, 1);
158
avfilter_end_frame
(link);
159
avfilter_unref_buffer
(c->
buf
);
160
c->
buf
=
NULL
;
161
162
return
0;
163
}
164
165
static
int
poll_frame
(
AVFilterLink
*link)
166
{
167
BufferSourceContext
*c = link->
src
->
priv
;
168
return
!!c->
buf
;
169
}
170
171
AVFilter
avfilter_vsrc_buffer
= {
172
.
name
=
"buffer"
,
173
.description =
NULL_IF_CONFIG_SMALL
(
"Buffer video frames, and make them accessible to the filterchain."
),
174
.priv_size =
sizeof
(
BufferSourceContext
),
175
.
query_formats
=
query_formats
,
176
177
.
init
=
init
,
178
.
uninit
=
uninit
,
179
180
.inputs = (
AVFilterPad
[]) {{ .name =
NULL
}},
181
.outputs = (
AVFilterPad
[]) {{ .name =
"default"
,
182
.type =
AVMEDIA_TYPE_VIDEO
,
183
.request_frame =
request_frame
,
184
.poll_frame =
poll_frame
,
185
.config_props =
config_props
, },
186
{ .name =
NULL
}},
187
};