]> git.sesse.net Git - ffmpeg/blob - libavfilter/defaults.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavfilter / defaults.c
1 /*
2  * Filter layer - default implementations
3  * Copyright (c) 2007 Bobby Bingham
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 "libavutil/avassert.h"
23 #include "libavutil/audioconvert.h"
24 #include "libavutil/imgutils.h"
25 #include "libavutil/samplefmt.h"
26 #include "avfilter.h"
27 #include "internal.h"
28
29 void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
30 {
31     av_free(ptr->data[0]);
32     av_free(ptr);
33 }
34
35 /* TODO: set the buffer's priv member to a context structure for the whole
36  * filter chain.  This will allow for a buffer pool instead of the constant
37  * alloc & free cycle currently implemented. */
38 AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
39 {
40     int linesize[4];
41     uint8_t *data[4];
42     int i;
43     AVFilterBufferRef *picref = NULL;
44     AVFilterPool *pool = link->pool;
45
46     if (pool) {
47         for (i = 0; i < POOL_SIZE; i++) {
48             picref = pool->pic[i];
49             if (picref && picref->buf->format == link->format && picref->buf->w == w && picref->buf->h == h) {
50                 AVFilterBuffer *pic = picref->buf;
51                 pool->pic[i] = NULL;
52                 pool->count--;
53                 picref->video->w = w;
54                 picref->video->h = h;
55                 picref->perms = perms | AV_PERM_READ;
56                 picref->format = link->format;
57                 pic->refcount = 1;
58                 memcpy(picref->data,     pic->data,     sizeof(picref->data));
59                 memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
60                 pool->refcount++;
61                 return picref;
62             }
63         }
64     } else {
65         pool = link->pool = av_mallocz(sizeof(AVFilterPool));
66         pool->refcount = 1;
67     }
68
69     // align: +2 is needed for swscaler, +16 to be SIMD-friendly
70     if ((i = av_image_alloc(data, linesize, w, h, link->format, 32)) < 0)
71         return NULL;
72
73     picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize,
74                                                        perms, w, h, link->format);
75     if (!picref) {
76         av_free(data[0]);
77         return NULL;
78     }
79     memset(data[0], 128, i);
80
81     picref->buf->priv = pool;
82     picref->buf->free = NULL;
83     pool->refcount++;
84
85     return picref;
86 }
87
88 AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms,
89                                                      int nb_samples)
90 {
91     AVFilterBufferRef *samplesref = NULL;
92     int linesize[8] = {0};
93     uint8_t *data[8] = {0};
94     int ch, nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
95
96     /* right now we don't support more than 8 channels */
97     av_assert0(nb_channels <= 8);
98
99     /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */
100     if (av_samples_alloc(data, linesize,
101                          nb_channels, nb_samples,
102                          av_get_alt_sample_fmt(link->format, link->planar),
103                          16) < 0)
104         return NULL;
105
106     for (ch = 1; link->planar && ch < nb_channels; ch++)
107         linesize[ch] = linesize[0];
108     samplesref =
109         avfilter_get_audio_buffer_ref_from_arrays(data, linesize, perms,
110                                                   nb_samples, link->format,
111                                                   link->channel_layout, link->planar);
112     if (!samplesref) {
113         av_free(data[0]);
114         return NULL;
115     }
116
117     return samplesref;
118 }
119
120 void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
121 {
122     AVFilterLink *outlink = NULL;
123
124     if (inlink->dst->output_count)
125         outlink = inlink->dst->outputs[0];
126
127     if (outlink) {
128         outlink->out_buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
129         avfilter_copy_buffer_ref_props(outlink->out_buf, picref);
130         avfilter_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
131     }
132 }
133
134 void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
135 {
136     AVFilterLink *outlink = NULL;
137
138     if (inlink->dst->output_count)
139         outlink = inlink->dst->outputs[0];
140
141     if (outlink)
142         avfilter_draw_slice(outlink, y, h, slice_dir);
143 }
144
145 void avfilter_default_end_frame(AVFilterLink *inlink)
146 {
147     AVFilterLink *outlink = NULL;
148
149     if (inlink->dst->output_count)
150         outlink = inlink->dst->outputs[0];
151
152     avfilter_unref_buffer(inlink->cur_buf);
153     inlink->cur_buf = NULL;
154
155     if (outlink) {
156         if (outlink->out_buf) {
157             avfilter_unref_buffer(outlink->out_buf);
158             outlink->out_buf = NULL;
159         }
160         avfilter_end_frame(outlink);
161     }
162 }
163
164 /* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */
165 void avfilter_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
166 {
167     AVFilterLink *outlink = NULL;
168
169     if (inlink->dst->output_count)
170         outlink = inlink->dst->outputs[0];
171
172     if (outlink) {
173         outlink->out_buf = avfilter_default_get_audio_buffer(inlink, AV_PERM_WRITE,
174                                                              samplesref->audio->nb_samples);
175         outlink->out_buf->pts                = samplesref->pts;
176         outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate;
177         avfilter_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
178         avfilter_unref_buffer(outlink->out_buf);
179         outlink->out_buf = NULL;
180     }
181     avfilter_unref_buffer(samplesref);
182     inlink->cur_buf = NULL;
183 }
184
185 static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts,
186                                enum AVMediaType type, int offin, int offout)
187 {
188     int i;
189     for (i = 0; i < ctx->input_count; i++)
190         if (ctx->inputs[i] && ctx->inputs[i]->type == type)
191             avfilter_formats_ref(fmts,
192                                  (AVFilterFormats **)((uint8_t *)ctx->inputs[i]+offout));
193
194     for (i = 0; i < ctx->output_count; i++)
195         if (ctx->outputs[i] && ctx->outputs[i]->type == type)
196             avfilter_formats_ref(fmts,
197                                  (AVFilterFormats **)((uint8_t *)ctx->outputs[i]+offin));
198
199     if (!fmts->refcount) {
200         av_free(fmts->formats);
201         av_free(fmts->refs);
202         av_free(fmts);
203     }
204 }
205
206 void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats)
207 {
208     set_common_formats(ctx, formats, AVMEDIA_TYPE_VIDEO,
209                        offsetof(AVFilterLink, in_formats),
210                        offsetof(AVFilterLink, out_formats));
211 }
212
213 void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats)
214 {
215     set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
216                        offsetof(AVFilterLink, in_formats),
217                        offsetof(AVFilterLink, out_formats));
218 }
219
220 void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats)
221 {
222     set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
223                        offsetof(AVFilterLink, in_chlayouts),
224                        offsetof(AVFilterLink, out_chlayouts));
225 }
226
227 void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats)
228 {
229     set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
230                        offsetof(AVFilterLink, in_packing),
231                        offsetof(AVFilterLink, out_packing));
232 }
233
234 int avfilter_default_query_formats(AVFilterContext *ctx)
235 {
236     avfilter_set_common_pixel_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_VIDEO));
237     avfilter_set_common_sample_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO));
238     avfilter_set_common_channel_layouts(ctx, avfilter_make_all_channel_layouts());
239     avfilter_set_common_packing_formats(ctx, avfilter_make_all_packing_formats());
240
241     return 0;
242 }
243
244 void avfilter_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
245 {
246     avfilter_start_frame(link->dst->outputs[0], picref);
247 }
248
249 void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
250 {
251     avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir);
252 }
253
254 void avfilter_null_end_frame(AVFilterLink *link)
255 {
256     avfilter_end_frame(link->dst->outputs[0]);
257 }
258
259 void avfilter_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
260 {
261     avfilter_filter_samples(link->dst->outputs[0], samplesref);
262 }
263
264 AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
265 {
266     return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h);
267 }
268
269 AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link, int perms,
270                                                   int nb_samples)
271 {
272     return avfilter_get_audio_buffer(link->dst->outputs[0], perms, nb_samples);
273 }