| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Filter layer - default implementations | 2 * Filter layer - default implementations |
| 3 * copyright (c) 2007 Bobby Bingham | 3 * copyright (c) 2007 Bobby Bingham |
| 4 * | 4 * |
| 5 * This file is part of FFmpeg. | 5 * This file is part of FFmpeg. |
| 6 * | 6 * |
| 7 * FFmpeg is free software; you can redistribute it and/or | 7 * FFmpeg is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Lesser General Public | 8 * modify it under the terms of the GNU Lesser General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2.1 of the License, or (at your option) any later version. | 10 * version 2.1 of the License, or (at your option) any later version. |
| 11 * | 11 * |
| 12 * FFmpeg is distributed in the hope that it will be useful, | 12 * FFmpeg is distributed in the hope that it will be useful, |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 * Lesser General Public License for more details. | 15 * Lesser General Public License for more details. |
| 16 * | 16 * |
| 17 * You should have received a copy of the GNU Lesser General Public | 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 | 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 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 */ | 20 */ |
| 21 | 21 |
| 22 #include "libavcore/imgutils.h" | 22 #include "libavcore/imgutils.h" |
| 23 #include "libavcodec/audioconvert.h" |
| 23 #include "avfilter.h" | 24 #include "avfilter.h" |
| 24 | 25 |
| 25 /* TODO: buffer pool. see comment for avfilter_default_get_video_buffer() */ | 26 /* TODO: buffer pool. see comment for avfilter_default_get_video_buffer() */ |
| 26 static void avfilter_default_free_buffer(AVFilterBuffer *ptr) | 27 static void avfilter_default_free_buffer(AVFilterBuffer *ptr) |
| 27 { | 28 { |
| 28 av_free(ptr->data[0]); | 29 av_free(ptr->data[0]); |
| 29 av_free(ptr); | 30 av_free(ptr); |
| 30 } | 31 } |
| 31 | 32 |
| 32 /* TODO: set the buffer's priv member to a context structure for the whole | 33 /* TODO: set the buffer's priv member to a context structure for the whole |
| 33 * filter chain. This will allow for a buffer pool instead of the constant | 34 * filter chain. This will allow for a buffer pool instead of the constant |
| 34 * alloc & free cycle currently implemented. */ | 35 * alloc & free cycle currently implemented. */ |
| 35 AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per
ms, int w, int h) | 36 AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per
ms, int w, int h) |
| 36 { | 37 { |
| 37 AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer)); | 38 AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer)); |
| 38 AVFilterBufferRef *ref = av_mallocz(sizeof(AVFilterBufferRef)); | 39 AVFilterBufferRef *ref = NULL; |
| 39 int i, tempsize; | 40 int i, tempsize; |
| 40 char *buf; | 41 char *buf = NULL; |
| 41 | 42 |
| 42 ref->buf = pic; | 43 if (!pic || !(ref = av_mallocz(sizeof(AVFilterBufferRef)))) |
| 43 ref->w = w; | 44 goto fail; |
| 44 ref->h = h; | 45 |
| 46 ref->buf = pic; |
| 47 ref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps)); |
| 48 ref->video->w = w; |
| 49 ref->video->h = h; |
| 45 | 50 |
| 46 /* make sure the buffer gets read permission or it's useless for output */ | 51 /* make sure the buffer gets read permission or it's useless for output */ |
| 47 ref->perms = perms | AV_PERM_READ; | 52 ref->perms = perms | AV_PERM_READ; |
| 48 | 53 |
| 49 pic->refcount = 1; | 54 pic->refcount = 1; |
| 50 ref->format = link->format; | 55 ref->format = link->format; |
| 51 pic->free = avfilter_default_free_buffer; | 56 pic->free = avfilter_default_free_buffer; |
| 52 av_fill_image_linesizes(pic->linesize, ref->format, ref->w); | 57 av_image_fill_linesizes(pic->linesize, ref->format, ref->video->w); |
| 53 | 58 |
| 54 for (i=0; i<4;i++) | 59 for (i = 0; i < 4; i++) |
| 55 pic->linesize[i] = FFALIGN(pic->linesize[i], 16); | 60 pic->linesize[i] = FFALIGN(pic->linesize[i], 16); |
| 56 | 61 |
| 57 tempsize = av_fill_image_pointers(pic->data, ref->format, ref->h, NULL, pic-
>linesize); | 62 tempsize = av_image_fill_pointers(pic->data, ref->format, ref->video->h, NUL
L, pic->linesize); |
| 58 buf = av_malloc(tempsize + 16); // +2 is needed for swscaler, +16 to be | 63 buf = av_malloc(tempsize + 16); // +2 is needed for swscaler, +16 to be |
| 59 // SIMD-friendly | 64 // SIMD-friendly |
| 60 av_fill_image_pointers(pic->data, ref->format, ref->h, buf, pic->linesize); | 65 if (!buf) |
| 66 goto fail; |
| 67 av_image_fill_pointers(pic->data, ref->format, ref->video->h, buf, pic->line
size); |
| 61 | 68 |
| 62 memcpy(ref->data, pic->data, 4*sizeof(pic->data[0])); | 69 memcpy(ref->data, pic->data, sizeof(ref->data)); |
| 63 memcpy(ref->linesize, pic->linesize, 4*sizeof(pic->linesize[0])); | 70 memcpy(ref->linesize, pic->linesize, sizeof(ref->linesize)); |
| 64 | 71 |
| 65 return ref; | 72 return ref; |
| 73 |
| 74 fail: |
| 75 av_free(buf); |
| 76 if (ref && ref->video) |
| 77 av_free(ref->video); |
| 78 av_free(ref); |
| 79 av_free(pic); |
| 80 return NULL; |
| 81 } |
| 82 |
| 83 AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int per
ms, |
| 84 enum SampleFormat sample_fm
t, int size, |
| 85 int64_t channel_layout, int
planar) |
| 86 { |
| 87 AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer)); |
| 88 AVFilterBufferRef *ref = NULL; |
| 89 int i, sample_size, chans_nb, bufsize, per_channel_size, step_size = 0; |
| 90 char *buf; |
| 91 |
| 92 if (!samples || !(ref = av_mallocz(sizeof(AVFilterBufferRef)))) |
| 93 goto fail; |
| 94 |
| 95 ref->buf = samples; |
| 96 ref->format = sample_fmt; |
| 97 |
| 98 ref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps)); |
| 99 if (!ref->audio) |
| 100 goto fail; |
| 101 |
| 102 ref->audio->channel_layout = channel_layout; |
| 103 ref->audio->size = size; |
| 104 ref->audio->planar = planar; |
| 105 |
| 106 /* make sure the buffer gets read permission or it's useless for output */ |
| 107 ref->perms = perms | AV_PERM_READ; |
| 108 |
| 109 samples->refcount = 1; |
| 110 samples->free = avfilter_default_free_buffer; |
| 111 |
| 112 sample_size = av_get_bits_per_sample_format(sample_fmt) >>3; |
| 113 chans_nb = avcodec_channel_layout_num_channels(channel_layout); |
| 114 |
| 115 per_channel_size = size/chans_nb; |
| 116 ref->audio->samples_nb = per_channel_size/sample_size; |
| 117 |
| 118 /* Set the number of bytes to traverse to reach next sample of a particular
channel: |
| 119 * For planar, this is simply the sample size. |
| 120 * For packed, this is the number of samples * sample_size. |
| 121 */ |
| 122 for (i = 0; i < chans_nb; i++) |
| 123 samples->linesize[i] = planar > 0 ? per_channel_size : sample_size; |
| 124 memset(&samples->linesize[chans_nb], 0, (8-chans_nb) * sizeof(samples->lines
ize[0])); |
| 125 |
| 126 /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly
*/ |
| 127 bufsize = (size + 15)&~15; |
| 128 buf = av_malloc(bufsize); |
| 129 if (!buf) |
| 130 goto fail; |
| 131 |
| 132 /* For planar, set the start point of each channel's data within the buffer |
| 133 * For packed, set the start point of the entire buffer only |
| 134 */ |
| 135 samples->data[0] = buf; |
| 136 if (buf && planar) { |
| 137 for (i = 1; i < chans_nb; i++) { |
| 138 step_size += per_channel_size; |
| 139 samples->data[i] = buf + step_size; |
| 140 } |
| 141 } else { |
| 142 for (i = 1; i < chans_nb; i++) |
| 143 samples->data[i] = buf; |
| 144 } |
| 145 |
| 146 memset(&samples->data[chans_nb], 0, (8-chans_nb) * sizeof(samples->data[0]))
; |
| 147 |
| 148 memcpy(ref->data, samples->data, sizeof(ref->data)); |
| 149 memcpy(ref->linesize, samples->linesize, sizeof(ref->linesize)); |
| 150 |
| 151 return ref; |
| 152 |
| 153 fail: |
| 154 av_free(buf); |
| 155 if (ref && ref->audio) |
| 156 av_free(ref->audio); |
| 157 av_free(ref); |
| 158 av_free(samples); |
| 159 return NULL; |
| 66 } | 160 } |
| 67 | 161 |
| 68 void avfilter_default_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | 162 void avfilter_default_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) |
| 69 { | 163 { |
| 70 AVFilterLink *out = NULL; | 164 AVFilterLink *out = NULL; |
| 71 | 165 |
| 72 if(link->dst->output_count) | 166 if (link->dst->output_count) |
| 73 out = link->dst->outputs[0]; | 167 out = link->dst->outputs[0]; |
| 74 | 168 |
| 75 if(out) { | 169 if (out) { |
| 76 out->out_buf = avfilter_get_video_buffer(out, AV_PERM_WRITE, out->w
, out->h); | 170 out->out_buf = avfilter_get_video_buffer(out, AV_PERM_WRITE, out->w
, out->h); |
| 77 avfilter_copy_buffer_ref_props(out->out_buf, picref); | 171 avfilter_copy_buffer_ref_props(out->out_buf, picref); |
| 78 avfilter_start_frame(out, avfilter_ref_buffer(out->out_buf, ~0)); | 172 avfilter_start_frame(out, avfilter_ref_buffer(out->out_buf, ~0)); |
| 79 } | 173 } |
| 80 } | 174 } |
| 81 | 175 |
| 82 void avfilter_default_draw_slice(AVFilterLink *link, int y, int h, int slice_dir
) | 176 void avfilter_default_draw_slice(AVFilterLink *link, int y, int h, int slice_dir
) |
| 83 { | 177 { |
| 84 AVFilterLink *out = NULL; | 178 AVFilterLink *out = NULL; |
| 85 | 179 |
| 86 if(link->dst->output_count) | 180 if (link->dst->output_count) |
| 87 out = link->dst->outputs[0]; | 181 out = link->dst->outputs[0]; |
| 88 | 182 |
| 89 if(out) | 183 if (out) |
| 90 avfilter_draw_slice(out, y, h, slice_dir); | 184 avfilter_draw_slice(out, y, h, slice_dir); |
| 91 } | 185 } |
| 92 | 186 |
| 93 void avfilter_default_end_frame(AVFilterLink *link) | 187 void avfilter_default_end_frame(AVFilterLink *link) |
| 94 { | 188 { |
| 95 AVFilterLink *out = NULL; | 189 AVFilterLink *out = NULL; |
| 96 | 190 |
| 97 if(link->dst->output_count) | 191 if (link->dst->output_count) |
| 98 out = link->dst->outputs[0]; | 192 out = link->dst->outputs[0]; |
| 99 | 193 |
| 100 avfilter_unref_buffer(link->cur_buf); | 194 avfilter_unref_buffer(link->cur_buf); |
| 101 link->cur_buf = NULL; | 195 link->cur_buf = NULL; |
| 102 | 196 |
| 103 if(out) { | 197 if (out) { |
| 104 if(out->out_buf) { | 198 if (out->out_buf) { |
| 105 avfilter_unref_buffer(out->out_buf); | 199 avfilter_unref_buffer(out->out_buf); |
| 106 out->out_buf = NULL; | 200 out->out_buf = NULL; |
| 107 } | 201 } |
| 108 avfilter_end_frame(out); | 202 avfilter_end_frame(out); |
| 109 } | 203 } |
| 110 } | 204 } |
| 111 | 205 |
| 206 /* FIXME: samplesref is same as link->cur_buf. Need to consider removing the red
undant parameter. */ |
| 207 void avfilter_default_filter_samples(AVFilterLink *link, AVFilterBufferRef *samp
lesref) |
| 208 { |
| 209 AVFilterLink *outlink = NULL; |
| 210 |
| 211 if (link->dst->output_count) |
| 212 outlink = link->dst->outputs[0]; |
| 213 |
| 214 if (outlink) { |
| 215 outlink->out_buf = avfilter_default_get_audio_buffer(link, AV_PERM_WRITE
, samplesref->format, |
| 216 samplesref->audio->
size, |
| 217 samplesref->audio->
channel_layout, |
| 218 samplesref->audio->
planar); |
| 219 outlink->out_buf->pts = samplesref->pts; |
| 220 outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate; |
| 221 avfilter_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~
0)); |
| 222 avfilter_unref_buffer(outlink->out_buf); |
| 223 outlink->out_buf = NULL; |
| 224 } |
| 225 avfilter_unref_buffer(samplesref); |
| 226 link->cur_buf = NULL; |
| 227 } |
| 228 |
| 112 /** | 229 /** |
| 113 * default config_link() implementation for output video links to simplify | 230 * default config_link() implementation for output video links to simplify |
| 114 * the implementation of one input one output video filters */ | 231 * the implementation of one input one output video filters */ |
| 115 int avfilter_default_config_output_link(AVFilterLink *link) | 232 int avfilter_default_config_output_link(AVFilterLink *link) |
| 116 { | 233 { |
| 117 if(link->src->input_count && link->src->inputs[0]) { | 234 if (link->src->input_count && link->src->inputs[0]) { |
| 118 link->w = link->src->inputs[0]->w; | 235 if (link->type == AVMEDIA_TYPE_VIDEO) { |
| 119 link->h = link->src->inputs[0]->h; | 236 link->w = link->src->inputs[0]->w; |
| 237 link->h = link->src->inputs[0]->h; |
| 238 } else if (link->type == AVMEDIA_TYPE_AUDIO) { |
| 239 link->channel_layout = link->src->inputs[0]->channel_layout; |
| 240 link->sample_rate = link->src->inputs[0]->sample_rate; |
| 241 } |
| 120 } else { | 242 } else { |
| 121 /* XXX: any non-simple filter which would cause this branch to be taken | 243 /* XXX: any non-simple filter which would cause this branch to be taken |
| 122 * really should implement its own config_props() for this link. */ | 244 * really should implement its own config_props() for this link. */ |
| 123 return -1; | 245 return -1; |
| 124 } | 246 } |
| 125 | 247 |
| 126 return 0; | 248 return 0; |
| 127 } | 249 } |
| 128 | 250 |
| 129 /** | 251 /** |
| 130 * A helper for query_formats() which sets all links to the same list of | 252 * A helper for query_formats() which sets all links to the same list of |
| 131 * formats. If there are no links hooked to this filter, the list of formats is | 253 * formats. If there are no links hooked to this filter, the list of formats is |
| 132 * freed. | 254 * freed. |
| 133 * | 255 * |
| 134 * FIXME: this will need changed for filters with a mix of pad types | 256 * FIXME: this will need changed for filters with a mix of pad types |
| 135 * (video + audio, etc) | 257 * (video + audio, etc) |
| 136 */ | 258 */ |
| 137 void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats) | 259 void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats) |
| 138 { | 260 { |
| 139 int count = 0, i; | 261 int count = 0, i; |
| 140 | 262 |
| 141 for(i = 0; i < ctx->input_count; i ++) { | 263 for (i = 0; i < ctx->input_count; i++) { |
| 142 if(ctx->inputs[i]) { | 264 if (ctx->inputs[i]) { |
| 143 avfilter_formats_ref(formats, &ctx->inputs[i]->out_formats); | 265 avfilter_formats_ref(formats, &ctx->inputs[i]->out_formats); |
| 144 count ++; | 266 count++; |
| 145 } | 267 } |
| 146 } | 268 } |
| 147 for(i = 0; i < ctx->output_count; i ++) { | 269 for (i = 0; i < ctx->output_count; i++) { |
| 148 if(ctx->outputs[i]) { | 270 if (ctx->outputs[i]) { |
| 149 avfilter_formats_ref(formats, &ctx->outputs[i]->in_formats); | 271 avfilter_formats_ref(formats, &ctx->outputs[i]->in_formats); |
| 150 count ++; | 272 count++; |
| 151 } | 273 } |
| 152 } | 274 } |
| 153 | 275 |
| 154 if(!count) { | 276 if (!count) { |
| 155 av_free(formats->formats); | 277 av_free(formats->formats); |
| 156 av_free(formats->refs); | 278 av_free(formats->refs); |
| 157 av_free(formats); | 279 av_free(formats); |
| 158 } | 280 } |
| 159 } | 281 } |
| 160 | 282 |
| 161 int avfilter_default_query_formats(AVFilterContext *ctx) | 283 int avfilter_default_query_formats(AVFilterContext *ctx) |
| 162 { | 284 { |
| 163 enum AVMediaType type = ctx->inputs [0] ? ctx->inputs [0]->type : | 285 enum AVMediaType type = ctx->inputs [0] ? ctx->inputs [0]->type : |
| 164 ctx->outputs[0] ? ctx->outputs[0]->type : | 286 ctx->outputs[0] ? ctx->outputs[0]->type : |
| (...skipping 11 matching lines...) Expand all Loading... |
| 176 void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | 298 void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) |
| 177 { | 299 { |
| 178 avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir); | 300 avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir); |
| 179 } | 301 } |
| 180 | 302 |
| 181 void avfilter_null_end_frame(AVFilterLink *link) | 303 void avfilter_null_end_frame(AVFilterLink *link) |
| 182 { | 304 { |
| 183 avfilter_end_frame(link->dst->outputs[0]); | 305 avfilter_end_frame(link->dst->outputs[0]); |
| 184 } | 306 } |
| 185 | 307 |
| 308 void avfilter_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samples
ref) |
| 309 { |
| 310 avfilter_filter_samples(link->dst->outputs[0], samplesref); |
| 311 } |
| 312 |
| 186 AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms,
int w, int h) | 313 AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms,
int w, int h) |
| 187 { | 314 { |
| 188 return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h); | 315 return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h); |
| 189 } | 316 } |
| 190 | 317 |
| 318 AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link, int perms, |
| 319 enum SampleFormat sample_fmt,
int size, |
| 320 int64_t channel_layout, int pa
cked) |
| 321 { |
| 322 return avfilter_get_audio_buffer(link->dst->outputs[0], perms, sample_fmt, |
| 323 size, channel_layout, packed); |
| 324 } |
| 325 |
| OLD | NEW |