| OLD | NEW |
| 1 /* | 1 /* |
| 2 * filter layer | 2 * filter layer |
| 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 /* #define DEBUG */ | 22 /* #define DEBUG */ |
| 23 | 23 |
| 24 #include "libavcodec/imgconvert.h" | 24 #include "libavcodec/audioconvert.c" |
| 25 #include "libavutil/pixdesc.h" | 25 #include "libavutil/pixdesc.h" |
| 26 #include "libavcore/imgutils.h" |
| 26 #include "avfilter.h" | 27 #include "avfilter.h" |
| 27 #include "internal.h" | 28 #include "internal.h" |
| 28 | 29 |
| 29 unsigned avfilter_version(void) { | 30 unsigned avfilter_version(void) { |
| 30 return LIBAVFILTER_VERSION_INT; | 31 return LIBAVFILTER_VERSION_INT; |
| 31 } | 32 } |
| 32 | 33 |
| 33 const char *avfilter_configuration(void) | 34 const char *avfilter_configuration(void) |
| 34 { | 35 { |
| 35 return FFMPEG_CONFIGURATION; | 36 return FFMPEG_CONFIGURATION; |
| 36 } | 37 } |
| 37 | 38 |
| 38 const char *avfilter_license(void) | 39 const char *avfilter_license(void) |
| 39 { | 40 { |
| 40 #define LICENSE_PREFIX "libavfilter license: " | 41 #define LICENSE_PREFIX "libavfilter license: " |
| 41 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; | 42 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; |
| 42 } | 43 } |
| 43 | 44 |
| 44 /** helper macros to get the in/out pad on the dst/src filter */ | 45 /** helper macros to get the in/out pad on the dst/src filter */ |
| 45 #define link_dpad(link) link->dst-> input_pads[link->dstpad] | 46 #define link_dpad(link) link->dst-> input_pads[link->dstpad] |
| 46 #define link_spad(link) link->src->output_pads[link->srcpad] | 47 #define link_spad(link) link->src->output_pads[link->srcpad] |
| 47 | 48 |
| 48 AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) | 49 AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) |
| 49 { | 50 { |
| 50 AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef)); | 51 AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef)); |
| 52 if (!ret) |
| 53 return NULL; |
| 51 *ret = *ref; | 54 *ret = *ref; |
| 55 if (ref->type == AVMEDIA_TYPE_VIDEO) { |
| 56 ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps)); |
| 57 if (!ret->video) { |
| 58 av_free(ret); |
| 59 return NULL; |
| 60 } |
| 61 *ret->video = *ref->video; |
| 62 } else if (ref->type == AVMEDIA_TYPE_AUDIO) { |
| 63 ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps)); |
| 64 if (!ret->audio) { |
| 65 av_free(ret); |
| 66 return NULL; |
| 67 } |
| 68 *ret->audio = *ref->audio; |
| 69 } |
| 52 ret->perms &= pmask; | 70 ret->perms &= pmask; |
| 53 ret->buf->refcount ++; | 71 ret->buf->refcount ++; |
| 54 return ret; | 72 return ret; |
| 55 } | 73 } |
| 56 | 74 |
| 57 void avfilter_unref_buffer(AVFilterBufferRef *ref) | 75 void avfilter_unref_buffer(AVFilterBufferRef *ref) |
| 58 { | 76 { |
| 59 if(!(--ref->buf->refcount)) | 77 if (!(--ref->buf->refcount)) |
| 60 ref->buf->free(ref->buf); | 78 ref->buf->free(ref->buf); |
| 79 av_free(ref->video); |
| 80 av_free(ref->audio); |
| 61 av_free(ref); | 81 av_free(ref); |
| 62 } | 82 } |
| 63 | 83 |
| 64 void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, | 84 void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, |
| 65 AVFilterPad **pads, AVFilterLink ***links, | 85 AVFilterPad **pads, AVFilterLink ***links, |
| 66 AVFilterPad *newpad) | 86 AVFilterPad *newpad) |
| 67 { | 87 { |
| 68 unsigned i; | 88 unsigned i; |
| 69 | 89 |
| 70 idx = FFMIN(idx, *count); | 90 idx = FFMIN(idx, *count); |
| 71 | 91 |
| 72 *pads = av_realloc(*pads, sizeof(AVFilterPad) * (*count + 1)); | 92 *pads = av_realloc(*pads, sizeof(AVFilterPad) * (*count + 1)); |
| 73 *links = av_realloc(*links, sizeof(AVFilterLink*) * (*count + 1)); | 93 *links = av_realloc(*links, sizeof(AVFilterLink*) * (*count + 1)); |
| 74 memmove(*pads +idx+1, *pads +idx, sizeof(AVFilterPad) * (*count-idx)); | 94 memmove(*pads +idx+1, *pads +idx, sizeof(AVFilterPad) * (*count-idx)); |
| 75 memmove(*links+idx+1, *links+idx, sizeof(AVFilterLink*) * (*count-idx)); | 95 memmove(*links+idx+1, *links+idx, sizeof(AVFilterLink*) * (*count-idx)); |
| 76 memcpy(*pads+idx, newpad, sizeof(AVFilterPad)); | 96 memcpy(*pads+idx, newpad, sizeof(AVFilterPad)); |
| 77 (*links)[idx] = NULL; | 97 (*links)[idx] = NULL; |
| 78 | 98 |
| 79 (*count) ++; | 99 (*count)++; |
| 80 for(i = idx+1; i < *count; i ++) | 100 for (i = idx+1; i < *count; i++) |
| 81 if(*links[i]) | 101 if (*links[i]) |
| 82 (*(unsigned *)((uint8_t *) *links[i] + padidx_off)) ++; | 102 (*(unsigned *)((uint8_t *) *links[i] + padidx_off))++; |
| 83 } | 103 } |
| 84 | 104 |
| 85 int avfilter_link(AVFilterContext *src, unsigned srcpad, | 105 int avfilter_link(AVFilterContext *src, unsigned srcpad, |
| 86 AVFilterContext *dst, unsigned dstpad) | 106 AVFilterContext *dst, unsigned dstpad) |
| 87 { | 107 { |
| 88 AVFilterLink *link; | 108 AVFilterLink *link; |
| 89 | 109 |
| 90 if(src->output_count <= srcpad || dst->input_count <= dstpad || | 110 if (src->output_count <= srcpad || dst->input_count <= dstpad || |
| 91 src->outputs[srcpad] || dst->inputs[dstpad]) | 111 src->outputs[srcpad] || dst->inputs[dstpad]) |
| 92 return -1; | 112 return -1; |
| 93 | 113 |
| 94 src->outputs[srcpad] = | 114 src->outputs[srcpad] = |
| 95 dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); | 115 dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); |
| 96 | 116 |
| 97 link->src = src; | 117 link->src = src; |
| 98 link->dst = dst; | 118 link->dst = dst; |
| 99 link->srcpad = srcpad; | 119 link->srcpad = srcpad; |
| 100 link->dstpad = dstpad; | 120 link->dstpad = dstpad; |
| 101 link->type = src->output_pads[srcpad].type; | 121 link->type = src->output_pads[srcpad].type; |
| 102 assert(PIX_FMT_NONE == -1 && SAMPLE_FMT_NONE == -1); | 122 assert(PIX_FMT_NONE == -1 && SAMPLE_FMT_NONE == -1); |
| 103 link->format = -1; | 123 link->format = -1; |
| 104 | 124 |
| 105 return 0; | 125 return 0; |
| 106 } | 126 } |
| 107 | 127 |
| 108 int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, | 128 int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, |
| 109 unsigned in, unsigned out) | 129 unsigned in, unsigned out) |
| 110 { | 130 { |
| 111 av_log(link->dst, AV_LOG_INFO, "auto-inserting filter '%s' " | 131 av_log(link->dst, AV_LOG_INFO, "auto-inserting filter '%s' " |
| 112 "between the filter '%s' and the filter '%s'\n", | 132 "between the filter '%s' and the filter '%s'\n", |
| 113 filt->name, link->src->name, link->dst->name); | 133 filt->name, link->src->name, link->dst->name); |
| 114 | 134 |
| 115 link->dst->inputs[link->dstpad] = NULL; | 135 link->dst->inputs[link->dstpad] = NULL; |
| 116 if(avfilter_link(filt, out, link->dst, link->dstpad)) { | 136 if (avfilter_link(filt, out, link->dst, link->dstpad)) { |
| 117 /* failed to link output filter to new filter */ | 137 /* failed to link output filter to new filter */ |
| 118 link->dst->inputs[link->dstpad] = link; | 138 link->dst->inputs[link->dstpad] = link; |
| 119 return -1; | 139 return -1; |
| 120 } | 140 } |
| 121 | 141 |
| 122 /* re-hookup the link to the new destination filter we inserted */ | 142 /* re-hookup the link to the new destination filter we inserted */ |
| 123 link->dst = filt; | 143 link->dst = filt; |
| 124 link->dstpad = in; | 144 link->dstpad = in; |
| 125 filt->inputs[in] = link; | 145 filt->inputs[in] = link; |
| 126 | 146 |
| 127 /* if any information on supported media formats already exists on the | 147 /* if any information on supported media formats already exists on the |
| 128 * link, we need to preserve that */ | 148 * link, we need to preserve that */ |
| 129 if(link->out_formats) | 149 if (link->out_formats) |
| 130 avfilter_formats_changeref(&link->out_formats, | 150 avfilter_formats_changeref(&link->out_formats, |
| 131 &filt->outputs[out]->out_formats); | 151 &filt->outputs[out]->out_formats); |
| 132 | 152 |
| 133 return 0; | 153 return 0; |
| 134 } | 154 } |
| 135 | 155 |
| 136 int avfilter_config_links(AVFilterContext *filter) | 156 int avfilter_config_links(AVFilterContext *filter) |
| 137 { | 157 { |
| 138 int (*config_link)(AVFilterLink *); | 158 int (*config_link)(AVFilterLink *); |
| 139 unsigned i; | 159 unsigned i; |
| 140 | 160 |
| 141 for(i = 0; i < filter->input_count; i ++) { | 161 for (i = 0; i < filter->input_count; i ++) { |
| 142 AVFilterLink *link = filter->inputs[i]; | 162 AVFilterLink *link = filter->inputs[i]; |
| 143 | 163 |
| 144 if(!link) continue; | 164 if (!link) continue; |
| 145 | 165 |
| 146 switch(link->init_state) { | 166 switch (link->init_state) { |
| 147 case AVLINK_INIT: | 167 case AVLINK_INIT: |
| 148 continue; | 168 continue; |
| 149 case AVLINK_STARTINIT: | 169 case AVLINK_STARTINIT: |
| 150 av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); | 170 av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); |
| 151 return 0; | 171 return 0; |
| 152 case AVLINK_UNINIT: | 172 case AVLINK_UNINIT: |
| 153 link->init_state = AVLINK_STARTINIT; | 173 link->init_state = AVLINK_STARTINIT; |
| 154 | 174 |
| 155 if(avfilter_config_links(link->src)) | 175 if (avfilter_config_links(link->src)) |
| 156 return -1; | 176 return -1; |
| 157 | 177 |
| 158 if(!(config_link = link_spad(link).config_props)) | 178 if (!(config_link = link_spad(link).config_props)) |
| 159 config_link = avfilter_default_config_output_link; | 179 config_link = avfilter_default_config_output_link; |
| 160 if(config_link(link)) | 180 if (config_link(link)) |
| 161 return -1; | 181 return -1; |
| 162 | 182 |
| 163 if((config_link = link_dpad(link).config_props)) | 183 if ((config_link = link_dpad(link).config_props)) |
| 164 if(config_link(link)) | 184 if (config_link(link)) |
| 165 return -1; | 185 return -1; |
| 166 | 186 |
| 167 link->init_state = AVLINK_INIT; | 187 link->init_state = AVLINK_INIT; |
| 168 } | 188 } |
| 169 } | 189 } |
| 170 | 190 |
| 171 return 0; | 191 return 0; |
| 172 } | 192 } |
| 173 | 193 |
| 174 void ff_dprintf_picref(void *ctx, AVFilterBufferRef *picref, int end) | 194 char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms) |
| 175 { | 195 { |
| 196 snprintf(buf, buf_size, "%s%s%s%s%s", |
| 197 perms & AV_PERM_READ ? "r" : "", |
| 198 perms & AV_PERM_WRITE ? "w" : "", |
| 199 perms & AV_PERM_PRESERVE ? "p" : "", |
| 200 perms & AV_PERM_REUSE ? "r" : "", |
| 201 perms & AV_PERM_REUSE2 ? "R" : ""); |
| 202 return buf; |
| 203 } |
| 204 |
| 205 void ff_dprintf_ref(void *ctx, AVFilterBufferRef *ref, int end) |
| 206 { |
| 207 av_unused char buf[16]; |
| 176 dprintf(ctx, | 208 dprintf(ctx, |
| 177 "picref[%p data[%p, %p, %p, %p] linesize[%d, %d, %d, %d] pts:%"PRId6
4" pos:%"PRId64" a:%d/%d s:%dx%d]%s", | 209 "ref[%p buf:%p refcount:%d perms:%s data:%p linesize[%d, %d, %d, %d]
pts:%"PRId64" pos:%"PRId64, |
| 178 picref, | 210 ref, ref->buf, ref->buf->refcount, ff_get_ref_perms_string(buf, size
of(buf), ref->perms), ref->data[0], |
| 179 picref->data [0], picref->data [1], picref->data [2], picre
f->data [3], | 211 ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[
3], |
| 180 picref->linesize[0], picref->linesize[1], picref->linesize[2], picre
f->linesize[3], | 212 ref->pts, ref->pos); |
| 181 picref->pts, picref->pos, | 213 |
| 182 picref->pixel_aspect.num, picref->pixel_aspect.den, picref->w, picre
f->h, | 214 if (ref->video) { |
| 183 end ? "\n" : ""); | 215 dprintf(ctx, " a:%d/%d s:%dx%d i:%c", |
| 216 ref->video->pixel_aspect.num, ref->video->pixel_aspect.den, |
| 217 ref->video->w, ref->video->h, |
| 218 !ref->video->interlaced ? 'P' : /* Progressive */ |
| 219 ref->video->top_field_first ? 'T' : 'B'); /* Top / Bottom */ |
| 220 } |
| 221 if (ref->audio) { |
| 222 dprintf(ctx, " cl:%"PRId64"d sn:%d s:%d sr:%d p:%d", |
| 223 ref->audio->channel_layout, |
| 224 ref->audio->samples_nb, |
| 225 ref->audio->size, |
| 226 ref->audio->sample_rate, |
| 227 ref->audio->planar); |
| 228 } |
| 229 |
| 230 dprintf(ctx, "]%s", end ? "\n" : ""); |
| 184 } | 231 } |
| 185 | 232 |
| 186 void ff_dprintf_link(void *ctx, AVFilterLink *link, int end) | 233 void ff_dprintf_link(void *ctx, AVFilterLink *link, int end) |
| 187 { | 234 { |
| 188 dprintf(ctx, | 235 dprintf(ctx, |
| 189 "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s", | 236 "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s", |
| 190 link, link->w, link->h, | 237 link, link->w, link->h, |
| 191 av_pix_fmt_descriptors[link->format].name, | 238 av_pix_fmt_descriptors[link->format].name, |
| 192 link->src ? link->src->filter->name : "", | 239 link->src ? link->src->filter->name : "", |
| 193 link->dst ? link->dst->filter->name : "", | 240 link->dst ? link->dst->filter->name : "", |
| 194 end ? "\n" : ""); | 241 end ? "\n" : ""); |
| 195 } | 242 } |
| 196 | 243 |
| 197 AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int
w, int h) | 244 AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int
w, int h) |
| 198 { | 245 { |
| 199 AVFilterBufferRef *ret = NULL; | 246 AVFilterBufferRef *ret = NULL; |
| 200 | 247 |
| 201 FF_DPRINTF_START(NULL, get_video_buffer); ff_dprintf_link(NULL, link, 0); dp
rintf(NULL, " perms:%d w:%d h:%d\n", perms, w, h); | 248 av_unused char buf[16]; |
| 249 FF_DPRINTF_START(NULL, get_video_buffer); ff_dprintf_link(NULL, link, 0); |
| 250 dprintf(NULL, " perms:%s w:%d h:%d\n", ff_get_ref_perms_string(buf, sizeof(b
uf), perms), w, h); |
| 202 | 251 |
| 203 if(link_dpad(link).get_video_buffer) | 252 if (link_dpad(link).get_video_buffer) |
| 204 ret = link_dpad(link).get_video_buffer(link, perms, w, h); | 253 ret = link_dpad(link).get_video_buffer(link, perms, w, h); |
| 205 | 254 |
| 206 if(!ret) | 255 if (!ret) |
| 207 ret = avfilter_default_get_video_buffer(link, perms, w, h); | 256 ret = avfilter_default_get_video_buffer(link, perms, w, h); |
| 208 | 257 |
| 209 FF_DPRINTF_START(NULL, get_video_buffer); ff_dprintf_link(NULL, link, 0); dp
rintf(NULL, " returning "); ff_dprintf_picref(NULL, ret, 1); | 258 if (ret) |
| 259 ret->type = AVMEDIA_TYPE_VIDEO; |
| 260 |
| 261 FF_DPRINTF_START(NULL, get_video_buffer); ff_dprintf_link(NULL, link, 0); dp
rintf(NULL, " returning "); ff_dprintf_ref(NULL, ret, 1); |
| 262 |
| 263 return ret; |
| 264 } |
| 265 |
| 266 AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, |
| 267 enum SampleFormat sample_fmt, int s
ize, |
| 268 int64_t channel_layout, int planar) |
| 269 { |
| 270 AVFilterBufferRef *ret = NULL; |
| 271 |
| 272 if (link_dpad(link).get_audio_buffer) |
| 273 ret = link_dpad(link).get_audio_buffer(link, perms, sample_fmt, size, ch
annel_layout, planar); |
| 274 |
| 275 if (!ret) |
| 276 ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, size, c
hannel_layout, planar); |
| 277 |
| 278 if (ret) |
| 279 ret->type = AVMEDIA_TYPE_AUDIO; |
| 210 | 280 |
| 211 return ret; | 281 return ret; |
| 212 } | 282 } |
| 213 | 283 |
| 214 int avfilter_request_frame(AVFilterLink *link) | 284 int avfilter_request_frame(AVFilterLink *link) |
| 215 { | 285 { |
| 216 FF_DPRINTF_START(NULL, request_frame); ff_dprintf_link(NULL, link, 1); | 286 FF_DPRINTF_START(NULL, request_frame); ff_dprintf_link(NULL, link, 1); |
| 217 | 287 |
| 218 if(link_spad(link).request_frame) | 288 if (link_spad(link).request_frame) |
| 219 return link_spad(link).request_frame(link); | 289 return link_spad(link).request_frame(link); |
| 220 else if(link->src->inputs[0]) | 290 else if (link->src->inputs[0]) |
| 221 return avfilter_request_frame(link->src->inputs[0]); | 291 return avfilter_request_frame(link->src->inputs[0]); |
| 222 else return -1; | 292 else return -1; |
| 223 } | 293 } |
| 224 | 294 |
| 225 int avfilter_poll_frame(AVFilterLink *link) | 295 int avfilter_poll_frame(AVFilterLink *link) |
| 226 { | 296 { |
| 227 int i, min=INT_MAX; | 297 int i, min = INT_MAX; |
| 228 | 298 |
| 229 if(link_spad(link).poll_frame) | 299 if (link_spad(link).poll_frame) |
| 230 return link_spad(link).poll_frame(link); | 300 return link_spad(link).poll_frame(link); |
| 231 | 301 |
| 232 for (i=0; i<link->src->input_count; i++) { | 302 for (i = 0; i < link->src->input_count; i++) { |
| 233 int val; | 303 int val; |
| 234 if(!link->src->inputs[i]) | 304 if (!link->src->inputs[i]) |
| 235 return -1; | 305 return -1; |
| 236 val = avfilter_poll_frame(link->src->inputs[i]); | 306 val = avfilter_poll_frame(link->src->inputs[i]); |
| 237 min = FFMIN(min, val); | 307 min = FFMIN(min, val); |
| 238 } | 308 } |
| 239 | 309 |
| 240 return min; | 310 return min; |
| 241 } | 311 } |
| 242 | 312 |
| 243 /* XXX: should we do the duplicating of the picture ref here, instead of | 313 /* XXX: should we do the duplicating of the picture ref here, instead of |
| 244 * forcing the source filter to do it? */ | 314 * forcing the source filter to do it? */ |
| 245 void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | 315 void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) |
| 246 { | 316 { |
| 247 void (*start_frame)(AVFilterLink *, AVFilterBufferRef *); | 317 void (*start_frame)(AVFilterLink *, AVFilterBufferRef *); |
| 248 AVFilterPad *dst = &link_dpad(link); | 318 AVFilterPad *dst = &link_dpad(link); |
| 249 | 319 |
| 250 FF_DPRINTF_START(NULL, start_frame); ff_dprintf_link(NULL, link, 0); dprintf
(NULL, " "); ff_dprintf_picref(NULL, picref, 1); | 320 FF_DPRINTF_START(NULL, start_frame); ff_dprintf_link(NULL, link, 0); dprintf
(NULL, " "); ff_dprintf_ref(NULL, picref, 1); |
| 251 | 321 |
| 252 if(!(start_frame = dst->start_frame)) | 322 if (!(start_frame = dst->start_frame)) |
| 253 start_frame = avfilter_default_start_frame; | 323 start_frame = avfilter_default_start_frame; |
| 254 | 324 |
| 255 /* prepare to copy the picture if it has insufficient permissions */ | 325 /* prepare to copy the picture if it has insufficient permissions */ |
| 256 if((dst->min_perms & picref->perms) != dst->min_perms || | 326 if ((dst->min_perms & picref->perms) != dst->min_perms || |
| 257 dst->rej_perms & picref->perms) { | 327 dst->rej_perms & picref->perms) { |
| 258 /* | 328 av_log(link->dst, AV_LOG_DEBUG, |
| 259 av_log(link->dst, AV_LOG_INFO, | |
| 260 "frame copy needed (have perms %x, need %x, reject %x)\n", | 329 "frame copy needed (have perms %x, need %x, reject %x)\n", |
| 261 picref->perms, | 330 picref->perms, |
| 262 link_dpad(link).min_perms, link_dpad(link).rej_perms); | 331 link_dpad(link).min_perms, link_dpad(link).rej_perms); |
| 263 */ | |
| 264 | 332 |
| 265 link->cur_buf = avfilter_default_get_video_buffer(link, dst->min_perms,
link->w, link->h); | 333 link->cur_buf = avfilter_get_video_buffer(link, dst->min_perms, link->w,
link->h); |
| 266 link->src_buf = picref; | 334 link->src_buf = picref; |
| 267 avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf); | 335 avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf); |
| 268 } | 336 } |
| 269 else | 337 else |
| 270 link->cur_buf = picref; | 338 link->cur_buf = picref; |
| 271 | 339 |
| 272 start_frame(link, link->cur_buf); | 340 start_frame(link, link->cur_buf); |
| 273 } | 341 } |
| 274 | 342 |
| 275 void avfilter_end_frame(AVFilterLink *link) | 343 void avfilter_end_frame(AVFilterLink *link) |
| 276 { | 344 { |
| 277 void (*end_frame)(AVFilterLink *); | 345 void (*end_frame)(AVFilterLink *); |
| 278 | 346 |
| 279 if(!(end_frame = link_dpad(link).end_frame)) | 347 if (!(end_frame = link_dpad(link).end_frame)) |
| 280 end_frame = avfilter_default_end_frame; | 348 end_frame = avfilter_default_end_frame; |
| 281 | 349 |
| 282 end_frame(link); | 350 end_frame(link); |
| 283 | 351 |
| 284 /* unreference the source picture if we're feeding the destination filter | 352 /* unreference the source picture if we're feeding the destination filter |
| 285 * a copied version dues to permission issues */ | 353 * a copied version dues to permission issues */ |
| 286 if(link->src_buf) { | 354 if (link->src_buf) { |
| 287 avfilter_unref_buffer(link->src_buf); | 355 avfilter_unref_buffer(link->src_buf); |
| 288 link->src_buf = NULL; | 356 link->src_buf = NULL; |
| 289 } | 357 } |
| 290 | |
| 291 } | 358 } |
| 292 | 359 |
| 293 void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | 360 void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) |
| 294 { | 361 { |
| 295 uint8_t *src[4], *dst[4]; | 362 uint8_t *src[4], *dst[4]; |
| 296 int i, j, vsub; | 363 int i, j, vsub; |
| 297 void (*draw_slice)(AVFilterLink *, int, int, int); | 364 void (*draw_slice)(AVFilterLink *, int, int, int); |
| 298 | 365 |
| 299 FF_DPRINTF_START(NULL, draw_slice); ff_dprintf_link(NULL, link, 0); dprintf(
NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir); | 366 FF_DPRINTF_START(NULL, draw_slice); ff_dprintf_link(NULL, link, 0); dprintf(
NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir); |
| 300 | 367 |
| 301 /* copy the slice if needed for permission reasons */ | 368 /* copy the slice if needed for permission reasons */ |
| 302 if(link->src_buf) { | 369 if (link->src_buf) { |
| 303 vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h; | 370 vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h; |
| 304 | 371 |
| 305 for(i = 0; i < 4; i ++) { | 372 for (i = 0; i < 4; i++) { |
| 306 if(link->src_buf->data[i]) { | 373 if (link->src_buf->data[i]) { |
| 307 src[i] = link->src_buf-> data[i] + | 374 src[i] = link->src_buf-> data[i] + |
| 308 (y >> (i==0 ? 0 : vsub)) * link->src_buf-> linesize[i]; | 375 (y >> (i==0 ? 0 : vsub)) * link->src_buf-> linesize[i]; |
| 309 dst[i] = link->cur_buf->data[i] + | 376 dst[i] = link->cur_buf->data[i] + |
| 310 (y >> (i==0 ? 0 : vsub)) * link->cur_buf->linesize[i]; | 377 (y >> (i==0 ? 0 : vsub)) * link->cur_buf->linesize[i]; |
| 311 } else | 378 } else |
| 312 src[i] = dst[i] = NULL; | 379 src[i] = dst[i] = NULL; |
| 313 } | 380 } |
| 314 | 381 |
| 315 for(i = 0; i < 4; i ++) { | 382 for (i = 0; i < 4; i++) { |
| 316 int planew = | 383 int planew = |
| 317 ff_get_plane_bytewidth(link->format, link->cur_buf->w, i); | 384 av_image_get_linesize(link->format, link->cur_buf->video->w, i); |
| 318 | 385 |
| 319 if(!src[i]) continue; | 386 if (!src[i]) continue; |
| 320 | 387 |
| 321 for(j = 0; j < h >> (i==0 ? 0 : vsub); j ++) { | 388 for (j = 0; j < h >> (i==0 ? 0 : vsub); j++) { |
| 322 memcpy(dst[i], src[i], planew); | 389 memcpy(dst[i], src[i], planew); |
| 323 src[i] += link->src_buf ->linesize[i]; | 390 src[i] += link->src_buf->linesize[i]; |
| 324 dst[i] += link->cur_buf->linesize[i]; | 391 dst[i] += link->cur_buf->linesize[i]; |
| 325 } | 392 } |
| 326 } | 393 } |
| 327 } | 394 } |
| 328 | 395 |
| 329 if(!(draw_slice = link_dpad(link).draw_slice)) | 396 if (!(draw_slice = link_dpad(link).draw_slice)) |
| 330 draw_slice = avfilter_default_draw_slice; | 397 draw_slice = avfilter_default_draw_slice; |
| 331 draw_slice(link, y, h, slice_dir); | 398 draw_slice(link, y, h, slice_dir); |
| 332 } | 399 } |
| 333 | 400 |
| 401 void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) |
| 402 { |
| 403 void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); |
| 404 AVFilterPad *dst = &link_dpad(link); |
| 405 |
| 406 if (!(filter_samples = dst->filter_samples)) |
| 407 filter_samples = avfilter_default_filter_samples; |
| 408 |
| 409 /* prepare to copy the samples if the buffer has insufficient permissions */ |
| 410 if ((dst->min_perms & samplesref->perms) != dst->min_perms || |
| 411 dst->rej_perms & samplesref->perms) { |
| 412 |
| 413 av_log(link->dst, AV_LOG_DEBUG, |
| 414 "Copying audio data in avfilter (have perms %x, need %x, reject %
x)\n", |
| 415 samplesref->perms, link_dpad(link).min_perms, link_dpad(link).rej
_perms); |
| 416 |
| 417 link->cur_buf = avfilter_default_get_audio_buffer(link, dst->min_perms, |
| 418 samplesref->format, |
| 419 samplesref->audio->siz
e, |
| 420 samplesref->audio->cha
nnel_layout, |
| 421 samplesref->audio->pla
nar); |
| 422 link->cur_buf->pts = samplesref->pts; |
| 423 link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate; |
| 424 |
| 425 /* Copy actual data into new samples buffer */ |
| 426 memcpy(link->cur_buf->data[0], samplesref->data[0], samplesref->audio->s
ize); |
| 427 |
| 428 avfilter_unref_buffer(samplesref); |
| 429 } else |
| 430 link->cur_buf = samplesref; |
| 431 |
| 432 filter_samples(link, link->cur_buf); |
| 433 } |
| 434 |
| 334 #define MAX_REGISTERED_AVFILTERS_NB 64 | 435 #define MAX_REGISTERED_AVFILTERS_NB 64 |
| 335 | 436 |
| 336 static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1]; | 437 static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1]; |
| 337 | 438 |
| 338 static int next_registered_avfilter_idx = 0; | 439 static int next_registered_avfilter_idx = 0; |
| 339 | 440 |
| 340 AVFilter *avfilter_get_by_name(const char *name) | 441 AVFilter *avfilter_get_by_name(const char *name) |
| 341 { | 442 { |
| 342 int i; | 443 int i; |
| 343 | 444 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 return filter->filter->name; | 483 return filter->filter->name; |
| 383 } | 484 } |
| 384 | 485 |
| 385 static const AVClass avfilter_class = { | 486 static const AVClass avfilter_class = { |
| 386 "AVFilter", | 487 "AVFilter", |
| 387 filter_name, | 488 filter_name, |
| 388 NULL, | 489 NULL, |
| 389 LIBAVUTIL_VERSION_INT, | 490 LIBAVUTIL_VERSION_INT, |
| 390 }; | 491 }; |
| 391 | 492 |
| 392 AVFilterContext *avfilter_open(AVFilter *filter, const char *inst_name) | 493 int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *in
st_name) |
| 393 { | 494 { |
| 394 AVFilterContext *ret; | 495 AVFilterContext *ret; |
| 496 *filter_ctx = NULL; |
| 395 | 497 |
| 396 if (!filter) | 498 if (!filter) |
| 397 return 0; | 499 return AVERROR(EINVAL); |
| 398 | 500 |
| 399 ret = av_mallocz(sizeof(AVFilterContext)); | 501 ret = av_mallocz(sizeof(AVFilterContext)); |
| 400 | 502 |
| 401 ret->av_class = &avfilter_class; | 503 ret->av_class = &avfilter_class; |
| 402 ret->filter = filter; | 504 ret->filter = filter; |
| 403 ret->name = inst_name ? av_strdup(inst_name) : NULL; | 505 ret->name = inst_name ? av_strdup(inst_name) : NULL; |
| 404 ret->priv = av_mallocz(filter->priv_size); | 506 ret->priv = av_mallocz(filter->priv_size); |
| 405 | 507 |
| 406 ret->input_count = pad_count(filter->inputs); | 508 ret->input_count = pad_count(filter->inputs); |
| 407 if (ret->input_count) { | 509 if (ret->input_count) { |
| 408 ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->input_count); | 510 ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->input_count); |
| 409 memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->input
_count); | 511 memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->input
_count); |
| 410 ret->inputs = av_mallocz(sizeof(AVFilterLink*) * ret->input_count)
; | 512 ret->inputs = av_mallocz(sizeof(AVFilterLink*) * ret->input_count)
; |
| 411 } | 513 } |
| 412 | 514 |
| 413 ret->output_count = pad_count(filter->outputs); | 515 ret->output_count = pad_count(filter->outputs); |
| 414 if (ret->output_count) { | 516 if (ret->output_count) { |
| 415 ret->output_pads = av_malloc(sizeof(AVFilterPad) * ret->output_count); | 517 ret->output_pads = av_malloc(sizeof(AVFilterPad) * ret->output_count); |
| 416 memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->out
put_count); | 518 memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->out
put_count); |
| 417 ret->outputs = av_mallocz(sizeof(AVFilterLink*) * ret->output_count
); | 519 ret->outputs = av_mallocz(sizeof(AVFilterLink*) * ret->output_count
); |
| 418 } | 520 } |
| 419 | 521 |
| 420 return ret; | 522 *filter_ctx = ret; |
| 523 return 0; |
| 421 } | 524 } |
| 422 | 525 |
| 423 void avfilter_destroy(AVFilterContext *filter) | 526 void avfilter_destroy(AVFilterContext *filter) |
| 424 { | 527 { |
| 425 int i; | 528 int i; |
| 426 | 529 |
| 427 if(filter->filter->uninit) | 530 if (filter->filter->uninit) |
| 428 filter->filter->uninit(filter); | 531 filter->filter->uninit(filter); |
| 429 | 532 |
| 430 for(i = 0; i < filter->input_count; i ++) { | 533 for (i = 0; i < filter->input_count; i++) { |
| 431 if(filter->inputs[i]) { | 534 if (filter->inputs[i]) { |
| 432 if (filter->inputs[i]->src) | 535 if (filter->inputs[i]->src) |
| 433 filter->inputs[i]->src->outputs[filter->inputs[i]->srcpad] = NUL
L; | 536 filter->inputs[i]->src->outputs[filter->inputs[i]->srcpad] = NUL
L; |
| 434 avfilter_formats_unref(&filter->inputs[i]->in_formats); | 537 avfilter_formats_unref(&filter->inputs[i]->in_formats); |
| 435 avfilter_formats_unref(&filter->inputs[i]->out_formats); | 538 avfilter_formats_unref(&filter->inputs[i]->out_formats); |
| 436 } | 539 } |
| 437 av_freep(&filter->inputs[i]); | 540 av_freep(&filter->inputs[i]); |
| 438 } | 541 } |
| 439 for(i = 0; i < filter->output_count; i ++) { | 542 for (i = 0; i < filter->output_count; i++) { |
| 440 if(filter->outputs[i]) { | 543 if (filter->outputs[i]) { |
| 441 if (filter->outputs[i]->dst) | 544 if (filter->outputs[i]->dst) |
| 442 filter->outputs[i]->dst->inputs[filter->outputs[i]->dstpad] = NU
LL; | 545 filter->outputs[i]->dst->inputs[filter->outputs[i]->dstpad] = NU
LL; |
| 443 avfilter_formats_unref(&filter->outputs[i]->in_formats); | 546 avfilter_formats_unref(&filter->outputs[i]->in_formats); |
| 444 avfilter_formats_unref(&filter->outputs[i]->out_formats); | 547 avfilter_formats_unref(&filter->outputs[i]->out_formats); |
| 445 } | 548 } |
| 446 av_freep(&filter->outputs[i]); | 549 av_freep(&filter->outputs[i]); |
| 447 } | 550 } |
| 448 | 551 |
| 449 av_freep(&filter->name); | 552 av_freep(&filter->name); |
| 450 av_freep(&filter->input_pads); | 553 av_freep(&filter->input_pads); |
| 451 av_freep(&filter->output_pads); | 554 av_freep(&filter->output_pads); |
| 452 av_freep(&filter->inputs); | 555 av_freep(&filter->inputs); |
| 453 av_freep(&filter->outputs); | 556 av_freep(&filter->outputs); |
| 454 av_freep(&filter->priv); | 557 av_freep(&filter->priv); |
| 455 av_free(filter); | 558 av_free(filter); |
| 456 } | 559 } |
| 457 | 560 |
| 458 int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
) | 561 int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
) |
| 459 { | 562 { |
| 460 int ret=0; | 563 int ret=0; |
| 461 | 564 |
| 462 if(filter->filter->init) | 565 if (filter->filter->init) |
| 463 ret = filter->filter->init(filter, args, opaque); | 566 ret = filter->filter->init(filter, args, opaque); |
| 464 return ret; | 567 return ret; |
| 465 } | 568 } |
| 466 | 569 |
| OLD | NEW |