1/* 2 * Copyright (c) 2011 Stefano Sabatini 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * FFmpeg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with FFmpeg; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21/** 22 * @file 23 * buffer sink 24 */ 25 26#include "libavutil/audio_fifo.h" 27#include "libavutil/avassert.h" 28#include "libavutil/channel_layout.h" 29#include "libavutil/common.h" 30#include "libavutil/internal.h" 31#include "libavutil/mathematics.h" 32#include "libavutil/opt.h" 33 34#include "audio.h" 35#include "avfilter.h" 36#include "buffersink.h" 37#include "internal.h" 38 39typedef struct BufferSinkContext { 40 const AVClass *class; 41 AVFifoBuffer *fifo; ///< FIFO buffer of video frame references 42 unsigned warning_limit; 43 44 /* only used for video */ 45 enum AVPixelFormat *pixel_fmts; ///< list of accepted pixel formats, must be terminated with -1 46 int pixel_fmts_size; 47 48 /* only used for audio */ 49 enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE 50 int sample_fmts_size; 51 int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1 52 int channel_layouts_size; 53 int *channel_counts; ///< list of accepted channel counts, terminated by -1 54 int channel_counts_size; 55 int all_channel_counts; 56 int *sample_rates; ///< list of accepted sample rates, terminated by -1 57 int sample_rates_size; 58 59 /* only used for compat API */ 60 AVAudioFifo *audio_fifo; ///< FIFO for audio samples 61 int64_t next_pts; ///< interpolating audio pts 62} BufferSinkContext; 63 64#define NB_ITEMS(list) (list ## _size / sizeof(*list)) 65 66static av_cold void uninit(AVFilterContext *ctx) 67{ 68 BufferSinkContext *sink = ctx->priv; 69 AVFrame *frame; 70 71 if (sink->audio_fifo) 72 av_audio_fifo_free(sink->audio_fifo); 73 74 if (sink->fifo) { 75 while (av_fifo_size(sink->fifo) >= sizeof(AVFilterBufferRef *)) { 76 av_fifo_generic_read(sink->fifo, &frame, sizeof(frame), NULL); 77 av_frame_free(&frame); 78 } 79 av_fifo_freep(&sink->fifo); 80 } 81} 82 83static int add_buffer_ref(AVFilterContext *ctx, AVFrame *ref) 84{ 85 BufferSinkContext *buf = ctx->priv; 86 87 if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) { 88 /* realloc fifo size */ 89 if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) { 90 av_log(ctx, AV_LOG_ERROR, 91 "Cannot buffer more frames. Consume some available frames " 92 "before adding new ones.\n"); 93 return AVERROR(ENOMEM); 94 } 95 } 96 97 /* cache frame */ 98 av_fifo_generic_write(buf->fifo, &ref, sizeof(AVFilterBufferRef *), NULL); 99 return 0; 100} 101 102static int filter_frame(AVFilterLink *link, AVFrame *frame) 103{ 104 AVFilterContext *ctx = link->dst; 105 BufferSinkContext *buf = link->dst->priv; 106 int ret; 107 108 if ((ret = add_buffer_ref(ctx, frame)) < 0) 109 return ret; 110 if (buf->warning_limit && 111 av_fifo_size(buf->fifo) / sizeof(AVFilterBufferRef *) >= buf->warning_limit) { 112 av_log(ctx, AV_LOG_WARNING, 113 "%d buffers queued in %s, something may be wrong.\n", 114 buf->warning_limit, 115 (char *)av_x_if_null(ctx->name, ctx->filter->name)); 116 buf->warning_limit *= 10; 117 } 118 return 0; 119} 120 121int attribute_align_arg av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame) 122{ 123 return av_buffersink_get_frame_flags(ctx, frame, 0); 124} 125 126int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags) 127{ 128 BufferSinkContext *buf = ctx->priv; 129 AVFilterLink *inlink = ctx->inputs[0]; 130 int ret; 131 AVFrame *cur_frame; 132 133 /* no picref available, fetch it from the filterchain */ 134 if (!av_fifo_size(buf->fifo)) { 135 if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST) 136 return AVERROR(EAGAIN); 137 if ((ret = ff_request_frame(inlink)) < 0) 138 return ret; 139 } 140 141 if (!av_fifo_size(buf->fifo)) 142 return AVERROR(EINVAL); 143 144 if (flags & AV_BUFFERSINK_FLAG_PEEK) { 145 cur_frame = *((AVFrame **)av_fifo_peek2(buf->fifo, 0)); 146 if ((ret = av_frame_ref(frame, cur_frame)) < 0) 147 return ret; 148 } else { 149 av_fifo_generic_read(buf->fifo, &cur_frame, sizeof(cur_frame), NULL); 150 av_frame_move_ref(frame, cur_frame); 151 av_frame_free(&cur_frame); 152 } 153 154 return 0; 155} 156 157static int read_from_fifo(AVFilterContext *ctx, AVFrame *frame, 158 int nb_samples) 159{ 160 BufferSinkContext *s = ctx->priv; 161 AVFilterLink *link = ctx->inputs[0]; 162 AVFrame *tmp; 163 164 if (!(tmp = ff_get_audio_buffer(link, nb_samples))) 165 return AVERROR(ENOMEM); 166 av_audio_fifo_read(s->audio_fifo, (void**)tmp->extended_data, nb_samples); 167 168 tmp->pts = s->next_pts; 169 if (s->next_pts != AV_NOPTS_VALUE) 170 s->next_pts += av_rescale_q(nb_samples, (AVRational){1, link->sample_rate}, 171 link->time_base); 172 173 av_frame_move_ref(frame, tmp); 174 av_frame_free(&tmp); 175 176 return 0; 177} 178 179int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx, 180 AVFrame *frame, int nb_samples) 181{ 182 BufferSinkContext *s = ctx->priv; 183 AVFilterLink *link = ctx->inputs[0]; 184 AVFrame *cur_frame; 185 int ret = 0; 186 187 if (!s->audio_fifo) { 188 int nb_channels = link->channels; 189 if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples))) 190 return AVERROR(ENOMEM); 191 } 192 193 while (ret >= 0) { 194 if (av_audio_fifo_size(s->audio_fifo) >= nb_samples) 195 return read_from_fifo(ctx, frame, nb_samples); 196 197 if (!(cur_frame = av_frame_alloc())) 198 return AVERROR(ENOMEM); 199 ret = av_buffersink_get_frame_flags(ctx, cur_frame, 0); 200 if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo)) { 201 av_frame_free(&cur_frame); 202 return read_from_fifo(ctx, frame, av_audio_fifo_size(s->audio_fifo)); 203 } else if (ret < 0) { 204 av_frame_free(&cur_frame); 205 return ret; 206 } 207 208 if (cur_frame->pts != AV_NOPTS_VALUE) { 209 s->next_pts = cur_frame->pts - 210 av_rescale_q(av_audio_fifo_size(s->audio_fifo), 211 (AVRational){ 1, link->sample_rate }, 212 link->time_base); 213 } 214 215 ret = av_audio_fifo_write(s->audio_fifo, (void**)cur_frame->extended_data, 216 cur_frame->nb_samples); 217 av_frame_free(&cur_frame); 218 } 219 220 return ret; 221} 222 223AVBufferSinkParams *av_buffersink_params_alloc(void) 224{ 225 static const int pixel_fmts[] = { AV_PIX_FMT_NONE }; 226 AVBufferSinkParams *params = av_malloc(sizeof(AVBufferSinkParams)); 227 if (!params) 228 return NULL; 229 230 params->pixel_fmts = pixel_fmts; 231 return params; 232} 233 234AVABufferSinkParams *av_abuffersink_params_alloc(void) 235{ 236 AVABufferSinkParams *params = av_mallocz(sizeof(AVABufferSinkParams)); 237 238 if (!params) 239 return NULL; 240 return params; 241} 242 243#define FIFO_INIT_SIZE 8 244 245static av_cold int common_init(AVFilterContext *ctx) 246{ 247 BufferSinkContext *buf = ctx->priv; 248 249 buf->fifo = av_fifo_alloc_array(FIFO_INIT_SIZE, sizeof(AVFilterBufferRef *)); 250 if (!buf->fifo) { 251 av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n"); 252 return AVERROR(ENOMEM); 253 } 254 buf->warning_limit = 100; 255 buf->next_pts = AV_NOPTS_VALUE; 256 return 0; 257} 258 259void av_buffersink_set_frame_size(AVFilterContext *ctx, unsigned frame_size) 260{ 261 AVFilterLink *inlink = ctx->inputs[0]; 262 263 inlink->min_samples = inlink->max_samples = 264 inlink->partial_buf_size = frame_size; 265} 266 267#if FF_API_AVFILTERBUFFER 268FF_DISABLE_DEPRECATION_WARNINGS 269static void compat_free_buffer(AVFilterBuffer *buf) 270{ 271 AVFrame *frame = buf->priv; 272 av_frame_free(&frame); 273 av_free(buf); 274} 275 276static int compat_read(AVFilterContext *ctx, 277 AVFilterBufferRef **pbuf, int nb_samples, int flags) 278{ 279 AVFilterBufferRef *buf; 280 AVFrame *frame; 281 int ret; 282 283 if (!pbuf) 284 return ff_poll_frame(ctx->inputs[0]); 285 286 frame = av_frame_alloc(); 287 if (!frame) 288 return AVERROR(ENOMEM); 289 290 if (!nb_samples) 291 ret = av_buffersink_get_frame_flags(ctx, frame, flags); 292 else 293 ret = av_buffersink_get_samples(ctx, frame, nb_samples); 294 295 if (ret < 0) 296 goto fail; 297 298 AV_NOWARN_DEPRECATED( 299 if (ctx->inputs[0]->type == AVMEDIA_TYPE_VIDEO) { 300 buf = avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize, 301 AV_PERM_READ, 302 frame->width, frame->height, 303 frame->format); 304 } else { 305 buf = avfilter_get_audio_buffer_ref_from_arrays(frame->extended_data, 306 frame->linesize[0], AV_PERM_READ, 307 frame->nb_samples, 308 frame->format, 309 frame->channel_layout); 310 } 311 if (!buf) { 312 ret = AVERROR(ENOMEM); 313 goto fail; 314 } 315 316 avfilter_copy_frame_props(buf, frame); 317 ) 318 319 buf->buf->priv = frame; 320 buf->buf->free = compat_free_buffer; 321 322 *pbuf = buf; 323 324 return 0; 325fail: 326 av_frame_free(&frame); 327 return ret; 328} 329 330int attribute_align_arg av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf) 331{ 332 return compat_read(ctx, buf, 0, 0); 333} 334 335int attribute_align_arg av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **buf, 336 int nb_samples) 337{ 338 return compat_read(ctx, buf, nb_samples, 0); 339} 340 341int attribute_align_arg av_buffersink_get_buffer_ref(AVFilterContext *ctx, 342 AVFilterBufferRef **bufref, int flags) 343{ 344 *bufref = NULL; 345 346 av_assert0( !strcmp(ctx->filter->name, "buffersink") 347 || !strcmp(ctx->filter->name, "abuffersink") 348 || !strcmp(ctx->filter->name, "ffbuffersink") 349 || !strcmp(ctx->filter->name, "ffabuffersink")); 350 351 return compat_read(ctx, bufref, 0, flags); 352} 353FF_ENABLE_DEPRECATION_WARNINGS 354#endif 355 356AVRational av_buffersink_get_frame_rate(AVFilterContext *ctx) 357{ 358 av_assert0( !strcmp(ctx->filter->name, "buffersink") 359 || !strcmp(ctx->filter->name, "ffbuffersink")); 360 361 return ctx->inputs[0]->frame_rate; 362} 363 364int attribute_align_arg av_buffersink_poll_frame(AVFilterContext *ctx) 365{ 366 BufferSinkContext *buf = ctx->priv; 367 AVFilterLink *inlink = ctx->inputs[0]; 368 369 av_assert0( !strcmp(ctx->filter->name, "buffersink") 370 || !strcmp(ctx->filter->name, "abuffersink") 371 || !strcmp(ctx->filter->name, "ffbuffersink") 372 || !strcmp(ctx->filter->name, "ffabuffersink")); 373 374 return av_fifo_size(buf->fifo)/sizeof(AVFilterBufferRef *) + ff_poll_frame(inlink); 375} 376 377static av_cold int vsink_init(AVFilterContext *ctx, void *opaque) 378{ 379 BufferSinkContext *buf = ctx->priv; 380 AVBufferSinkParams *params = opaque; 381 int ret; 382 383 if (params) { 384 if ((ret = av_opt_set_int_list(buf, "pix_fmts", params->pixel_fmts, AV_PIX_FMT_NONE, 0)) < 0) 385 return ret; 386 } 387 388 return common_init(ctx); 389} 390 391#define CHECK_LIST_SIZE(field) \ 392 if (buf->field ## _size % sizeof(*buf->field)) { \ 393 av_log(ctx, AV_LOG_ERROR, "Invalid size for " #field ": %d, " \ 394 "should be multiple of %d\n", \ 395 buf->field ## _size, (int)sizeof(*buf->field)); \ 396 return AVERROR(EINVAL); \ 397 } 398static int vsink_query_formats(AVFilterContext *ctx) 399{ 400 BufferSinkContext *buf = ctx->priv; 401 AVFilterFormats *formats = NULL; 402 unsigned i; 403 int ret; 404 405 CHECK_LIST_SIZE(pixel_fmts) 406 if (buf->pixel_fmts_size) { 407 for (i = 0; i < NB_ITEMS(buf->pixel_fmts); i++) 408 if ((ret = ff_add_format(&formats, buf->pixel_fmts[i])) < 0) { 409 ff_formats_unref(&formats); 410 return ret; 411 } 412 ff_set_common_formats(ctx, formats); 413 } else { 414 ff_default_query_formats(ctx); 415 } 416 417 return 0; 418} 419 420static av_cold int asink_init(AVFilterContext *ctx, void *opaque) 421{ 422 BufferSinkContext *buf = ctx->priv; 423 AVABufferSinkParams *params = opaque; 424 int ret; 425 426 if (params) { 427 if ((ret = av_opt_set_int_list(buf, "sample_fmts", params->sample_fmts, AV_SAMPLE_FMT_NONE, 0)) < 0 || 428 (ret = av_opt_set_int_list(buf, "sample_rates", params->sample_rates, -1, 0)) < 0 || 429 (ret = av_opt_set_int_list(buf, "channel_layouts", params->channel_layouts, -1, 0)) < 0 || 430 (ret = av_opt_set_int_list(buf, "channel_counts", params->channel_counts, -1, 0)) < 0 || 431 (ret = av_opt_set_int(buf, "all_channel_counts", params->all_channel_counts, 0)) < 0) 432 return ret; 433 } 434 return common_init(ctx); 435} 436 437static int asink_query_formats(AVFilterContext *ctx) 438{ 439 BufferSinkContext *buf = ctx->priv; 440 AVFilterFormats *formats = NULL; 441 AVFilterChannelLayouts *layouts = NULL; 442 unsigned i; 443 int ret; 444 445 CHECK_LIST_SIZE(sample_fmts) 446 CHECK_LIST_SIZE(sample_rates) 447 CHECK_LIST_SIZE(channel_layouts) 448 CHECK_LIST_SIZE(channel_counts) 449 450 if (buf->sample_fmts_size) { 451 for (i = 0; i < NB_ITEMS(buf->sample_fmts); i++) 452 if ((ret = ff_add_format(&formats, buf->sample_fmts[i])) < 0) { 453 ff_formats_unref(&formats); 454 return ret; 455 } 456 ff_set_common_formats(ctx, formats); 457 } 458 459 if (buf->channel_layouts_size || buf->channel_counts_size || 460 buf->all_channel_counts) { 461 for (i = 0; i < NB_ITEMS(buf->channel_layouts); i++) 462 if ((ret = ff_add_channel_layout(&layouts, buf->channel_layouts[i])) < 0) { 463 ff_channel_layouts_unref(&layouts); 464 return ret; 465 } 466 for (i = 0; i < NB_ITEMS(buf->channel_counts); i++) 467 if ((ret = ff_add_channel_layout(&layouts, FF_COUNT2LAYOUT(buf->channel_counts[i]))) < 0) { 468 ff_channel_layouts_unref(&layouts); 469 return ret; 470 } 471 if (buf->all_channel_counts) { 472 if (layouts) 473 av_log(ctx, AV_LOG_WARNING, 474 "Conflicting all_channel_counts and list in options\n"); 475 else if (!(layouts = ff_all_channel_counts())) 476 return AVERROR(ENOMEM); 477 } 478 ff_set_common_channel_layouts(ctx, layouts); 479 } 480 481 if (buf->sample_rates_size) { 482 formats = NULL; 483 for (i = 0; i < NB_ITEMS(buf->sample_rates); i++) 484 if ((ret = ff_add_format(&formats, buf->sample_rates[i])) < 0) { 485 ff_formats_unref(&formats); 486 return ret; 487 } 488 ff_set_common_samplerates(ctx, formats); 489 } 490 491 return 0; 492} 493 494#define OFFSET(x) offsetof(BufferSinkContext, x) 495#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM 496static const AVOption buffersink_options[] = { 497 { "pix_fmts", "set the supported pixel formats", OFFSET(pixel_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, 498 { NULL }, 499}; 500#undef FLAGS 501#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM 502static const AVOption abuffersink_options[] = { 503 { "sample_fmts", "set the supported sample formats", OFFSET(sample_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, 504 { "sample_rates", "set the supported sample rates", OFFSET(sample_rates), AV_OPT_TYPE_BINARY, .flags = FLAGS }, 505 { "channel_layouts", "set the supported channel layouts", OFFSET(channel_layouts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, 506 { "channel_counts", "set the supported channel counts", OFFSET(channel_counts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, 507 { "all_channel_counts", "accept all channel counts", OFFSET(all_channel_counts), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, 508 { NULL }, 509}; 510#undef FLAGS 511 512AVFILTER_DEFINE_CLASS(buffersink); 513AVFILTER_DEFINE_CLASS(abuffersink); 514 515#if FF_API_AVFILTERBUFFER 516 517#define ffbuffersink_options buffersink_options 518#define ffabuffersink_options abuffersink_options 519AVFILTER_DEFINE_CLASS(ffbuffersink); 520AVFILTER_DEFINE_CLASS(ffabuffersink); 521 522static const AVFilterPad ffbuffersink_inputs[] = { 523 { 524 .name = "default", 525 .type = AVMEDIA_TYPE_VIDEO, 526 .filter_frame = filter_frame, 527 }, 528 { NULL }, 529}; 530 531AVFilter ff_vsink_ffbuffersink = { 532 .name = "ffbuffersink", 533 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), 534 .priv_size = sizeof(BufferSinkContext), 535 .priv_class = &ffbuffersink_class, 536 .init_opaque = vsink_init, 537 .uninit = uninit, 538 539 .query_formats = vsink_query_formats, 540 .inputs = ffbuffersink_inputs, 541 .outputs = NULL, 542}; 543 544static const AVFilterPad ffabuffersink_inputs[] = { 545 { 546 .name = "default", 547 .type = AVMEDIA_TYPE_AUDIO, 548 .filter_frame = filter_frame, 549 }, 550 { NULL }, 551}; 552 553AVFilter ff_asink_ffabuffersink = { 554 .name = "ffabuffersink", 555 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), 556 .init_opaque = asink_init, 557 .uninit = uninit, 558 .priv_size = sizeof(BufferSinkContext), 559 .priv_class = &ffabuffersink_class, 560 .query_formats = asink_query_formats, 561 .inputs = ffabuffersink_inputs, 562 .outputs = NULL, 563}; 564#endif /* FF_API_AVFILTERBUFFER */ 565 566static const AVFilterPad avfilter_vsink_buffer_inputs[] = { 567 { 568 .name = "default", 569 .type = AVMEDIA_TYPE_VIDEO, 570 .filter_frame = filter_frame, 571 }, 572 { NULL } 573}; 574 575AVFilter ff_vsink_buffer = { 576 .name = "buffersink", 577 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), 578 .priv_size = sizeof(BufferSinkContext), 579 .priv_class = &buffersink_class, 580 .init_opaque = vsink_init, 581 .uninit = uninit, 582 583 .query_formats = vsink_query_formats, 584 .inputs = avfilter_vsink_buffer_inputs, 585 .outputs = NULL, 586}; 587 588static const AVFilterPad avfilter_asink_abuffer_inputs[] = { 589 { 590 .name = "default", 591 .type = AVMEDIA_TYPE_AUDIO, 592 .filter_frame = filter_frame, 593 }, 594 { NULL } 595}; 596 597AVFilter ff_asink_abuffer = { 598 .name = "abuffersink", 599 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), 600 .priv_class = &abuffersink_class, 601 .priv_size = sizeof(BufferSinkContext), 602 .init_opaque = asink_init, 603 .uninit = uninit, 604 605 .query_formats = asink_query_formats, 606 .inputs = avfilter_asink_abuffer_inputs, 607 .outputs = NULL, 608}; 609