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