xref: /third_party/ffmpeg/libavcodec/mmaldec.c (revision cabdff1a)
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