1/* 2 * MMAL Video Decoder 3 * Copyright (c) 2015 rcombs 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * MMAL Video Decoder 25 */ 26 27#include <bcm_host.h> 28#include <interface/mmal/mmal.h> 29#include <interface/mmal/mmal_parameters_video.h> 30#include <interface/mmal/util/mmal_util.h> 31#include <interface/mmal/util/mmal_util_params.h> 32#include <interface/mmal/util/mmal_default_components.h> 33#include <interface/mmal/vc/mmal_vc_api.h> 34#include <stdatomic.h> 35 36#include "avcodec.h" 37#include "codec_internal.h" 38#include "decode.h" 39#include "hwconfig.h" 40#include "internal.h" 41#include "libavutil/avassert.h" 42#include "libavutil/buffer.h" 43#include "libavutil/common.h" 44#include "libavutil/imgutils.h" 45#include "libavutil/opt.h" 46#include "libavutil/log.h" 47 48typedef struct FFBufferEntry { 49 AVBufferRef *ref; 50 void *data; 51 size_t length; 52 int64_t pts, dts; 53 int flags; 54 struct FFBufferEntry *next; 55} FFBufferEntry; 56 57// MMAL_POOL_T destroys all of its MMAL_BUFFER_HEADER_Ts. If we want correct 58// refcounting for AVFrames, we can free the MMAL_POOL_T only after all AVFrames 59// have been unreferenced. 60typedef struct FFPoolRef { 61 atomic_int refcount; 62 MMAL_POOL_T *pool; 63} FFPoolRef; 64 65typedef struct FFBufferRef { 66 MMAL_BUFFER_HEADER_T *buffer; 67 FFPoolRef *pool; 68} FFBufferRef; 69 70typedef struct MMALDecodeContext { 71 AVClass *av_class; 72 int extra_buffers; 73 int extra_decoder_buffers; 74 75 MMAL_COMPONENT_T *decoder; 76 MMAL_QUEUE_T *queue_decoded_frames; 77 MMAL_POOL_T *pool_in; 78 FFPoolRef *pool_out; 79 80 // Waiting input packets. Because the libavcodec API requires decoding and 81 // returning packets in lockstep, it can happen that queue_decoded_frames 82 // contains almost all surfaces - then the decoder input queue can quickly 83 // fill up and won't accept new input either. Without consuming input, the 84 // libavcodec API can't return new frames, and we have a logical deadlock. 85 // This is avoided by queuing such buffers here. 86 FFBufferEntry *waiting_buffers, *waiting_buffers_tail; 87 /* Packet used to hold received packets temporarily; not owned by us. */ 88 AVPacket *pkt; 89 90 int64_t packets_sent; 91 atomic_int packets_buffered; 92 int64_t frames_output; 93 int eos_received; 94 int eos_sent; 95 int extradata_sent; 96 int interlaced_frame; 97 int top_field_first; 98} MMALDecodeContext; 99 100// Assume decoder is guaranteed to produce output after at least this many 101// packets (where each packet contains 1 frame). 102#define MAX_DELAYED_FRAMES 16 103 104static void ffmmal_poolref_unref(FFPoolRef *ref) 105{ 106 if (ref && 107 atomic_fetch_add_explicit(&ref->refcount, -1, memory_order_acq_rel) == 1) { 108 mmal_pool_destroy(ref->pool); 109 av_free(ref); 110 } 111} 112 113static void ffmmal_release_frame(void *opaque, uint8_t *data) 114{ 115 FFBufferRef *ref = (void *)data; 116 117 mmal_buffer_header_release(ref->buffer); 118 ffmmal_poolref_unref(ref->pool); 119 120 av_free(ref); 121} 122 123// Setup frame with a new reference to buffer. The buffer must have been 124// allocated from the given pool. 125static int ffmmal_set_ref(AVFrame *frame, FFPoolRef *pool, 126 MMAL_BUFFER_HEADER_T *buffer) 127{ 128 FFBufferRef *ref = av_mallocz(sizeof(*ref)); 129 if (!ref) 130 return AVERROR(ENOMEM); 131 132 ref->pool = pool; 133 ref->buffer = buffer; 134 135 frame->buf[0] = av_buffer_create((void *)ref, sizeof(*ref), 136 ffmmal_release_frame, NULL, 137 AV_BUFFER_FLAG_READONLY); 138 if (!frame->buf[0]) { 139 av_free(ref); 140 return AVERROR(ENOMEM); 141 } 142 143 atomic_fetch_add_explicit(&ref->pool->refcount, 1, memory_order_relaxed); 144 mmal_buffer_header_acquire(buffer); 145 146 frame->format = AV_PIX_FMT_MMAL; 147 frame->data[3] = (uint8_t *)ref->buffer; 148 return 0; 149} 150 151static void ffmmal_stop_decoder(AVCodecContext *avctx) 152{ 153 MMALDecodeContext *ctx = avctx->priv_data; 154 MMAL_COMPONENT_T *decoder = ctx->decoder; 155 MMAL_BUFFER_HEADER_T *buffer; 156 157 mmal_port_disable(decoder->input[0]); 158 mmal_port_disable(decoder->output[0]); 159 mmal_port_disable(decoder->control); 160 161 mmal_port_flush(decoder->input[0]); 162 mmal_port_flush(decoder->output[0]); 163 mmal_port_flush(decoder->control); 164 165 while ((buffer = mmal_queue_get(ctx->queue_decoded_frames))) 166 mmal_buffer_header_release(buffer); 167 168 while (ctx->waiting_buffers) { 169 FFBufferEntry *buffer = ctx->waiting_buffers; 170 171 ctx->waiting_buffers = buffer->next; 172 173 if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) 174 atomic_fetch_add(&ctx->packets_buffered, -1); 175 176 av_buffer_unref(&buffer->ref); 177 av_free(buffer); 178 } 179 ctx->waiting_buffers_tail = NULL; 180 181 av_assert0(atomic_load(&ctx->packets_buffered) == 0); 182 183 ctx->frames_output = ctx->eos_received = ctx->eos_sent = ctx->packets_sent = ctx->extradata_sent = 0; 184} 185 186static av_cold int ffmmal_close_decoder(AVCodecContext *avctx) 187{ 188 MMALDecodeContext *ctx = avctx->priv_data; 189 190 if (ctx->decoder) 191 ffmmal_stop_decoder(avctx); 192 193 mmal_component_destroy(ctx->decoder); 194 ctx->decoder = NULL; 195 mmal_queue_destroy(ctx->queue_decoded_frames); 196 mmal_pool_destroy(ctx->pool_in); 197 ffmmal_poolref_unref(ctx->pool_out); 198 199 mmal_vc_deinit(); 200 201 return 0; 202} 203 204static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) 205{ 206 AVCodecContext *avctx = (AVCodecContext*)port->userdata; 207 MMALDecodeContext *ctx = avctx->priv_data; 208 209 if (!buffer->cmd) { 210 FFBufferEntry *entry = buffer->user_data; 211 av_buffer_unref(&entry->ref); 212 if (entry->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) 213 atomic_fetch_add(&ctx->packets_buffered, -1); 214 av_free(entry); 215 } 216 mmal_buffer_header_release(buffer); 217} 218 219static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) 220{ 221 AVCodecContext *avctx = (AVCodecContext*)port->userdata; 222 MMALDecodeContext *ctx = avctx->priv_data; 223 224 mmal_queue_put(ctx->queue_decoded_frames, buffer); 225} 226 227static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) 228{ 229 AVCodecContext *avctx = (AVCodecContext*)port->userdata; 230 MMAL_STATUS_T status; 231 232 if (buffer->cmd == MMAL_EVENT_ERROR) { 233 status = *(uint32_t *)buffer->data; 234 av_log(avctx, AV_LOG_ERROR, "MMAL error %d on control port\n", (int)status); 235 } else { 236 av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on control port\n", 237 av_fourcc2str(buffer->cmd)); 238 } 239 240 mmal_buffer_header_release(buffer); 241} 242 243// Feed free output buffers to the decoder. 244static int ffmmal_fill_output_port(AVCodecContext *avctx) 245{ 246 MMALDecodeContext *ctx = avctx->priv_data; 247 MMAL_BUFFER_HEADER_T *buffer; 248 MMAL_STATUS_T status; 249 250 if (!ctx->pool_out) 251 return AVERROR_UNKNOWN; // format change code failed with OOM previously 252 253 while ((buffer = mmal_queue_get(ctx->pool_out->pool->queue))) { 254 if ((status = mmal_port_send_buffer(ctx->decoder->output[0], buffer))) { 255 mmal_buffer_header_release(buffer); 256 av_log(avctx, AV_LOG_ERROR, "MMAL error %d when sending output buffer.\n", (int)status); 257 return AVERROR_UNKNOWN; 258 } 259 } 260 261 return 0; 262} 263 264static enum AVColorSpace ffmmal_csp_to_av_csp(MMAL_FOURCC_T fourcc) 265{ 266 switch (fourcc) { 267 case MMAL_COLOR_SPACE_BT470_2_BG: 268 case MMAL_COLOR_SPACE_BT470_2_M: 269 case MMAL_COLOR_SPACE_ITUR_BT601: return AVCOL_SPC_BT470BG; 270 case MMAL_COLOR_SPACE_ITUR_BT709: return AVCOL_SPC_BT709; 271 case MMAL_COLOR_SPACE_FCC: return AVCOL_SPC_FCC; 272 case MMAL_COLOR_SPACE_SMPTE240M: return AVCOL_SPC_SMPTE240M; 273 default: return AVCOL_SPC_UNSPECIFIED; 274 } 275} 276 277static int ffmal_update_format(AVCodecContext *avctx) 278{ 279 MMALDecodeContext *ctx = avctx->priv_data; 280 MMAL_STATUS_T status; 281 int ret = 0; 282 MMAL_COMPONENT_T *decoder = ctx->decoder; 283 MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format; 284 MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type; 285 286 ffmmal_poolref_unref(ctx->pool_out); 287 if (!(ctx->pool_out = av_mallocz(sizeof(*ctx->pool_out)))) { 288 ret = AVERROR(ENOMEM); 289 goto fail; 290 } 291 atomic_init(&ctx->pool_out->refcount, 1); 292 293 if (!format_out) 294 goto fail; 295 296 if ((status = mmal_port_parameter_set_uint32(decoder->output[0], MMAL_PARAMETER_EXTRA_BUFFERS, ctx->extra_buffers))) 297 goto fail; 298 299 if ((status = mmal_port_parameter_set_boolean(decoder->output[0], MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0))) 300 goto fail; 301 302 if (avctx->pix_fmt == AV_PIX_FMT_MMAL) { 303 format_out->encoding = MMAL_ENCODING_OPAQUE; 304 } else { 305 format_out->encoding_variant = format_out->encoding = MMAL_ENCODING_I420; 306 } 307 308 if ((status = mmal_port_format_commit(decoder->output[0]))) 309 goto fail; 310 311 interlace_type.hdr.id = MMAL_PARAMETER_VIDEO_INTERLACE_TYPE; 312 interlace_type.hdr.size = sizeof(MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T); 313 status = mmal_port_parameter_get(decoder->output[0], &interlace_type.hdr); 314 if (status != MMAL_SUCCESS) { 315 av_log(avctx, AV_LOG_ERROR, "Cannot read MMAL interlace information!\n"); 316 } else { 317 ctx->interlaced_frame = (interlace_type.eMode != MMAL_InterlaceProgressive); 318 ctx->top_field_first = (interlace_type.eMode == MMAL_InterlaceFieldsInterleavedUpperFirst); 319 } 320 321 if ((ret = ff_set_dimensions(avctx, format_out->es->video.crop.x + format_out->es->video.crop.width, 322 format_out->es->video.crop.y + format_out->es->video.crop.height)) < 0) 323 goto fail; 324 325 if (format_out->es->video.par.num && format_out->es->video.par.den) { 326 avctx->sample_aspect_ratio.num = format_out->es->video.par.num; 327 avctx->sample_aspect_ratio.den = format_out->es->video.par.den; 328 } 329 if (format_out->es->video.frame_rate.num && format_out->es->video.frame_rate.den) { 330 avctx->framerate.num = format_out->es->video.frame_rate.num; 331 avctx->framerate.den = format_out->es->video.frame_rate.den; 332 } 333 334 avctx->colorspace = ffmmal_csp_to_av_csp(format_out->es->video.color_space); 335 336 decoder->output[0]->buffer_size = 337 FFMAX(decoder->output[0]->buffer_size_min, decoder->output[0]->buffer_size_recommended); 338 decoder->output[0]->buffer_num = 339 FFMAX(decoder->output[0]->buffer_num_min, decoder->output[0]->buffer_num_recommended) + ctx->extra_buffers; 340 ctx->pool_out->pool = mmal_pool_create(decoder->output[0]->buffer_num, 341 decoder->output[0]->buffer_size); 342 if (!ctx->pool_out->pool) { 343 ret = AVERROR(ENOMEM); 344 goto fail; 345 } 346 347 return 0; 348 349fail: 350 return ret < 0 ? ret : AVERROR_UNKNOWN; 351} 352 353static av_cold int ffmmal_init_decoder(AVCodecContext *avctx) 354{ 355 MMALDecodeContext *ctx = avctx->priv_data; 356 MMAL_STATUS_T status; 357 MMAL_ES_FORMAT_T *format_in; 358 MMAL_COMPONENT_T *decoder; 359 int ret = 0; 360 361 ctx->pkt = avctx->internal->in_pkt; 362 363 bcm_host_init(); 364 365 if (mmal_vc_init()) { 366 av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n"); 367 return AVERROR(ENOSYS); 368 } 369 370 if ((ret = ff_get_format(avctx, avctx->codec->pix_fmts)) < 0) 371 return ret; 372 373 avctx->pix_fmt = ret; 374 375 if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder))) 376 goto fail; 377 378 decoder = ctx->decoder; 379 380 format_in = decoder->input[0]->format; 381 format_in->type = MMAL_ES_TYPE_VIDEO; 382 switch (avctx->codec_id) { 383 case AV_CODEC_ID_MPEG2VIDEO: 384 format_in->encoding = MMAL_ENCODING_MP2V; 385 break; 386 case AV_CODEC_ID_MPEG4: 387 format_in->encoding = MMAL_ENCODING_MP4V; 388 break; 389 case AV_CODEC_ID_VC1: 390 format_in->encoding = MMAL_ENCODING_WVC1; 391 break; 392 case AV_CODEC_ID_H264: 393 default: 394 format_in->encoding = MMAL_ENCODING_H264; 395 break; 396 } 397 format_in->es->video.width = FFALIGN(avctx->width, 32); 398 format_in->es->video.height = FFALIGN(avctx->height, 16); 399 format_in->es->video.crop.width = avctx->width; 400 format_in->es->video.crop.height = avctx->height; 401 format_in->es->video.frame_rate.num = 24000; 402 format_in->es->video.frame_rate.den = 1001; 403 format_in->es->video.par.num = avctx->sample_aspect_ratio.num; 404 format_in->es->video.par.den = avctx->sample_aspect_ratio.den; 405 format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED; 406 407 av_log(avctx, AV_LOG_DEBUG, "Using MMAL %s encoding.\n", 408 av_fourcc2str(format_in->encoding)); 409 410#if HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS 411 if (mmal_port_parameter_set_uint32(decoder->input[0], MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS, 412 -1 - ctx->extra_decoder_buffers)) { 413 av_log(avctx, AV_LOG_WARNING, "Could not set input buffering limit.\n"); 414 } 415#endif 416 417 if ((status = mmal_port_format_commit(decoder->input[0]))) 418 goto fail; 419 420 decoder->input[0]->buffer_num = 421 FFMAX(decoder->input[0]->buffer_num_min, 20); 422 decoder->input[0]->buffer_size = 423 FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024); 424 ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0); 425 if (!ctx->pool_in) { 426 ret = AVERROR(ENOMEM); 427 goto fail; 428 } 429 430 if ((ret = ffmal_update_format(avctx)) < 0) 431 goto fail; 432 433 ctx->queue_decoded_frames = mmal_queue_create(); 434 if (!ctx->queue_decoded_frames) 435 goto fail; 436 437 decoder->input[0]->userdata = (void*)avctx; 438 decoder->output[0]->userdata = (void*)avctx; 439 decoder->control->userdata = (void*)avctx; 440 441 if ((status = mmal_port_enable(decoder->control, control_port_cb))) 442 goto fail; 443 if ((status = mmal_port_enable(decoder->input[0], input_callback))) 444 goto fail; 445 if ((status = mmal_port_enable(decoder->output[0], output_callback))) 446 goto fail; 447 448 if ((status = mmal_component_enable(decoder))) 449 goto fail; 450 451 return 0; 452 453fail: 454 ffmmal_close_decoder(avctx); 455 return ret < 0 ? ret : AVERROR_UNKNOWN; 456} 457 458static void ffmmal_flush(AVCodecContext *avctx) 459{ 460 MMALDecodeContext *ctx = avctx->priv_data; 461 MMAL_COMPONENT_T *decoder = ctx->decoder; 462 MMAL_STATUS_T status; 463 464 ffmmal_stop_decoder(avctx); 465 466 if ((status = mmal_port_enable(decoder->control, control_port_cb))) 467 goto fail; 468 if ((status = mmal_port_enable(decoder->input[0], input_callback))) 469 goto fail; 470 if ((status = mmal_port_enable(decoder->output[0], output_callback))) 471 goto fail; 472 473 return; 474 475fail: 476 av_log(avctx, AV_LOG_ERROR, "MMAL flush error: %i\n", (int)status); 477} 478 479// Split packets and add them to the waiting_buffers list. We don't queue them 480// immediately, because it can happen that the decoder is temporarily blocked 481// (due to us not reading/returning enough output buffers) and won't accept 482// new input. (This wouldn't be an issue if MMAL input buffers always were 483// complete frames - then the input buffer just would have to be big enough.) 484// If is_extradata is set, send it as MMAL_BUFFER_HEADER_FLAG_CONFIG. 485static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, 486 int is_extradata) 487{ 488 MMALDecodeContext *ctx = avctx->priv_data; 489 const AVBufferRef *buf = NULL; 490 int size = 0; 491 uint8_t *data = (uint8_t *)""; 492 uint8_t *start; 493 int ret = 0; 494 495 if (avpkt->size) { 496 ret = av_packet_make_refcounted(avpkt); 497 if (ret < 0) 498 goto done; 499 buf = avpkt->buf; 500 data = avpkt->data; 501 size = avpkt->size; 502 if (!is_extradata) 503 ctx->packets_sent++; 504 } else { 505 if (ctx->eos_sent) 506 goto done; 507 if (!ctx->packets_sent) { 508 // Short-cut the flush logic to avoid upsetting MMAL. 509 ctx->eos_sent = 1; 510 ctx->eos_received = 1; 511 goto done; 512 } 513 } 514 515 start = data; 516 517 do { 518 FFBufferEntry *buffer = av_mallocz(sizeof(*buffer)); 519 if (!buffer) { 520 ret = AVERROR(ENOMEM); 521 goto done; 522 } 523 524 buffer->data = data; 525 buffer->length = FFMIN(size, ctx->decoder->input[0]->buffer_size); 526 527 if (is_extradata) 528 buffer->flags |= MMAL_BUFFER_HEADER_FLAG_CONFIG; 529 530 if (data == start) 531 buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_START; 532 533 data += buffer->length; 534 size -= buffer->length; 535 536 buffer->pts = avpkt->pts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : avpkt->pts; 537 buffer->dts = avpkt->dts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : avpkt->dts; 538 539 if (!size) { 540 buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; 541 atomic_fetch_add(&ctx->packets_buffered, 1); 542 } 543 544 if (!buffer->length) { 545 buffer->flags |= MMAL_BUFFER_HEADER_FLAG_EOS; 546 ctx->eos_sent = 1; 547 } 548 549 if (buf) { 550 buffer->ref = av_buffer_ref(buf); 551 if (!buffer->ref) { 552 av_free(buffer); 553 ret = AVERROR(ENOMEM); 554 goto done; 555 } 556 } 557 558 // Insert at end of the list 559 if (!ctx->waiting_buffers) 560 ctx->waiting_buffers = buffer; 561 if (ctx->waiting_buffers_tail) 562 ctx->waiting_buffers_tail->next = buffer; 563 ctx->waiting_buffers_tail = buffer; 564 } while (size); 565 566done: 567 av_packet_unref(avpkt); 568 return ret; 569} 570 571// Move prepared/split packets from waiting_buffers to the MMAL decoder. 572static int ffmmal_fill_input_port(AVCodecContext *avctx) 573{ 574 MMALDecodeContext *ctx = avctx->priv_data; 575 576 while (ctx->waiting_buffers) { 577 MMAL_BUFFER_HEADER_T *mbuffer; 578 FFBufferEntry *buffer; 579 MMAL_STATUS_T status; 580 581 mbuffer = mmal_queue_get(ctx->pool_in->queue); 582 if (!mbuffer) 583 return 0; 584 585 buffer = ctx->waiting_buffers; 586 587 mmal_buffer_header_reset(mbuffer); 588 mbuffer->cmd = 0; 589 mbuffer->pts = buffer->pts; 590 mbuffer->dts = buffer->dts; 591 mbuffer->flags = buffer->flags; 592 mbuffer->data = buffer->data; 593 mbuffer->length = buffer->length; 594 mbuffer->user_data = buffer; 595 mbuffer->alloc_size = ctx->decoder->input[0]->buffer_size; 596 597 // Remove from start of the list 598 ctx->waiting_buffers = buffer->next; 599 if (ctx->waiting_buffers_tail == buffer) 600 ctx->waiting_buffers_tail = NULL; 601 602 if ((status = mmal_port_send_buffer(ctx->decoder->input[0], mbuffer))) { 603 mmal_buffer_header_release(mbuffer); 604 av_buffer_unref(&buffer->ref); 605 if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) 606 atomic_fetch_add(&ctx->packets_buffered, -1); 607 av_free(buffer); 608 } 609 610 if (status) { 611 av_log(avctx, AV_LOG_ERROR, "MMAL error %d when sending input\n", (int)status); 612 return AVERROR_UNKNOWN; 613 } 614 } 615 616 return 0; 617} 618 619static int ffmal_copy_frame(AVCodecContext *avctx, AVFrame *frame, 620 MMAL_BUFFER_HEADER_T *buffer) 621{ 622 MMALDecodeContext *ctx = avctx->priv_data; 623 int ret = 0; 624 625 frame->interlaced_frame = ctx->interlaced_frame; 626 frame->top_field_first = ctx->top_field_first; 627 628 if (avctx->pix_fmt == AV_PIX_FMT_MMAL) { 629 if (!ctx->pool_out) 630 return AVERROR_UNKNOWN; // format change code failed with OOM previously 631 632 if ((ret = ff_decode_frame_props(avctx, frame)) < 0) 633 goto done; 634 635 if ((ret = ffmmal_set_ref(frame, ctx->pool_out, buffer)) < 0) 636 goto done; 637 } else { 638 int w = FFALIGN(avctx->width, 32); 639 int h = FFALIGN(avctx->height, 16); 640 uint8_t *src[4]; 641 int linesize[4]; 642 643 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 644 goto done; 645 646 av_image_fill_arrays(src, linesize, 647 buffer->data + buffer->type->video.offset[0], 648 avctx->pix_fmt, w, h, 1); 649 av_image_copy(frame->data, frame->linesize, (const uint8_t **)src, linesize, 650 avctx->pix_fmt, avctx->width, avctx->height); 651 } 652 653 frame->sample_aspect_ratio = avctx->sample_aspect_ratio; 654 frame->width = avctx->width; 655 frame->width = avctx->width; 656 frame->height = avctx->height; 657 frame->format = avctx->pix_fmt; 658 659 frame->pts = buffer->pts == MMAL_TIME_UNKNOWN ? AV_NOPTS_VALUE : buffer->pts; 660 frame->pkt_dts = AV_NOPTS_VALUE; 661 662done: 663 return ret; 664} 665 666// Fetch a decoded buffer and place it into the frame parameter. 667static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame) 668{ 669 MMALDecodeContext *ctx = avctx->priv_data; 670 MMAL_BUFFER_HEADER_T *buffer = NULL; 671 MMAL_STATUS_T status = 0; 672 int ret = 0; 673 674 if (ctx->eos_received) 675 goto done; 676 677 while (1) { 678 // To ensure decoding in lockstep with a constant delay between fed packets 679 // and output frames, we always wait until an output buffer is available. 680 // Except during start we don't know after how many input packets the decoder 681 // is going to return the first buffer, and we can't distinguish decoder 682 // being busy from decoder waiting for input. So just poll at the start and 683 // keep feeding new data to the buffer. 684 // We are pretty sure the decoder will produce output if we sent more input 685 // frames than what a H.264 decoder could logically delay. This avoids too 686 // excessive buffering. 687 // We also wait if we sent eos, but didn't receive it yet (think of decoding 688 // stream with a very low number of frames). 689 if (atomic_load(&ctx->packets_buffered) > MAX_DELAYED_FRAMES || 690 (ctx->packets_sent && ctx->eos_sent)) { 691 // MMAL will ignore broken input packets, which means the frame we 692 // expect here may never arrive. Dealing with this correctly is 693 // complicated, so here's a hack to avoid that it freezes forever 694 // in this unlikely situation. 695 buffer = mmal_queue_timedwait(ctx->queue_decoded_frames, 100); 696 if (!buffer) { 697 av_log(avctx, AV_LOG_ERROR, "Did not get output frame from MMAL.\n"); 698 ret = AVERROR_UNKNOWN; 699 goto done; 700 } 701 } else { 702 buffer = mmal_queue_get(ctx->queue_decoded_frames); 703 if (!buffer) 704 goto done; 705 } 706 707 ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS); 708 if (ctx->eos_received) 709 goto done; 710 711 if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) { 712 MMAL_COMPONENT_T *decoder = ctx->decoder; 713 MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer); 714 MMAL_BUFFER_HEADER_T *stale_buffer; 715 716 av_log(avctx, AV_LOG_INFO, "Changing output format.\n"); 717 718 if ((status = mmal_port_disable(decoder->output[0]))) 719 goto done; 720 721 while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames))) 722 mmal_buffer_header_release(stale_buffer); 723 724 mmal_format_copy(decoder->output[0]->format, ev->format); 725 726 if ((ret = ffmal_update_format(avctx)) < 0) 727 goto done; 728 729 if ((status = mmal_port_enable(decoder->output[0], output_callback))) 730 goto done; 731 732 if ((ret = ffmmal_fill_output_port(avctx)) < 0) 733 goto done; 734 735 if ((ret = ffmmal_fill_input_port(avctx)) < 0) 736 goto done; 737 738 mmal_buffer_header_release(buffer); 739 continue; 740 } else if (buffer->cmd) { 741 av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on output port\n", 742 av_fourcc2str(buffer->cmd)); 743 goto done; 744 } else if (buffer->length == 0) { 745 // Unused output buffer that got drained after format change. 746 mmal_buffer_header_release(buffer); 747 continue; 748 } 749 750 ctx->frames_output++; 751 752 if ((ret = ffmal_copy_frame(avctx, frame, buffer)) < 0) 753 goto done; 754 755 *got_frame = 1; 756 break; 757 } 758 759done: 760 if (buffer) 761 mmal_buffer_header_release(buffer); 762 if (status && ret >= 0) 763 ret = AVERROR_UNKNOWN; 764 return ret; 765} 766 767static int ffmmal_receive_frame(AVCodecContext *avctx, AVFrame *frame) 768{ 769 MMALDecodeContext *ctx = avctx->priv_data; 770 AVPacket *const avpkt = ctx->pkt; 771 int ret = 0; 772 int got_frame = 0; 773 774 if (avctx->extradata_size && !ctx->extradata_sent) { 775 avpkt->data = avctx->extradata; 776 avpkt->size = avctx->extradata_size; 777 ctx->extradata_sent = 1; 778 if ((ret = ffmmal_add_packet(avctx, avpkt, 1)) < 0) 779 return ret; 780 } 781 782 ret = ff_decode_get_packet(avctx, avpkt); 783 if (ret == 0) { 784 if ((ret = ffmmal_add_packet(avctx, avpkt, 0)) < 0) 785 return ret; 786 } else if (ret < 0 && !(ret == AVERROR(EAGAIN))) 787 return ret; 788 789 if ((ret = ffmmal_fill_input_port(avctx)) < 0) 790 return ret; 791 792 if ((ret = ffmmal_fill_output_port(avctx)) < 0) 793 return ret; 794 795 if ((ret = ffmmal_read_frame(avctx, frame, &got_frame)) < 0) 796 return ret; 797 798 // ffmmal_read_frame() can block for a while. Since the decoder is 799 // asynchronous, it's a good idea to fill the ports again. 800 801 if ((ret = ffmmal_fill_output_port(avctx)) < 0) 802 return ret; 803 804 if ((ret = ffmmal_fill_input_port(avctx)) < 0) 805 return ret; 806 807 if (!got_frame && ret == 0) 808 return AVERROR(EAGAIN); 809 else 810 return ret; 811} 812 813static const AVCodecHWConfigInternal *const mmal_hw_configs[] = { 814 HW_CONFIG_INTERNAL(MMAL), 815 NULL 816}; 817 818static const AVOption options[]={ 819 {"extra_buffers", "extra buffers", offsetof(MMALDecodeContext, extra_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0}, 820 {"extra_decoder_buffers", "extra MMAL internal buffered frames", offsetof(MMALDecodeContext, extra_decoder_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0}, 821 {NULL} 822}; 823 824static const AVClass ffmmal_dec_class = { 825 .class_name = "mmal_dec", 826 .item_name = av_default_item_name, 827 .option = options, 828 .version = LIBAVUTIL_VERSION_INT, 829}; 830 831#define FFMMAL_DEC(NAME, ID) \ 832 const FFCodec ff_##NAME##_mmal_decoder = { \ 833 .p.name = #NAME "_mmal", \ 834 .p.long_name = NULL_IF_CONFIG_SMALL(#NAME " (mmal)"), \ 835 .p.type = AVMEDIA_TYPE_VIDEO, \ 836 .p.id = ID, \ 837 .priv_data_size = sizeof(MMALDecodeContext), \ 838 .init = ffmmal_init_decoder, \ 839 .close = ffmmal_close_decoder, \ 840 FF_CODEC_RECEIVE_FRAME_CB(ffmmal_receive_frame), \ 841 .flush = ffmmal_flush, \ 842 .p.priv_class = &ffmmal_dec_class, \ 843 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ 844 .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ 845 .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \ 846 AV_PIX_FMT_YUV420P, \ 847 AV_PIX_FMT_NONE}, \ 848 .hw_configs = mmal_hw_configs, \ 849 .p.wrapper_name = "mmal", \ 850 }; 851 852FFMMAL_DEC(h264, AV_CODEC_ID_H264) 853FFMMAL_DEC(mpeg2, AV_CODEC_ID_MPEG2VIDEO) 854FFMMAL_DEC(mpeg4, AV_CODEC_ID_MPEG4) 855FFMMAL_DEC(vc1, AV_CODEC_ID_VC1) 856