1/* 2 * filter layer 3 * Copyright (c) 2007 Bobby Bingham 4 * 5 * This file is part of Libav. 6 * 7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/* #define DEBUG */ 23 24#include "libavutil/pixdesc.h" 25#include "libavutil/rational.h" 26#include "libavutil/audioconvert.h" 27#include "libavutil/imgutils.h" 28#include "libavcodec/avcodec.h" 29#include "avfilter.h" 30#include "internal.h" 31 32unsigned avfilter_version(void) { 33 return LIBAVFILTER_VERSION_INT; 34} 35 36const char *avfilter_configuration(void) 37{ 38 return LIBAV_CONFIGURATION; 39} 40 41const char *avfilter_license(void) 42{ 43#define LICENSE_PREFIX "libavfilter license: " 44 return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; 45} 46 47AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask) 48{ 49 AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef)); 50 if (!ret) 51 return NULL; 52 *ret = *ref; 53 if (ref->type == AVMEDIA_TYPE_VIDEO) { 54 ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps)); 55 if (!ret->video) { 56 av_free(ret); 57 return NULL; 58 } 59 *ret->video = *ref->video; 60 } else if (ref->type == AVMEDIA_TYPE_AUDIO) { 61 ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps)); 62 if (!ret->audio) { 63 av_free(ret); 64 return NULL; 65 } 66 *ret->audio = *ref->audio; 67 } 68 ret->perms &= pmask; 69 ret->buf->refcount ++; 70 return ret; 71} 72 73void avfilter_unref_buffer(AVFilterBufferRef *ref) 74{ 75 if (!ref) 76 return; 77 if (!(--ref->buf->refcount)) 78 ref->buf->free(ref->buf); 79 av_free(ref->video); 80 av_free(ref->audio); 81 av_free(ref); 82} 83 84void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, 85 AVFilterPad **pads, AVFilterLink ***links, 86 AVFilterPad *newpad) 87{ 88 unsigned i; 89 90 idx = FFMIN(idx, *count); 91 92 *pads = av_realloc(*pads, sizeof(AVFilterPad) * (*count + 1)); 93 *links = av_realloc(*links, sizeof(AVFilterLink*) * (*count + 1)); 94 memmove(*pads +idx+1, *pads +idx, sizeof(AVFilterPad) * (*count-idx)); 95 memmove(*links+idx+1, *links+idx, sizeof(AVFilterLink*) * (*count-idx)); 96 memcpy(*pads+idx, newpad, sizeof(AVFilterPad)); 97 (*links)[idx] = NULL; 98 99 (*count)++; 100 for (i = idx+1; i < *count; i++) 101 if (*links[i]) 102 (*(unsigned *)((uint8_t *) *links[i] + padidx_off))++; 103} 104 105int avfilter_link(AVFilterContext *src, unsigned srcpad, 106 AVFilterContext *dst, unsigned dstpad) 107{ 108 AVFilterLink *link; 109 110 if (src->output_count <= srcpad || dst->input_count <= dstpad || 111 src->outputs[srcpad] || dst->inputs[dstpad]) 112 return -1; 113 114 if (src->output_pads[srcpad].type != dst->input_pads[dstpad].type) { 115 av_log(src, AV_LOG_ERROR, 116 "Media type mismatch between the '%s' filter output pad %d and the '%s' filter input pad %d\n", 117 src->name, srcpad, dst->name, dstpad); 118 return AVERROR(EINVAL); 119 } 120 121 src->outputs[srcpad] = 122 dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); 123 124 link->src = src; 125 link->dst = dst; 126 link->srcpad = &src->output_pads[srcpad]; 127 link->dstpad = &dst->input_pads[dstpad]; 128 link->type = src->output_pads[srcpad].type; 129 assert(PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1); 130 link->format = -1; 131 132 return 0; 133} 134 135int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, 136 unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) 137{ 138 int ret; 139 unsigned dstpad_idx = link->dstpad - link->dst->input_pads; 140 141 av_log(link->dst, AV_LOG_INFO, "auto-inserting filter '%s' " 142 "between the filter '%s' and the filter '%s'\n", 143 filt->name, link->src->name, link->dst->name); 144 145 link->dst->inputs[dstpad_idx] = NULL; 146 if ((ret = avfilter_link(filt, filt_dstpad_idx, link->dst, dstpad_idx)) < 0) { 147 /* failed to link output filter to new filter */ 148 link->dst->inputs[dstpad_idx] = link; 149 return ret; 150 } 151 152 /* re-hookup the link to the new destination filter we inserted */ 153 link->dst = filt; 154 link->dstpad = &filt->input_pads[filt_srcpad_idx]; 155 filt->inputs[filt_srcpad_idx] = link; 156 157 /* if any information on supported media formats already exists on the 158 * link, we need to preserve that */ 159 if (link->out_formats) 160 avfilter_formats_changeref(&link->out_formats, 161 &filt->outputs[filt_dstpad_idx]->out_formats); 162 163 return 0; 164} 165 166int avfilter_config_links(AVFilterContext *filter) 167{ 168 int (*config_link)(AVFilterLink *); 169 unsigned i; 170 int ret; 171 172 for (i = 0; i < filter->input_count; i ++) { 173 AVFilterLink *link = filter->inputs[i]; 174 175 if (!link) continue; 176 177 switch (link->init_state) { 178 case AVLINK_INIT: 179 continue; 180 case AVLINK_STARTINIT: 181 av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); 182 return 0; 183 case AVLINK_UNINIT: 184 link->init_state = AVLINK_STARTINIT; 185 186 if ((ret = avfilter_config_links(link->src)) < 0) 187 return ret; 188 189 if (!(config_link = link->srcpad->config_props)) 190 config_link = avfilter_default_config_output_link; 191 if ((ret = config_link(link)) < 0) 192 return ret; 193 194 if (link->time_base.num == 0 && link->time_base.den == 0) 195 link->time_base = link->src && link->src->input_count ? 196 link->src->inputs[0]->time_base : AV_TIME_BASE_Q; 197 198 if (link->sample_aspect_ratio.num == 0 && link->sample_aspect_ratio.den == 0) 199 link->sample_aspect_ratio = link->src->input_count ? 200 link->src->inputs[0]->sample_aspect_ratio : (AVRational){1,1}; 201 202 if (link->sample_rate == 0 && link->src && link->src->input_count) 203 link->sample_rate = link->src->inputs[0]->sample_rate; 204 205 if (link->channel_layout == 0 && link->src && link->src->input_count) 206 link->channel_layout = link->src->inputs[0]->channel_layout; 207 208 if ((config_link = link->dstpad->config_props)) 209 if ((ret = config_link(link)) < 0) 210 return ret; 211 212 link->init_state = AVLINK_INIT; 213 } 214 } 215 216 return 0; 217} 218 219#ifdef DEBUG 220static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms) 221{ 222 snprintf(buf, buf_size, "%s%s%s%s%s%s", 223 perms & AV_PERM_READ ? "r" : "", 224 perms & AV_PERM_WRITE ? "w" : "", 225 perms & AV_PERM_PRESERVE ? "p" : "", 226 perms & AV_PERM_REUSE ? "u" : "", 227 perms & AV_PERM_REUSE2 ? "U" : "", 228 perms & AV_PERM_NEG_LINESIZES ? "n" : ""); 229 return buf; 230} 231#endif 232 233static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) 234{ 235 av_unused char buf[16]; 236 av_dlog(ctx, 237 "ref[%p buf:%p refcount:%d perms:%s data:%p linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64, 238 ref, ref->buf, ref->buf->refcount, ff_get_ref_perms_string(buf, sizeof(buf), ref->perms), ref->data[0], 239 ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3], 240 ref->pts, ref->pos); 241 242 if (ref->video) { 243 av_dlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c", 244 ref->video->pixel_aspect.num, ref->video->pixel_aspect.den, 245 ref->video->w, ref->video->h, 246 !ref->video->interlaced ? 'P' : /* Progressive */ 247 ref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ 248 ref->video->key_frame, 249 av_get_picture_type_char(ref->video->pict_type)); 250 } 251 if (ref->audio) { 252 av_dlog(ctx, " cl:%"PRId64"d sn:%d s:%d sr:%d p:%d", 253 ref->audio->channel_layout, 254 ref->audio->nb_samples, 255 ref->audio->size, 256 ref->audio->sample_rate, 257 ref->audio->planar); 258 } 259 260 av_dlog(ctx, "]%s", end ? "\n" : ""); 261} 262 263static void ff_dlog_link(void *ctx, AVFilterLink *link, int end) 264{ 265 if (link->type == AVMEDIA_TYPE_VIDEO) { 266 av_dlog(ctx, 267 "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s", 268 link, link->w, link->h, 269 av_pix_fmt_descriptors[link->format].name, 270 link->src ? link->src->filter->name : "", 271 link->dst ? link->dst->filter->name : "", 272 end ? "\n" : ""); 273 } else { 274 char buf[128]; 275 av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout); 276 277 av_dlog(ctx, 278 "link[%p r:%"PRId64" cl:%s fmt:%-16s %-16s->%-16s]%s", 279 link, link->sample_rate, buf, 280 av_get_sample_fmt_name(link->format), 281 link->src ? link->src->filter->name : "", 282 link->dst ? link->dst->filter->name : "", 283 end ? "\n" : ""); 284 } 285} 286 287#define FF_DPRINTF_START(ctx, func) av_dlog(NULL, "%-16s: ", #func) 288 289AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h) 290{ 291 AVFilterBufferRef *ret = NULL; 292 293 av_unused char buf[16]; 294 FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0); 295 av_dlog(NULL, " perms:%s w:%d h:%d\n", ff_get_ref_perms_string(buf, sizeof(buf), perms), w, h); 296 297 if (link->dstpad->get_video_buffer) 298 ret = link->dstpad->get_video_buffer(link, perms, w, h); 299 300 if (!ret) 301 ret = avfilter_default_get_video_buffer(link, perms, w, h); 302 303 if (ret) 304 ret->type = AVMEDIA_TYPE_VIDEO; 305 306 FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " returning "); ff_dlog_ref(NULL, ret, 1); 307 308 return ret; 309} 310 311AVFilterBufferRef * 312avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int perms, 313 int w, int h, enum PixelFormat format) 314{ 315 AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer)); 316 AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef)); 317 318 if (!pic || !picref) 319 goto fail; 320 321 picref->buf = pic; 322 picref->buf->free = ff_avfilter_default_free_buffer; 323 if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps)))) 324 goto fail; 325 326 pic->w = picref->video->w = w; 327 pic->h = picref->video->h = h; 328 329 /* make sure the buffer gets read permission or it's useless for output */ 330 picref->perms = perms | AV_PERM_READ; 331 332 pic->refcount = 1; 333 picref->type = AVMEDIA_TYPE_VIDEO; 334 pic->format = picref->format = format; 335 336 memcpy(pic->data, data, 4*sizeof(data[0])); 337 memcpy(pic->linesize, linesize, 4*sizeof(linesize[0])); 338 memcpy(picref->data, pic->data, sizeof(picref->data)); 339 memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize)); 340 341 return picref; 342 343fail: 344 if (picref && picref->video) 345 av_free(picref->video); 346 av_free(picref); 347 av_free(pic); 348 return NULL; 349} 350 351AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, 352 enum AVSampleFormat sample_fmt, int size, 353 uint64_t channel_layout, int planar) 354{ 355 AVFilterBufferRef *ret = NULL; 356 357 if (link->dstpad->get_audio_buffer) 358 ret = link->dstpad->get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); 359 360 if (!ret) 361 ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); 362 363 if (ret) 364 ret->type = AVMEDIA_TYPE_AUDIO; 365 366 return ret; 367} 368 369int avfilter_request_frame(AVFilterLink *link) 370{ 371 FF_DPRINTF_START(NULL, request_frame); ff_dlog_link(NULL, link, 1); 372 373 if (link->srcpad->request_frame) 374 return link->srcpad->request_frame(link); 375 else if (link->src->inputs[0]) 376 return avfilter_request_frame(link->src->inputs[0]); 377 else return -1; 378} 379 380int avfilter_poll_frame(AVFilterLink *link) 381{ 382 int i, min = INT_MAX; 383 384 if (link->srcpad->poll_frame) 385 return link->srcpad->poll_frame(link); 386 387 for (i = 0; i < link->src->input_count; i++) { 388 int val; 389 if (!link->src->inputs[i]) 390 return -1; 391 val = avfilter_poll_frame(link->src->inputs[i]); 392 min = FFMIN(min, val); 393 } 394 395 return min; 396} 397 398/* XXX: should we do the duplicating of the picture ref here, instead of 399 * forcing the source filter to do it? */ 400void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) 401{ 402 void (*start_frame)(AVFilterLink *, AVFilterBufferRef *); 403 AVFilterPad *dst = link->dstpad; 404 int perms = picref->perms; 405 406 FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1); 407 408 if (!(start_frame = dst->start_frame)) 409 start_frame = avfilter_default_start_frame; 410 411 if (picref->linesize[0] < 0) 412 perms |= AV_PERM_NEG_LINESIZES; 413 /* prepare to copy the picture if it has insufficient permissions */ 414 if ((dst->min_perms & perms) != dst->min_perms || dst->rej_perms & perms) { 415 av_log(link->dst, AV_LOG_DEBUG, 416 "frame copy needed (have perms %x, need %x, reject %x)\n", 417 picref->perms, 418 link->dstpad->min_perms, link->dstpad->rej_perms); 419 420 link->cur_buf = avfilter_get_video_buffer(link, dst->min_perms, link->w, link->h); 421 link->src_buf = picref; 422 avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf); 423 } 424 else 425 link->cur_buf = picref; 426 427 start_frame(link, link->cur_buf); 428} 429 430void avfilter_end_frame(AVFilterLink *link) 431{ 432 void (*end_frame)(AVFilterLink *); 433 434 if (!(end_frame = link->dstpad->end_frame)) 435 end_frame = avfilter_default_end_frame; 436 437 end_frame(link); 438 439 /* unreference the source picture if we're feeding the destination filter 440 * a copied version dues to permission issues */ 441 if (link->src_buf) { 442 avfilter_unref_buffer(link->src_buf); 443 link->src_buf = NULL; 444 } 445} 446 447void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) 448{ 449 uint8_t *src[4], *dst[4]; 450 int i, j, vsub; 451 void (*draw_slice)(AVFilterLink *, int, int, int); 452 453 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); 454 455 /* copy the slice if needed for permission reasons */ 456 if (link->src_buf) { 457 vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h; 458 459 for (i = 0; i < 4; i++) { 460 if (link->src_buf->data[i]) { 461 src[i] = link->src_buf-> data[i] + 462 (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i]; 463 dst[i] = link->cur_buf->data[i] + 464 (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i]; 465 } else 466 src[i] = dst[i] = NULL; 467 } 468 469 for (i = 0; i < 4; i++) { 470 int planew = 471 av_image_get_linesize(link->format, link->cur_buf->video->w, i); 472 473 if (!src[i]) continue; 474 475 for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) { 476 memcpy(dst[i], src[i], planew); 477 src[i] += link->src_buf->linesize[i]; 478 dst[i] += link->cur_buf->linesize[i]; 479 } 480 } 481 } 482 483 if (!(draw_slice = link->dstpad->draw_slice)) 484 draw_slice = avfilter_default_draw_slice; 485 draw_slice(link, y, h, slice_dir); 486} 487 488void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) 489{ 490 void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); 491 AVFilterPad *dst = link->dstpad; 492 493 FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1); 494 495 if (!(filter_samples = dst->filter_samples)) 496 filter_samples = avfilter_default_filter_samples; 497 498 /* prepare to copy the samples if the buffer has insufficient permissions */ 499 if ((dst->min_perms & samplesref->perms) != dst->min_perms || 500 dst->rej_perms & samplesref->perms) { 501 502 av_log(link->dst, AV_LOG_DEBUG, 503 "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n", 504 samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms); 505 506 link->cur_buf = avfilter_default_get_audio_buffer(link, dst->min_perms, 507 samplesref->format, 508 samplesref->audio->size, 509 samplesref->audio->channel_layout, 510 samplesref->audio->planar); 511 link->cur_buf->pts = samplesref->pts; 512 link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate; 513 514 /* Copy actual data into new samples buffer */ 515 memcpy(link->cur_buf->data[0], samplesref->data[0], samplesref->audio->size); 516 517 avfilter_unref_buffer(samplesref); 518 } else 519 link->cur_buf = samplesref; 520 521 filter_samples(link, link->cur_buf); 522} 523 524#define MAX_REGISTERED_AVFILTERS_NB 64 525 526static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1]; 527 528static int next_registered_avfilter_idx = 0; 529 530AVFilter *avfilter_get_by_name(const char *name) 531{ 532 int i; 533 534 for (i = 0; registered_avfilters[i]; i++) 535 if (!strcmp(registered_avfilters[i]->name, name)) 536 return registered_avfilters[i]; 537 538 return NULL; 539} 540 541int avfilter_register(AVFilter *filter) 542{ 543 if (next_registered_avfilter_idx == MAX_REGISTERED_AVFILTERS_NB) 544 return -1; 545 546 registered_avfilters[next_registered_avfilter_idx++] = filter; 547 return 0; 548} 549 550AVFilter **av_filter_next(AVFilter **filter) 551{ 552 return filter ? ++filter : ®istered_avfilters[0]; 553} 554 555void avfilter_uninit(void) 556{ 557 memset(registered_avfilters, 0, sizeof(registered_avfilters)); 558 next_registered_avfilter_idx = 0; 559} 560 561static int pad_count(const AVFilterPad *pads) 562{ 563 int count; 564 565 for(count = 0; pads->name; count ++) pads ++; 566 return count; 567} 568 569static const char *filter_name(void *p) 570{ 571 AVFilterContext *filter = p; 572 return filter->filter->name; 573} 574 575static const AVClass avfilter_class = { 576 "AVFilter", 577 filter_name, 578 NULL, 579 LIBAVUTIL_VERSION_INT, 580}; 581 582int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name) 583{ 584 AVFilterContext *ret; 585 *filter_ctx = NULL; 586 587 if (!filter) 588 return AVERROR(EINVAL); 589 590 ret = av_mallocz(sizeof(AVFilterContext)); 591 if (!ret) 592 return AVERROR(ENOMEM); 593 594 ret->av_class = &avfilter_class; 595 ret->filter = filter; 596 ret->name = inst_name ? av_strdup(inst_name) : NULL; 597 if (filter->priv_size) { 598 ret->priv = av_mallocz(filter->priv_size); 599 if (!ret->priv) 600 goto err; 601 } 602 603 ret->input_count = pad_count(filter->inputs); 604 if (ret->input_count) { 605 ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->input_count); 606 if (!ret->input_pads) 607 goto err; 608 memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->input_count); 609 ret->inputs = av_mallocz(sizeof(AVFilterLink*) * ret->input_count); 610 if (!ret->inputs) 611 goto err; 612 } 613 614 ret->output_count = pad_count(filter->outputs); 615 if (ret->output_count) { 616 ret->output_pads = av_malloc(sizeof(AVFilterPad) * ret->output_count); 617 if (!ret->output_pads) 618 goto err; 619 memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->output_count); 620 ret->outputs = av_mallocz(sizeof(AVFilterLink*) * ret->output_count); 621 if (!ret->outputs) 622 goto err; 623 } 624 625 *filter_ctx = ret; 626 return 0; 627 628err: 629 av_freep(&ret->inputs); 630 av_freep(&ret->input_pads); 631 ret->input_count = 0; 632 av_freep(&ret->outputs); 633 av_freep(&ret->output_pads); 634 ret->output_count = 0; 635 av_freep(&ret->priv); 636 av_free(ret); 637 return AVERROR(ENOMEM); 638} 639 640void avfilter_free(AVFilterContext *filter) 641{ 642 int i; 643 AVFilterLink *link; 644 645 if (filter->filter->uninit) 646 filter->filter->uninit(filter); 647 648 for (i = 0; i < filter->input_count; i++) { 649 if ((link = filter->inputs[i])) { 650 if (link->src) 651 link->src->outputs[link->srcpad - link->src->output_pads] = NULL; 652 avfilter_formats_unref(&link->in_formats); 653 avfilter_formats_unref(&link->out_formats); 654 } 655 av_freep(&link); 656 } 657 for (i = 0; i < filter->output_count; i++) { 658 if ((link = filter->outputs[i])) { 659 if (link->dst) 660 link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; 661 avfilter_formats_unref(&link->in_formats); 662 avfilter_formats_unref(&link->out_formats); 663 } 664 av_freep(&link); 665 } 666 667 av_freep(&filter->name); 668 av_freep(&filter->input_pads); 669 av_freep(&filter->output_pads); 670 av_freep(&filter->inputs); 671 av_freep(&filter->outputs); 672 av_freep(&filter->priv); 673 av_free(filter); 674} 675 676int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque) 677{ 678 int ret=0; 679 680 if (filter->filter->init) 681 ret = filter->filter->init(filter, args, opaque); 682 return ret; 683} 684 685int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src) 686{ 687 if (dst->type != AVMEDIA_TYPE_VIDEO) 688 return AVERROR(EINVAL); 689 690 dst->pts = src->pts; 691 dst->format = src->format; 692 693 dst->video->w = src->width; 694 dst->video->h = src->height; 695 dst->video->pixel_aspect = src->sample_aspect_ratio; 696 dst->video->interlaced = src->interlaced_frame; 697 dst->video->top_field_first = src->top_field_first; 698 dst->video->key_frame = src->key_frame; 699 dst->video->pict_type = src->pict_type; 700 701 return 0; 702} 703