Libav 0.7.1
|
00001 /* 00002 * filter layer 00003 * Copyright (c) 2007 Bobby Bingham 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 /* #define DEBUG */ 00023 00024 #include "libavutil/pixdesc.h" 00025 #include "libavutil/rational.h" 00026 #include "libavutil/audioconvert.h" 00027 #include "libavutil/imgutils.h" 00028 #include "avfilter.h" 00029 #include "internal.h" 00030 00031 unsigned avfilter_version(void) { 00032 return LIBAVFILTER_VERSION_INT; 00033 } 00034 00035 const char *avfilter_configuration(void) 00036 { 00037 return LIBAV_CONFIGURATION; 00038 } 00039 00040 const char *avfilter_license(void) 00041 { 00042 #define LICENSE_PREFIX "libavfilter license: " 00043 return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; 00044 } 00045 00046 AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) 00047 { 00048 AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef)); 00049 if (!ret) 00050 return NULL; 00051 *ret = *ref; 00052 if (ref->type == AVMEDIA_TYPE_VIDEO) { 00053 ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps)); 00054 if (!ret->video) { 00055 av_free(ret); 00056 return NULL; 00057 } 00058 *ret->video = *ref->video; 00059 } else if (ref->type == AVMEDIA_TYPE_AUDIO) { 00060 ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps)); 00061 if (!ret->audio) { 00062 av_free(ret); 00063 return NULL; 00064 } 00065 *ret->audio = *ref->audio; 00066 } 00067 ret->perms &= pmask; 00068 ret->buf->refcount ++; 00069 return ret; 00070 } 00071 00072 void avfilter_unref_buffer(AVFilterBufferRef *ref) 00073 { 00074 if (!ref) 00075 return; 00076 if (!(--ref->buf->refcount)) 00077 ref->buf->free(ref->buf); 00078 av_free(ref->video); 00079 av_free(ref->audio); 00080 av_free(ref); 00081 } 00082 00083 void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, 00084 AVFilterPad **pads, AVFilterLink ***links, 00085 AVFilterPad *newpad) 00086 { 00087 unsigned i; 00088 00089 idx = FFMIN(idx, *count); 00090 00091 *pads = av_realloc(*pads, sizeof(AVFilterPad) * (*count + 1)); 00092 *links = av_realloc(*links, sizeof(AVFilterLink*) * (*count + 1)); 00093 memmove(*pads +idx+1, *pads +idx, sizeof(AVFilterPad) * (*count-idx)); 00094 memmove(*links+idx+1, *links+idx, sizeof(AVFilterLink*) * (*count-idx)); 00095 memcpy(*pads+idx, newpad, sizeof(AVFilterPad)); 00096 (*links)[idx] = NULL; 00097 00098 (*count)++; 00099 for (i = idx+1; i < *count; i++) 00100 if (*links[i]) 00101 (*(unsigned *)((uint8_t *) *links[i] + padidx_off))++; 00102 } 00103 00104 int avfilter_link(AVFilterContext *src, unsigned srcpad, 00105 AVFilterContext *dst, unsigned dstpad) 00106 { 00107 AVFilterLink *link; 00108 00109 if (src->output_count <= srcpad || dst->input_count <= dstpad || 00110 src->outputs[srcpad] || dst->inputs[dstpad]) 00111 return -1; 00112 00113 if (src->output_pads[srcpad].type != dst->input_pads[dstpad].type) { 00114 av_log(src, AV_LOG_ERROR, 00115 "Media type mismatch between the '%s' filter output pad %d and the '%s' filter input pad %d\n", 00116 src->name, srcpad, dst->name, dstpad); 00117 return AVERROR(EINVAL); 00118 } 00119 00120 src->outputs[srcpad] = 00121 dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); 00122 00123 link->src = src; 00124 link->dst = dst; 00125 link->srcpad = &src->output_pads[srcpad]; 00126 link->dstpad = &dst->input_pads[dstpad]; 00127 link->type = src->output_pads[srcpad].type; 00128 assert(PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1); 00129 link->format = -1; 00130 00131 return 0; 00132 } 00133 00134 int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, 00135 unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) 00136 { 00137 int ret; 00138 unsigned dstpad_idx = link->dstpad - link->dst->input_pads; 00139 00140 av_log(link->dst, AV_LOG_INFO, "auto-inserting filter '%s' " 00141 "between the filter '%s' and the filter '%s'\n", 00142 filt->name, link->src->name, link->dst->name); 00143 00144 link->dst->inputs[dstpad_idx] = NULL; 00145 if ((ret = avfilter_link(filt, filt_dstpad_idx, link->dst, dstpad_idx)) < 0) { 00146 /* failed to link output filter to new filter */ 00147 link->dst->inputs[dstpad_idx] = link; 00148 return ret; 00149 } 00150 00151 /* re-hookup the link to the new destination filter we inserted */ 00152 link->dst = filt; 00153 link->dstpad = &filt->input_pads[filt_srcpad_idx]; 00154 filt->inputs[filt_srcpad_idx] = link; 00155 00156 /* if any information on supported media formats already exists on the 00157 * link, we need to preserve that */ 00158 if (link->out_formats) 00159 avfilter_formats_changeref(&link->out_formats, 00160 &filt->outputs[filt_dstpad_idx]->out_formats); 00161 00162 return 0; 00163 } 00164 00165 int avfilter_config_links(AVFilterContext *filter) 00166 { 00167 int (*config_link)(AVFilterLink *); 00168 unsigned i; 00169 int ret; 00170 00171 for (i = 0; i < filter->input_count; i ++) { 00172 AVFilterLink *link = filter->inputs[i]; 00173 00174 if (!link) continue; 00175 00176 switch (link->init_state) { 00177 case AVLINK_INIT: 00178 continue; 00179 case AVLINK_STARTINIT: 00180 av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); 00181 return 0; 00182 case AVLINK_UNINIT: 00183 link->init_state = AVLINK_STARTINIT; 00184 00185 if ((ret = avfilter_config_links(link->src)) < 0) 00186 return ret; 00187 00188 if (!(config_link = link->srcpad->config_props)) 00189 config_link = avfilter_default_config_output_link; 00190 if ((ret = config_link(link)) < 0) 00191 return ret; 00192 00193 if (link->time_base.num == 0 && link->time_base.den == 0) 00194 link->time_base = link->src && link->src->input_count ? 00195 link->src->inputs[0]->time_base : AV_TIME_BASE_Q; 00196 00197 if (link->sample_aspect_ratio.num == 0 && link->sample_aspect_ratio.den == 0) 00198 link->sample_aspect_ratio = link->src->input_count ? 00199 link->src->inputs[0]->sample_aspect_ratio : (AVRational){1,1}; 00200 00201 if (link->sample_rate == 0 && link->src && link->src->input_count) 00202 link->sample_rate = link->src->inputs[0]->sample_rate; 00203 00204 if (link->channel_layout == 0 && link->src && link->src->input_count) 00205 link->channel_layout = link->src->inputs[0]->channel_layout; 00206 00207 if ((config_link = link->dstpad->config_props)) 00208 if ((ret = config_link(link)) < 0) 00209 return ret; 00210 00211 link->init_state = AVLINK_INIT; 00212 } 00213 } 00214 00215 return 0; 00216 } 00217 00218 #ifdef DEBUG 00219 static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms) 00220 { 00221 snprintf(buf, buf_size, "%s%s%s%s%s%s", 00222 perms & AV_PERM_READ ? "r" : "", 00223 perms & AV_PERM_WRITE ? "w" : "", 00224 perms & AV_PERM_PRESERVE ? "p" : "", 00225 perms & AV_PERM_REUSE ? "u" : "", 00226 perms & AV_PERM_REUSE2 ? "U" : "", 00227 perms & AV_PERM_NEG_LINESIZES ? "n" : ""); 00228 return buf; 00229 } 00230 #endif 00231 00232 static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) 00233 { 00234 av_unused char buf[16]; 00235 av_dlog(ctx, 00236 "ref[%p buf:%p refcount:%d perms:%s data:%p linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64, 00237 ref, ref->buf, ref->buf->refcount, ff_get_ref_perms_string(buf, sizeof(buf), ref->perms), ref->data[0], 00238 ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3], 00239 ref->pts, ref->pos); 00240 00241 if (ref->video) { 00242 av_dlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c", 00243 ref->video->pixel_aspect.num, ref->video->pixel_aspect.den, 00244 ref->video->w, ref->video->h, 00245 !ref->video->interlaced ? 'P' : /* Progressive */ 00246 ref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ 00247 ref->video->key_frame, 00248 av_get_picture_type_char(ref->video->pict_type)); 00249 } 00250 if (ref->audio) { 00251 av_dlog(ctx, " cl:%"PRId64"d sn:%d s:%d sr:%d p:%d", 00252 ref->audio->channel_layout, 00253 ref->audio->nb_samples, 00254 ref->audio->size, 00255 ref->audio->sample_rate, 00256 ref->audio->planar); 00257 } 00258 00259 av_dlog(ctx, "]%s", end ? "\n" : ""); 00260 } 00261 00262 static void ff_dlog_link(void *ctx, AVFilterLink *link, int end) 00263 { 00264 if (link->type == AVMEDIA_TYPE_VIDEO) { 00265 av_dlog(ctx, 00266 "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s", 00267 link, link->w, link->h, 00268 av_pix_fmt_descriptors[link->format].name, 00269 link->src ? link->src->filter->name : "", 00270 link->dst ? link->dst->filter->name : "", 00271 end ? "\n" : ""); 00272 } else { 00273 char buf[128]; 00274 av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout); 00275 00276 av_dlog(ctx, 00277 "link[%p r:%"PRId64" cl:%s fmt:%-16s %-16s->%-16s]%s", 00278 link, link->sample_rate, buf, 00279 av_get_sample_fmt_name(link->format), 00280 link->src ? link->src->filter->name : "", 00281 link->dst ? link->dst->filter->name : "", 00282 end ? "\n" : ""); 00283 } 00284 } 00285 00286 #define FF_DPRINTF_START(ctx, func) av_dlog(NULL, "%-16s: ", #func) 00287 00288 AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h) 00289 { 00290 AVFilterBufferRef *ret = NULL; 00291 00292 av_unused char buf[16]; 00293 FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0); 00294 av_dlog(NULL, " perms:%s w:%d h:%d\n", ff_get_ref_perms_string(buf, sizeof(buf), perms), w, h); 00295 00296 if (link->dstpad->get_video_buffer) 00297 ret = link->dstpad->get_video_buffer(link, perms, w, h); 00298 00299 if (!ret) 00300 ret = avfilter_default_get_video_buffer(link, perms, w, h); 00301 00302 if (ret) 00303 ret->type = AVMEDIA_TYPE_VIDEO; 00304 00305 FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " returning "); ff_dlog_ref(NULL, ret, 1); 00306 00307 return ret; 00308 } 00309 00310 AVFilterBufferRef * 00311 avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int perms, 00312 int w, int h, enum PixelFormat format) 00313 { 00314 AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer)); 00315 AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef)); 00316 00317 if (!pic || !picref) 00318 goto fail; 00319 00320 picref->buf = pic; 00321 picref->buf->free = ff_avfilter_default_free_buffer; 00322 if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps)))) 00323 goto fail; 00324 00325 pic->w = picref->video->w = w; 00326 pic->h = picref->video->h = h; 00327 00328 /* make sure the buffer gets read permission or it's useless for output */ 00329 picref->perms = perms | AV_PERM_READ; 00330 00331 pic->refcount = 1; 00332 picref->type = AVMEDIA_TYPE_VIDEO; 00333 pic->format = picref->format = format; 00334 00335 memcpy(pic->data, data, sizeof(pic->data)); 00336 memcpy(pic->linesize, linesize, sizeof(pic->linesize)); 00337 memcpy(picref->data, pic->data, sizeof(picref->data)); 00338 memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize)); 00339 00340 return picref; 00341 00342 fail: 00343 if (picref && picref->video) 00344 av_free(picref->video); 00345 av_free(picref); 00346 av_free(pic); 00347 return NULL; 00348 } 00349 00350 AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, 00351 enum AVSampleFormat sample_fmt, int size, 00352 int64_t channel_layout, int planar) 00353 { 00354 AVFilterBufferRef *ret = NULL; 00355 00356 if (link->dstpad->get_audio_buffer) 00357 ret = link->dstpad->get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); 00358 00359 if (!ret) 00360 ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); 00361 00362 if (ret) 00363 ret->type = AVMEDIA_TYPE_AUDIO; 00364 00365 return ret; 00366 } 00367 00368 int avfilter_request_frame(AVFilterLink *link) 00369 { 00370 FF_DPRINTF_START(NULL, request_frame); ff_dlog_link(NULL, link, 1); 00371 00372 if (link->srcpad->request_frame) 00373 return link->srcpad->request_frame(link); 00374 else if (link->src->inputs[0]) 00375 return avfilter_request_frame(link->src->inputs[0]); 00376 else return -1; 00377 } 00378 00379 int avfilter_poll_frame(AVFilterLink *link) 00380 { 00381 int i, min = INT_MAX; 00382 00383 if (link->srcpad->poll_frame) 00384 return link->srcpad->poll_frame(link); 00385 00386 for (i = 0; i < link->src->input_count; i++) { 00387 int val; 00388 if (!link->src->inputs[i]) 00389 return -1; 00390 val = avfilter_poll_frame(link->src->inputs[i]); 00391 min = FFMIN(min, val); 00392 } 00393 00394 return min; 00395 } 00396 00397 /* XXX: should we do the duplicating of the picture ref here, instead of 00398 * forcing the source filter to do it? */ 00399 void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) 00400 { 00401 void (*start_frame)(AVFilterLink *, AVFilterBufferRef *); 00402 AVFilterPad *dst = link->dstpad; 00403 int perms = picref->perms; 00404 00405 FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1); 00406 00407 if (!(start_frame = dst->start_frame)) 00408 start_frame = avfilter_default_start_frame; 00409 00410 if (picref->linesize[0] < 0) 00411 perms |= AV_PERM_NEG_LINESIZES; 00412 /* prepare to copy the picture if it has insufficient permissions */ 00413 if ((dst->min_perms & perms) != dst->min_perms || dst->rej_perms & perms) { 00414 av_log(link->dst, AV_LOG_DEBUG, 00415 "frame copy needed (have perms %x, need %x, reject %x)\n", 00416 picref->perms, 00417 link->dstpad->min_perms, link->dstpad->rej_perms); 00418 00419 link->cur_buf = avfilter_get_video_buffer(link, dst->min_perms, link->w, link->h); 00420 link->src_buf = picref; 00421 avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf); 00422 } 00423 else 00424 link->cur_buf = picref; 00425 00426 start_frame(link, link->cur_buf); 00427 } 00428 00429 void avfilter_end_frame(AVFilterLink *link) 00430 { 00431 void (*end_frame)(AVFilterLink *); 00432 00433 if (!(end_frame = link->dstpad->end_frame)) 00434 end_frame = avfilter_default_end_frame; 00435 00436 end_frame(link); 00437 00438 /* unreference the source picture if we're feeding the destination filter 00439 * a copied version dues to permission issues */ 00440 if (link->src_buf) { 00441 avfilter_unref_buffer(link->src_buf); 00442 link->src_buf = NULL; 00443 } 00444 } 00445 00446 void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) 00447 { 00448 uint8_t *src[4], *dst[4]; 00449 int i, j, vsub; 00450 void (*draw_slice)(AVFilterLink *, int, int, int); 00451 00452 FF_DPRINTF_START(NULL, draw_slice); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir); 00453 00454 /* copy the slice if needed for permission reasons */ 00455 if (link->src_buf) { 00456 vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h; 00457 00458 for (i = 0; i < 4; i++) { 00459 if (link->src_buf->data[i]) { 00460 src[i] = link->src_buf-> data[i] + 00461 (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i]; 00462 dst[i] = link->cur_buf->data[i] + 00463 (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i]; 00464 } else 00465 src[i] = dst[i] = NULL; 00466 } 00467 00468 for (i = 0; i < 4; i++) { 00469 int planew = 00470 av_image_get_linesize(link->format, link->cur_buf->video->w, i); 00471 00472 if (!src[i]) continue; 00473 00474 for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) { 00475 memcpy(dst[i], src[i], planew); 00476 src[i] += link->src_buf->linesize[i]; 00477 dst[i] += link->cur_buf->linesize[i]; 00478 } 00479 } 00480 } 00481 00482 if (!(draw_slice = link->dstpad->draw_slice)) 00483 draw_slice = avfilter_default_draw_slice; 00484 draw_slice(link, y, h, slice_dir); 00485 } 00486 00487 void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) 00488 { 00489 void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); 00490 AVFilterPad *dst = link->dstpad; 00491 00492 FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1); 00493 00494 if (!(filter_samples = dst->filter_samples)) 00495 filter_samples = avfilter_default_filter_samples; 00496 00497 /* prepare to copy the samples if the buffer has insufficient permissions */ 00498 if ((dst->min_perms & samplesref->perms) != dst->min_perms || 00499 dst->rej_perms & samplesref->perms) { 00500 00501 av_log(link->dst, AV_LOG_DEBUG, 00502 "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n", 00503 samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms); 00504 00505 link->cur_buf = avfilter_default_get_audio_buffer(link, dst->min_perms, 00506 samplesref->format, 00507 samplesref->audio->size, 00508 samplesref->audio->channel_layout, 00509 samplesref->audio->planar); 00510 link->cur_buf->pts = samplesref->pts; 00511 link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate; 00512 00513 /* Copy actual data into new samples buffer */ 00514 memcpy(link->cur_buf->data[0], samplesref->data[0], samplesref->audio->size); 00515 00516 avfilter_unref_buffer(samplesref); 00517 } else 00518 link->cur_buf = samplesref; 00519 00520 filter_samples(link, link->cur_buf); 00521 } 00522 00523 #define MAX_REGISTERED_AVFILTERS_NB 64 00524 00525 static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1]; 00526 00527 static int next_registered_avfilter_idx = 0; 00528 00529 AVFilter *avfilter_get_by_name(const char *name) 00530 { 00531 int i; 00532 00533 for (i = 0; registered_avfilters[i]; i++) 00534 if (!strcmp(registered_avfilters[i]->name, name)) 00535 return registered_avfilters[i]; 00536 00537 return NULL; 00538 } 00539 00540 int avfilter_register(AVFilter *filter) 00541 { 00542 if (next_registered_avfilter_idx == MAX_REGISTERED_AVFILTERS_NB) 00543 return -1; 00544 00545 registered_avfilters[next_registered_avfilter_idx++] = filter; 00546 return 0; 00547 } 00548 00549 AVFilter **av_filter_next(AVFilter **filter) 00550 { 00551 return filter ? ++filter : ®istered_avfilters[0]; 00552 } 00553 00554 void avfilter_uninit(void) 00555 { 00556 memset(registered_avfilters, 0, sizeof(registered_avfilters)); 00557 next_registered_avfilter_idx = 0; 00558 } 00559 00560 static int pad_count(const AVFilterPad *pads) 00561 { 00562 int count; 00563 00564 for(count = 0; pads->name; count ++) pads ++; 00565 return count; 00566 } 00567 00568 static const char *filter_name(void *p) 00569 { 00570 AVFilterContext *filter = p; 00571 return filter->filter->name; 00572 } 00573 00574 static const AVClass avfilter_class = { 00575 "AVFilter", 00576 filter_name, 00577 NULL, 00578 LIBAVUTIL_VERSION_INT, 00579 }; 00580 00581 int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name) 00582 { 00583 AVFilterContext *ret; 00584 *filter_ctx = NULL; 00585 00586 if (!filter) 00587 return AVERROR(EINVAL); 00588 00589 ret = av_mallocz(sizeof(AVFilterContext)); 00590 if (!ret) 00591 return AVERROR(ENOMEM); 00592 00593 ret->av_class = &avfilter_class; 00594 ret->filter = filter; 00595 ret->name = inst_name ? av_strdup(inst_name) : NULL; 00596 if (filter->priv_size) { 00597 ret->priv = av_mallocz(filter->priv_size); 00598 if (!ret->priv) 00599 goto err; 00600 } 00601 00602 ret->input_count = pad_count(filter->inputs); 00603 if (ret->input_count) { 00604 ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->input_count); 00605 if (!ret->input_pads) 00606 goto err; 00607 memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->input_count); 00608 ret->inputs = av_mallocz(sizeof(AVFilterLink*) * ret->input_count); 00609 if (!ret->inputs) 00610 goto err; 00611 } 00612 00613 ret->output_count = pad_count(filter->outputs); 00614 if (ret->output_count) { 00615 ret->output_pads = av_malloc(sizeof(AVFilterPad) * ret->output_count); 00616 if (!ret->output_pads) 00617 goto err; 00618 memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->output_count); 00619 ret->outputs = av_mallocz(sizeof(AVFilterLink*) * ret->output_count); 00620 if (!ret->outputs) 00621 goto err; 00622 } 00623 00624 *filter_ctx = ret; 00625 return 0; 00626 00627 err: 00628 av_freep(&ret->inputs); 00629 av_freep(&ret->input_pads); 00630 ret->input_count = 0; 00631 av_freep(&ret->outputs); 00632 av_freep(&ret->output_pads); 00633 ret->output_count = 0; 00634 av_freep(&ret->priv); 00635 av_free(ret); 00636 return AVERROR(ENOMEM); 00637 } 00638 00639 void avfilter_free(AVFilterContext *filter) 00640 { 00641 int i; 00642 AVFilterLink *link; 00643 00644 if (filter->filter->uninit) 00645 filter->filter->uninit(filter); 00646 00647 for (i = 0; i < filter->input_count; i++) { 00648 if ((link = filter->inputs[i])) { 00649 if (link->src) 00650 link->src->outputs[link->srcpad - link->src->output_pads] = NULL; 00651 avfilter_formats_unref(&link->in_formats); 00652 avfilter_formats_unref(&link->out_formats); 00653 } 00654 av_freep(&link); 00655 } 00656 for (i = 0; i < filter->output_count; i++) { 00657 if ((link = filter->outputs[i])) { 00658 if (link->dst) 00659 link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; 00660 avfilter_formats_unref(&link->in_formats); 00661 avfilter_formats_unref(&link->out_formats); 00662 } 00663 av_freep(&link); 00664 } 00665 00666 av_freep(&filter->name); 00667 av_freep(&filter->input_pads); 00668 av_freep(&filter->output_pads); 00669 av_freep(&filter->inputs); 00670 av_freep(&filter->outputs); 00671 av_freep(&filter->priv); 00672 av_free(filter); 00673 } 00674 00675 int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque) 00676 { 00677 int ret=0; 00678 00679 if (filter->filter->init) 00680 ret = filter->filter->init(filter, args, opaque); 00681 return ret; 00682 } 00683