FFmpeg
mmaldec.c
Go to the documentation of this file.
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/mem.h"
46 #include "libavutil/opt.h"
47 #include "libavutil/log.h"
48 
49 typedef struct FFBufferEntry {
51  void *data;
52  size_t length;
53  int64_t pts, dts;
54  int flags;
57 
58 // MMAL_POOL_T destroys all of its MMAL_BUFFER_HEADER_Ts. If we want correct
59 // refcounting for AVFrames, we can free the MMAL_POOL_T only after all AVFrames
60 // have been unreferenced.
61 typedef struct FFPoolRef {
63  MMAL_POOL_T *pool;
64 } FFPoolRef;
65 
66 typedef struct FFBufferRef {
67  MMAL_BUFFER_HEADER_T *buffer;
69 } FFBufferRef;
70 
71 typedef struct MMALDecodeContext {
75 
76  MMAL_COMPONENT_T *decoder;
77  MMAL_QUEUE_T *queue_decoded_frames;
78  MMAL_POOL_T *pool_in;
80 
81  // Waiting input packets. Because the libavcodec API requires decoding and
82  // returning packets in lockstep, it can happen that queue_decoded_frames
83  // contains almost all surfaces - then the decoder input queue can quickly
84  // fill up and won't accept new input either. Without consuming input, the
85  // libavcodec API can't return new frames, and we have a logical deadlock.
86  // This is avoided by queuing such buffers here.
88  /* Packet used to hold received packets temporarily; not owned by us. */
90 
91  int64_t packets_sent;
93  int64_t frames_output;
95  int eos_sent;
100 
101 // Assume decoder is guaranteed to produce output after at least this many
102 // packets (where each packet contains 1 frame).
103 #define MAX_DELAYED_FRAMES 16
104 
105 static const enum AVPixelFormat mmal_pixfmts[] = {
107 };
108 
110 {
111  if (ref &&
112  atomic_fetch_add_explicit(&ref->refcount, -1, memory_order_acq_rel) == 1) {
113  mmal_pool_destroy(ref->pool);
114  av_free(ref);
115  }
116 }
117 
118 static void ffmmal_release_frame(void *opaque, uint8_t *data)
119 {
120  FFBufferRef *ref = (void *)data;
121 
122  mmal_buffer_header_release(ref->buffer);
123  ffmmal_poolref_unref(ref->pool);
124 
125  av_free(ref);
126 }
127 
128 // Setup frame with a new reference to buffer. The buffer must have been
129 // allocated from the given pool.
131  MMAL_BUFFER_HEADER_T *buffer)
132 {
133  FFBufferRef *ref = av_mallocz(sizeof(*ref));
134  if (!ref)
135  return AVERROR(ENOMEM);
136 
137  ref->pool = pool;
138  ref->buffer = buffer;
139 
140  frame->buf[0] = av_buffer_create((void *)ref, sizeof(*ref),
143  if (!frame->buf[0]) {
144  av_free(ref);
145  return AVERROR(ENOMEM);
146  }
147 
148  atomic_fetch_add_explicit(&ref->pool->refcount, 1, memory_order_relaxed);
149  mmal_buffer_header_acquire(buffer);
150 
151  frame->format = AV_PIX_FMT_MMAL;
152  frame->data[3] = (uint8_t *)ref->buffer;
153  return 0;
154 }
155 
157 {
158  MMALDecodeContext *ctx = avctx->priv_data;
159  MMAL_COMPONENT_T *decoder = ctx->decoder;
160  MMAL_BUFFER_HEADER_T *buffer;
161 
162  mmal_port_disable(decoder->input[0]);
163  mmal_port_disable(decoder->output[0]);
164  mmal_port_disable(decoder->control);
165 
166  mmal_port_flush(decoder->input[0]);
167  mmal_port_flush(decoder->output[0]);
168  mmal_port_flush(decoder->control);
169 
170  while ((buffer = mmal_queue_get(ctx->queue_decoded_frames)))
171  mmal_buffer_header_release(buffer);
172 
173  while (ctx->waiting_buffers) {
174  FFBufferEntry *buffer = ctx->waiting_buffers;
175 
176  ctx->waiting_buffers = buffer->next;
177 
178  if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
179  atomic_fetch_add(&ctx->packets_buffered, -1);
180 
181  av_buffer_unref(&buffer->ref);
182  av_free(buffer);
183  }
184  ctx->waiting_buffers_tail = NULL;
185 
186  av_assert0(atomic_load(&ctx->packets_buffered) == 0);
187 
188  ctx->frames_output = ctx->eos_received = ctx->eos_sent = ctx->packets_sent = ctx->extradata_sent = 0;
189 }
190 
192 {
193  MMALDecodeContext *ctx = avctx->priv_data;
194 
195  if (ctx->decoder)
196  ffmmal_stop_decoder(avctx);
197 
198  mmal_component_destroy(ctx->decoder);
199  ctx->decoder = NULL;
200  mmal_queue_destroy(ctx->queue_decoded_frames);
201  mmal_pool_destroy(ctx->pool_in);
202  ffmmal_poolref_unref(ctx->pool_out);
203 
204  mmal_vc_deinit();
205 
206  return 0;
207 }
208 
209 static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
210 {
211  AVCodecContext *avctx = (AVCodecContext*)port->userdata;
212  MMALDecodeContext *ctx = avctx->priv_data;
213 
214  if (!buffer->cmd) {
215  FFBufferEntry *entry = buffer->user_data;
216  av_buffer_unref(&entry->ref);
217  if (entry->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
218  atomic_fetch_add(&ctx->packets_buffered, -1);
219  av_free(entry);
220  }
221  mmal_buffer_header_release(buffer);
222 }
223 
224 static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
225 {
226  AVCodecContext *avctx = (AVCodecContext*)port->userdata;
227  MMALDecodeContext *ctx = avctx->priv_data;
228 
229  mmal_queue_put(ctx->queue_decoded_frames, buffer);
230 }
231 
232 static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
233 {
234  AVCodecContext *avctx = (AVCodecContext*)port->userdata;
235  MMAL_STATUS_T status;
236 
237  if (buffer->cmd == MMAL_EVENT_ERROR) {
238  status = *(uint32_t *)buffer->data;
239  av_log(avctx, AV_LOG_ERROR, "MMAL error %d on control port\n", (int)status);
240  } else {
241  av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on control port\n",
242  av_fourcc2str(buffer->cmd));
243  }
244 
245  mmal_buffer_header_release(buffer);
246 }
247 
248 // Feed free output buffers to the decoder.
250 {
251  MMALDecodeContext *ctx = avctx->priv_data;
252  MMAL_BUFFER_HEADER_T *buffer;
253  MMAL_STATUS_T status;
254 
255  if (!ctx->pool_out)
256  return AVERROR_UNKNOWN; // format change code failed with OOM previously
257 
258  while ((buffer = mmal_queue_get(ctx->pool_out->pool->queue))) {
259  if ((status = mmal_port_send_buffer(ctx->decoder->output[0], buffer))) {
260  mmal_buffer_header_release(buffer);
261  av_log(avctx, AV_LOG_ERROR, "MMAL error %d when sending output buffer.\n", (int)status);
262  return AVERROR_UNKNOWN;
263  }
264  }
265 
266  return 0;
267 }
268 
269 static enum AVColorSpace ffmmal_csp_to_av_csp(MMAL_FOURCC_T fourcc)
270 {
271  switch (fourcc) {
272  case MMAL_COLOR_SPACE_BT470_2_BG:
273  case MMAL_COLOR_SPACE_BT470_2_M:
274  case MMAL_COLOR_SPACE_ITUR_BT601: return AVCOL_SPC_BT470BG;
275  case MMAL_COLOR_SPACE_ITUR_BT709: return AVCOL_SPC_BT709;
276  case MMAL_COLOR_SPACE_FCC: return AVCOL_SPC_FCC;
277  case MMAL_COLOR_SPACE_SMPTE240M: return AVCOL_SPC_SMPTE240M;
278  default: return AVCOL_SPC_UNSPECIFIED;
279  }
280 }
281 
283 {
284  MMALDecodeContext *ctx = avctx->priv_data;
285  MMAL_STATUS_T status;
286  int ret = 0;
287  MMAL_COMPONENT_T *decoder = ctx->decoder;
288  MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format;
289  MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type;
290 
291  ffmmal_poolref_unref(ctx->pool_out);
292  if (!(ctx->pool_out = av_mallocz(sizeof(*ctx->pool_out)))) {
293  ret = AVERROR(ENOMEM);
294  goto fail;
295  }
296  atomic_init(&ctx->pool_out->refcount, 1);
297 
298  if (!format_out)
299  goto fail;
300 
301  if ((status = mmal_port_parameter_set_uint32(decoder->output[0], MMAL_PARAMETER_EXTRA_BUFFERS, ctx->extra_buffers)))
302  goto fail;
303 
304  if ((status = mmal_port_parameter_set_boolean(decoder->output[0], MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0)))
305  goto fail;
306 
307  if (avctx->pix_fmt == AV_PIX_FMT_MMAL) {
308  format_out->encoding = MMAL_ENCODING_OPAQUE;
309  } else {
310  format_out->encoding_variant = format_out->encoding = MMAL_ENCODING_I420;
311  }
312 
313  if ((status = mmal_port_format_commit(decoder->output[0])))
314  goto fail;
315 
316  interlace_type.hdr.id = MMAL_PARAMETER_VIDEO_INTERLACE_TYPE;
317  interlace_type.hdr.size = sizeof(MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T);
318  status = mmal_port_parameter_get(decoder->output[0], &interlace_type.hdr);
319  if (status != MMAL_SUCCESS) {
320  av_log(avctx, AV_LOG_ERROR, "Cannot read MMAL interlace information!\n");
321  } else {
322  ctx->interlaced_frame = (interlace_type.eMode != MMAL_InterlaceProgressive);
323  ctx->top_field_first = (interlace_type.eMode == MMAL_InterlaceFieldsInterleavedUpperFirst);
324  }
325 
326  if ((ret = ff_set_dimensions(avctx, format_out->es->video.crop.x + format_out->es->video.crop.width,
327  format_out->es->video.crop.y + format_out->es->video.crop.height)) < 0)
328  goto fail;
329 
330  if (format_out->es->video.par.num && format_out->es->video.par.den) {
331  avctx->sample_aspect_ratio.num = format_out->es->video.par.num;
332  avctx->sample_aspect_ratio.den = format_out->es->video.par.den;
333  }
334  if (format_out->es->video.frame_rate.num && format_out->es->video.frame_rate.den) {
335  avctx->framerate.num = format_out->es->video.frame_rate.num;
336  avctx->framerate.den = format_out->es->video.frame_rate.den;
337  }
338 
339  avctx->colorspace = ffmmal_csp_to_av_csp(format_out->es->video.color_space);
340 
341  decoder->output[0]->buffer_size =
342  FFMAX(decoder->output[0]->buffer_size_min, decoder->output[0]->buffer_size_recommended);
343  decoder->output[0]->buffer_num =
344  FFMAX(decoder->output[0]->buffer_num_min, decoder->output[0]->buffer_num_recommended) + ctx->extra_buffers;
345  ctx->pool_out->pool = mmal_pool_create(decoder->output[0]->buffer_num,
346  decoder->output[0]->buffer_size);
347  if (!ctx->pool_out->pool) {
348  ret = AVERROR(ENOMEM);
349  goto fail;
350  }
351 
352  return 0;
353 
354 fail:
355  return ret < 0 ? ret : AVERROR_UNKNOWN;
356 }
357 
359 {
360  MMALDecodeContext *ctx = avctx->priv_data;
361  MMAL_STATUS_T status;
362  MMAL_ES_FORMAT_T *format_in;
363  MMAL_COMPONENT_T *decoder;
364  int ret = 0;
365 
366  ctx->pkt = avctx->internal->in_pkt;
367 
368  bcm_host_init();
369 
370  if (mmal_vc_init()) {
371  av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n");
372  return AVERROR(ENOSYS);
373  }
374 
375  if ((ret = ff_get_format(avctx, mmal_pixfmts)) < 0)
376  return ret;
377 
378  avctx->pix_fmt = ret;
379 
380  if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder)))
381  goto fail;
382 
383  decoder = ctx->decoder;
384 
385  format_in = decoder->input[0]->format;
386  format_in->type = MMAL_ES_TYPE_VIDEO;
387  switch (avctx->codec_id) {
389  format_in->encoding = MMAL_ENCODING_MP2V;
390  break;
391  case AV_CODEC_ID_MPEG4:
392  format_in->encoding = MMAL_ENCODING_MP4V;
393  break;
394  case AV_CODEC_ID_VC1:
395  format_in->encoding = MMAL_ENCODING_WVC1;
396  break;
397  case AV_CODEC_ID_H264:
398  default:
399  format_in->encoding = MMAL_ENCODING_H264;
400  break;
401  }
402  format_in->es->video.width = FFALIGN(avctx->width, 32);
403  format_in->es->video.height = FFALIGN(avctx->height, 16);
404  format_in->es->video.crop.width = avctx->width;
405  format_in->es->video.crop.height = avctx->height;
406  format_in->es->video.frame_rate.num = 24000;
407  format_in->es->video.frame_rate.den = 1001;
408  format_in->es->video.par.num = avctx->sample_aspect_ratio.num;
409  format_in->es->video.par.den = avctx->sample_aspect_ratio.den;
410  format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;
411 
412  av_log(avctx, AV_LOG_DEBUG, "Using MMAL %s encoding.\n",
413  av_fourcc2str(format_in->encoding));
414 
415 #if HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS
416  if (mmal_port_parameter_set_uint32(decoder->input[0], MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS,
417  -1 - ctx->extra_decoder_buffers)) {
418  av_log(avctx, AV_LOG_WARNING, "Could not set input buffering limit.\n");
419  }
420 #endif
421 
422  if ((status = mmal_port_format_commit(decoder->input[0])))
423  goto fail;
424 
425  decoder->input[0]->buffer_num =
426  FFMAX(decoder->input[0]->buffer_num_min, 20);
427  decoder->input[0]->buffer_size =
428  FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024);
429  ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0);
430  if (!ctx->pool_in) {
431  ret = AVERROR(ENOMEM);
432  goto fail;
433  }
434 
435  if ((ret = ffmal_update_format(avctx)) < 0)
436  goto fail;
437 
438  ctx->queue_decoded_frames = mmal_queue_create();
439  if (!ctx->queue_decoded_frames)
440  goto fail;
441 
442  decoder->input[0]->userdata = (void*)avctx;
443  decoder->output[0]->userdata = (void*)avctx;
444  decoder->control->userdata = (void*)avctx;
445 
446  if ((status = mmal_port_enable(decoder->control, control_port_cb)))
447  goto fail;
448  if ((status = mmal_port_enable(decoder->input[0], input_callback)))
449  goto fail;
450  if ((status = mmal_port_enable(decoder->output[0], output_callback)))
451  goto fail;
452 
453  if ((status = mmal_component_enable(decoder)))
454  goto fail;
455 
456  return 0;
457 
458 fail:
459  ffmmal_close_decoder(avctx);
460  return ret < 0 ? ret : AVERROR_UNKNOWN;
461 }
462 
463 static void ffmmal_flush(AVCodecContext *avctx)
464 {
465  MMALDecodeContext *ctx = avctx->priv_data;
466  MMAL_COMPONENT_T *decoder = ctx->decoder;
467  MMAL_STATUS_T status;
468 
469  ffmmal_stop_decoder(avctx);
470 
471  if ((status = mmal_port_enable(decoder->control, control_port_cb)))
472  goto fail;
473  if ((status = mmal_port_enable(decoder->input[0], input_callback)))
474  goto fail;
475  if ((status = mmal_port_enable(decoder->output[0], output_callback)))
476  goto fail;
477 
478  return;
479 
480 fail:
481  av_log(avctx, AV_LOG_ERROR, "MMAL flush error: %i\n", (int)status);
482 }
483 
484 // Split packets and add them to the waiting_buffers list. We don't queue them
485 // immediately, because it can happen that the decoder is temporarily blocked
486 // (due to us not reading/returning enough output buffers) and won't accept
487 // new input. (This wouldn't be an issue if MMAL input buffers always were
488 // complete frames - then the input buffer just would have to be big enough.)
489 // If is_extradata is set, send it as MMAL_BUFFER_HEADER_FLAG_CONFIG.
490 static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt,
491  int is_extradata)
492 {
493  MMALDecodeContext *ctx = avctx->priv_data;
494  const AVBufferRef *buf = NULL;
495  int size = 0;
496  uint8_t *data = (uint8_t *)"";
497  uint8_t *start;
498  int ret = 0;
499 
500  if (avpkt->size) {
502  if (ret < 0)
503  goto done;
504  buf = avpkt->buf;
505  data = avpkt->data;
506  size = avpkt->size;
507  if (!is_extradata)
508  ctx->packets_sent++;
509  } else {
510  if (ctx->eos_sent)
511  goto done;
512  if (!ctx->packets_sent) {
513  // Short-cut the flush logic to avoid upsetting MMAL.
514  ctx->eos_sent = 1;
515  ctx->eos_received = 1;
516  goto done;
517  }
518  }
519 
520  start = data;
521 
522  do {
523  FFBufferEntry *buffer = av_mallocz(sizeof(*buffer));
524  if (!buffer) {
525  ret = AVERROR(ENOMEM);
526  goto done;
527  }
528 
529  buffer->data = data;
530  buffer->length = FFMIN(size, ctx->decoder->input[0]->buffer_size);
531 
532  if (is_extradata)
533  buffer->flags |= MMAL_BUFFER_HEADER_FLAG_CONFIG;
534 
535  if (data == start)
536  buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_START;
537 
538  data += buffer->length;
539  size -= buffer->length;
540 
541  buffer->pts = avpkt->pts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : avpkt->pts;
542  buffer->dts = avpkt->dts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : avpkt->dts;
543 
544  if (!size) {
545  buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
546  atomic_fetch_add(&ctx->packets_buffered, 1);
547  }
548 
549  if (!buffer->length) {
550  buffer->flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
551  ctx->eos_sent = 1;
552  }
553 
554  if (buf) {
555  buffer->ref = av_buffer_ref(buf);
556  if (!buffer->ref) {
557  av_free(buffer);
558  ret = AVERROR(ENOMEM);
559  goto done;
560  }
561  }
562 
563  // Insert at end of the list
564  if (!ctx->waiting_buffers)
565  ctx->waiting_buffers = buffer;
566  if (ctx->waiting_buffers_tail)
567  ctx->waiting_buffers_tail->next = buffer;
568  ctx->waiting_buffers_tail = buffer;
569  } while (size);
570 
571 done:
572  av_packet_unref(avpkt);
573  return ret;
574 }
575 
576 // Move prepared/split packets from waiting_buffers to the MMAL decoder.
578 {
579  MMALDecodeContext *ctx = avctx->priv_data;
580 
581  while (ctx->waiting_buffers) {
582  MMAL_BUFFER_HEADER_T *mbuffer;
584  MMAL_STATUS_T status;
585 
586  mbuffer = mmal_queue_get(ctx->pool_in->queue);
587  if (!mbuffer)
588  return 0;
589 
590  buffer = ctx->waiting_buffers;
591 
592  mmal_buffer_header_reset(mbuffer);
593  mbuffer->cmd = 0;
594  mbuffer->pts = buffer->pts;
595  mbuffer->dts = buffer->dts;
596  mbuffer->flags = buffer->flags;
597  mbuffer->data = buffer->data;
598  mbuffer->length = buffer->length;
599  mbuffer->user_data = buffer;
600  mbuffer->alloc_size = ctx->decoder->input[0]->buffer_size;
601 
602  // Remove from start of the list
603  ctx->waiting_buffers = buffer->next;
604  if (ctx->waiting_buffers_tail == buffer)
605  ctx->waiting_buffers_tail = NULL;
606 
607  if ((status = mmal_port_send_buffer(ctx->decoder->input[0], mbuffer))) {
608  mmal_buffer_header_release(mbuffer);
609  av_buffer_unref(&buffer->ref);
610  if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
611  atomic_fetch_add(&ctx->packets_buffered, -1);
612  av_free(buffer);
613  }
614 
615  if (status) {
616  av_log(avctx, AV_LOG_ERROR, "MMAL error %d when sending input\n", (int)status);
617  return AVERROR_UNKNOWN;
618  }
619  }
620 
621  return 0;
622 }
623 
625  MMAL_BUFFER_HEADER_T *buffer)
626 {
627  MMALDecodeContext *ctx = avctx->priv_data;
628  int ret = 0;
629 
630  if (ctx->interlaced_frame)
632  if (ctx->top_field_first)
634 
635  if (avctx->pix_fmt == AV_PIX_FMT_MMAL) {
636  if (!ctx->pool_out)
637  return AVERROR_UNKNOWN; // format change code failed with OOM previously
638 
639  if ((ret = ff_decode_frame_props(avctx, frame)) < 0)
640  goto done;
641 
642  if ((ret = ffmmal_set_ref(frame, ctx->pool_out, buffer)) < 0)
643  goto done;
644  } else {
645  int w = FFALIGN(avctx->width, 32);
646  int h = FFALIGN(avctx->height, 16);
647  uint8_t *src[4];
648  int linesize[4];
649 
650  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
651  goto done;
652 
653  av_image_fill_arrays(src, linesize,
654  buffer->data + buffer->type->video.offset[0],
655  avctx->pix_fmt, w, h, 1);
656  av_image_copy2(frame->data, frame->linesize, src, linesize,
657  avctx->pix_fmt, avctx->width, avctx->height);
658  }
659 
660  frame->sample_aspect_ratio = avctx->sample_aspect_ratio;
661  frame->width = avctx->width;
662  frame->width = avctx->width;
663  frame->height = avctx->height;
664  frame->format = avctx->pix_fmt;
665 
666  frame->pts = buffer->pts == MMAL_TIME_UNKNOWN ? AV_NOPTS_VALUE : buffer->pts;
667  frame->pkt_dts = AV_NOPTS_VALUE;
668 
669 done:
670  return ret;
671 }
672 
673 // Fetch a decoded buffer and place it into the frame parameter.
674 static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)
675 {
676  MMALDecodeContext *ctx = avctx->priv_data;
677  MMAL_BUFFER_HEADER_T *buffer = NULL;
678  MMAL_STATUS_T status = 0;
679  int ret = 0;
680 
681  if (ctx->eos_received)
682  goto done;
683 
684  while (1) {
685  // To ensure decoding in lockstep with a constant delay between fed packets
686  // and output frames, we always wait until an output buffer is available.
687  // Except during start we don't know after how many input packets the decoder
688  // is going to return the first buffer, and we can't distinguish decoder
689  // being busy from decoder waiting for input. So just poll at the start and
690  // keep feeding new data to the buffer.
691  // We are pretty sure the decoder will produce output if we sent more input
692  // frames than what a H.264 decoder could logically delay. This avoids too
693  // excessive buffering.
694  // We also wait if we sent eos, but didn't receive it yet (think of decoding
695  // stream with a very low number of frames).
696  if (atomic_load(&ctx->packets_buffered) > MAX_DELAYED_FRAMES ||
697  (ctx->packets_sent && ctx->eos_sent)) {
698  // MMAL will ignore broken input packets, which means the frame we
699  // expect here may never arrive. Dealing with this correctly is
700  // complicated, so here's a hack to avoid that it freezes forever
701  // in this unlikely situation.
702  buffer = mmal_queue_timedwait(ctx->queue_decoded_frames, 100);
703  if (!buffer) {
704  av_log(avctx, AV_LOG_ERROR, "Did not get output frame from MMAL.\n");
706  goto done;
707  }
708  } else {
709  buffer = mmal_queue_get(ctx->queue_decoded_frames);
710  if (!buffer)
711  goto done;
712  }
713 
714  ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS);
715  if (ctx->eos_received)
716  goto done;
717 
718  if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {
719  MMAL_COMPONENT_T *decoder = ctx->decoder;
720  MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer);
721  MMAL_BUFFER_HEADER_T *stale_buffer;
722 
723  av_log(avctx, AV_LOG_INFO, "Changing output format.\n");
724 
725  if ((status = mmal_port_disable(decoder->output[0])))
726  goto done;
727 
728  while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames)))
729  mmal_buffer_header_release(stale_buffer);
730 
731  mmal_format_copy(decoder->output[0]->format, ev->format);
732 
733  if ((ret = ffmal_update_format(avctx)) < 0)
734  goto done;
735 
736  if ((status = mmal_port_enable(decoder->output[0], output_callback)))
737  goto done;
738 
739  if ((ret = ffmmal_fill_output_port(avctx)) < 0)
740  goto done;
741 
742  if ((ret = ffmmal_fill_input_port(avctx)) < 0)
743  goto done;
744 
745  mmal_buffer_header_release(buffer);
746  continue;
747  } else if (buffer->cmd) {
748  av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on output port\n",
749  av_fourcc2str(buffer->cmd));
750  goto done;
751  } else if (buffer->length == 0) {
752  // Unused output buffer that got drained after format change.
753  mmal_buffer_header_release(buffer);
754  continue;
755  }
756 
757  ctx->frames_output++;
758 
759  if ((ret = ffmal_copy_frame(avctx, frame, buffer)) < 0)
760  goto done;
761 
762  *got_frame = 1;
763  break;
764  }
765 
766 done:
767  if (buffer)
768  mmal_buffer_header_release(buffer);
769  if (status && ret >= 0)
771  return ret;
772 }
773 
775 {
776  MMALDecodeContext *ctx = avctx->priv_data;
777  AVPacket *const avpkt = ctx->pkt;
778  int ret = 0;
779  int got_frame = 0;
780 
781  if (avctx->extradata_size && !ctx->extradata_sent) {
782  avpkt->data = avctx->extradata;
783  avpkt->size = avctx->extradata_size;
784  ctx->extradata_sent = 1;
785  if ((ret = ffmmal_add_packet(avctx, avpkt, 1)) < 0)
786  return ret;
787  }
788 
789  ret = ff_decode_get_packet(avctx, avpkt);
790  if (ret == 0) {
791  if ((ret = ffmmal_add_packet(avctx, avpkt, 0)) < 0)
792  return ret;
793  } else if (ret < 0 && !(ret == AVERROR(EAGAIN)))
794  return ret;
795 
796  if ((ret = ffmmal_fill_input_port(avctx)) < 0)
797  return ret;
798 
799  if ((ret = ffmmal_fill_output_port(avctx)) < 0)
800  return ret;
801 
802  if ((ret = ffmmal_read_frame(avctx, frame, &got_frame)) < 0)
803  return ret;
804 
805  // ffmmal_read_frame() can block for a while. Since the decoder is
806  // asynchronous, it's a good idea to fill the ports again.
807 
808  if ((ret = ffmmal_fill_output_port(avctx)) < 0)
809  return ret;
810 
811  if ((ret = ffmmal_fill_input_port(avctx)) < 0)
812  return ret;
813 
814  if (!got_frame && ret == 0)
815  return AVERROR(EAGAIN);
816  else
817  return ret;
818 }
819 
820 static const AVCodecHWConfigInternal *const mmal_hw_configs[] = {
821  HW_CONFIG_INTERNAL(MMAL),
822  NULL
823 };
824 
825 static const AVOption options[]={
826  {"extra_buffers", "extra buffers", offsetof(MMALDecodeContext, extra_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0},
827  {"extra_decoder_buffers", "extra MMAL internal buffered frames", offsetof(MMALDecodeContext, extra_decoder_buffers), AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0},
828  {NULL}
829 };
830 
831 static const AVClass ffmmal_dec_class = {
832  .class_name = "mmal_dec",
833  .item_name = av_default_item_name,
834  .option = options,
835  .version = LIBAVUTIL_VERSION_INT,
836 };
837 
838 #define FFMMAL_DEC(NAME, ID) \
839  const FFCodec ff_##NAME##_mmal_decoder = { \
840  .p.name = #NAME "_mmal", \
841  CODEC_LONG_NAME(#NAME " (mmal)"), \
842  .p.type = AVMEDIA_TYPE_VIDEO, \
843  .p.id = ID, \
844  .priv_data_size = sizeof(MMALDecodeContext), \
845  .init = ffmmal_init_decoder, \
846  .close = ffmmal_close_decoder, \
847  FF_CODEC_RECEIVE_FRAME_CB(ffmmal_receive_frame), \
848  .flush = ffmmal_flush, \
849  .p.priv_class = &ffmmal_dec_class, \
850  .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \
851  .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, \
852  .hw_configs = mmal_hw_configs, \
853  .p.wrapper_name = "mmal", \
854  };
855 
FFMMAL_DEC
#define FFMMAL_DEC(NAME, ID)
Definition: mmaldec.c:838
hwconfig.h
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:427
ffmmal_fill_input_port
static int ffmmal_fill_input_port(AVCodecContext *avctx)
Definition: mmaldec.c:577
ff_decode_get_packet
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
Called by decoders to get the next packet for decoding.
Definition: decode.c:221
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
entry
#define entry
Definition: aom_film_grain_template.c:66
MMALDecodeContext::top_field_first
int top_field_first
Definition: mmaldec.c:98
ffmmal_receive_frame
static int ffmmal_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Definition: mmaldec.c:774
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
MMALDecodeContext::extra_decoder_buffers
int extra_decoder_buffers
Definition: mmaldec.c:74
AVCodecContext::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: avcodec.h:685
ff_get_format
int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
Select the (possibly hardware accelerated) pixel format.
Definition: decode.c:1220
mmal_pixfmts
static enum AVPixelFormat mmal_pixfmts[]
Definition: mmaldec.c:105
MMALDecodeContext::frames_output
int64_t frames_output
Definition: mmaldec.c:93
AV_PIX_FMT_MMAL
@ AV_PIX_FMT_MMAL
HW acceleration though MMAL, data[3] contains a pointer to the MMAL_BUFFER_HEADER_T structure.
Definition: pixfmt.h:252
FFBufferRef::buffer
MMAL_BUFFER_HEADER_T * buffer
Definition: mmaldec.c:67
AV_CODEC_ID_MPEG4
@ AV_CODEC_ID_MPEG4
Definition: codec_id.h:64
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:486
w
uint8_t w
Definition: llviddspenc.c:38
MMALDecodeContext::decoder
MMAL_COMPONENT_T * decoder
Definition: mmaldec.c:76
internal.h
AVPacket::data
uint8_t * data
Definition: packet.h:524
MMALDecodeContext::packets_sent
int64_t packets_sent
Definition: mmaldec.c:91
AVOption
AVOption.
Definition: opt.h:346
data
const char data[16]
Definition: mxf.c:148
atomic_int
intptr_t atomic_int
Definition: stdatomic.h:55
AVFrame::flags
int flags
Frame flags, a combination of AV_FRAME_FLAGS.
Definition: frame.h:646
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
ffmmal_fill_output_port
static int ffmmal_fill_output_port(AVCodecContext *avctx)
Definition: mmaldec.c:249
ff_set_dimensions
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:94
MMALDecodeContext::av_class
AVClass * av_class
Definition: mmaldec.c:72
MMALDecodeContext::eos_sent
int eos_sent
Definition: mmaldec.c:95
FFPoolRef::pool
MMAL_POOL_T * pool
Definition: mmaldec.c:63
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:395
FFBufferEntry::flags
int flags
Definition: mmaldec.c:54
AV_FRAME_FLAG_TOP_FIELD_FIRST
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition: frame.h:638
AVCodecContext::framerate
AVRational framerate
Definition: avcodec.h:560
AVCOL_SPC_BT470BG
@ AVCOL_SPC_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
Definition: pixfmt.h:615
decoder
static const chunk_decoder decoder[8]
Definition: dfa.c:331
ffmmal_poolref_unref
static void ffmmal_poolref_unref(FFPoolRef *ref)
Definition: mmaldec.c:109
fail
#define fail()
Definition: checkasm.h:179
mmal_hw_configs
static const AVCodecHWConfigInternal *const mmal_hw_configs[]
Definition: mmaldec.c:820
options
static const AVOption options[]
Definition: mmaldec.c:825
AVRational::num
int num
Numerator.
Definition: rational.h:59
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:524
FFBufferEntry::next
struct FFBufferEntry * next
Definition: mmaldec.c:55
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:114
ffmmal_flush
static void ffmmal_flush(AVCodecContext *avctx)
Definition: mmaldec.c:463
ffmmal_csp_to_av_csp
static enum AVColorSpace ffmmal_csp_to_av_csp(MMAL_FOURCC_T fourcc)
Definition: mmaldec.c:269
FFBufferEntry::pts
int64_t pts
Definition: mmaldec.c:53
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
ffmmal_set_ref
static int ffmmal_set_ref(AVFrame *frame, FFPoolRef *pool, MMAL_BUFFER_HEADER_T *buffer)
Definition: mmaldec.c:130
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:49
decode.h
MMALDecodeContext::queue_decoded_frames
MMAL_QUEUE_T * queue_decoded_frames
Definition: mmaldec.c:77
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
atomic_load
#define atomic_load(object)
Definition: stdatomic.h:93
MAX_DELAYED_FRAMES
#define MAX_DELAYED_FRAMES
Definition: mmaldec.c:103
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
MMALDecodeContext::interlaced_frame
int interlaced_frame
Definition: mmaldec.c:97
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:455
control_port_cb
static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
Definition: mmaldec.c:232
if
if(ret)
Definition: filter_design.txt:179
output_callback
static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
Definition: mmaldec.c:224
ffmmal_init_decoder
static av_cold int ffmmal_init_decoder(AVCodecContext *avctx)
Definition: mmaldec.c:358
AVPacket::buf
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:507
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
ffmal_copy_frame
static int ffmal_copy_frame(AVCodecContext *avctx, AVFrame *frame, MMAL_BUFFER_HEADER_T *buffer)
Definition: mmaldec.c:624
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:480
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
ffmmal_close_decoder
static av_cold int ffmmal_close_decoder(AVCodecContext *avctx)
Definition: mmaldec.c:191
ffmmal_stop_decoder
static void ffmmal_stop_decoder(AVCodecContext *avctx)
Definition: mmaldec.c:156
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1554
AVPacket::size
int size
Definition: packet.h:525
av_image_fill_arrays
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], const uint8_t *src, enum AVPixelFormat pix_fmt, int width, int height, int align)
Setup the data pointers and linesizes based on the specified image parameters and the provided array.
Definition: imgutils.c:446
codec_internal.h
size
int size
Definition: twinvq_data.h:10344
atomic_fetch_add_explicit
#define atomic_fetch_add_explicit(object, operand, order)
Definition: stdatomic.h:149
FFBufferEntry::ref
AVBufferRef * ref
Definition: mmaldec.c:50
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
HW_CONFIG_INTERNAL
#define HW_CONFIG_INTERNAL(format)
Definition: hwconfig.h:54
ffmmal_read_frame
static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)
Definition: mmaldec.c:674
AVCodecHWConfigInternal
Definition: hwconfig.h:25
buffer.h
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:523
MMALDecodeContext::waiting_buffers_tail
FFBufferEntry * waiting_buffers_tail
Definition: mmaldec.c:87
av_packet_make_refcounted
int av_packet_make_refcounted(AVPacket *pkt)
Ensure the data described by a given packet is reference counted.
Definition: packet.c:490
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
AVCOL_SPC_SMPTE240M
@ AVCOL_SPC_SMPTE240M
derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries
Definition: pixfmt.h:617
log.h
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:517
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:523
MMALDecodeContext::extradata_sent
int extradata_sent
Definition: mmaldec.c:96
MMALDecodeContext::pool_out
FFPoolRef * pool_out
Definition: mmaldec.c:79
AVColorSpace
AVColorSpace
YUV colorspace type.
Definition: pixfmt.h:609
common.h
AVCodecInternal::in_pkt
AVPacket * in_pkt
This packet is used to hold the packet given to decoders implementing the .decode API; it is unused b...
Definition: internal.h:74
FFBufferEntry::dts
int64_t dts
Definition: mmaldec.c:53
MMALDecodeContext
Definition: mmaldec.c:71
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
AV_CODEC_ID_VC1
@ AV_CODEC_ID_VC1
Definition: codec_id.h:122
AVCOL_SPC_UNSPECIFIED
@ AVCOL_SPC_UNSPECIFIED
Definition: pixfmt.h:612
AVCodecContext::height
int height
Definition: avcodec.h:618
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:657
AV_FRAME_FLAG_INTERLACED
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition: frame.h:633
avcodec.h
FFPoolRef
Definition: mmaldec.c:61
ret
ret
Definition: filter_design.txt:187
MMALDecodeContext::extra_buffers
int extra_buffers
Definition: mmaldec.c:73
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
ffmal_update_format
static int ffmal_update_format(AVCodecContext *avctx)
Definition: mmaldec.c:282
MMALDecodeContext::pkt
AVPacket * pkt
Definition: mmaldec.c:89
ff_decode_frame_props
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
Set various frame properties from the codec context / packet data.
Definition: decode.c:1446
AVCodecContext
main external API structure.
Definition: avcodec.h:445
FFBufferEntry::data
void * data
Definition: mmaldec.c:51
status
ov_status_e status
Definition: dnn_backend_openvino.c:121
input_callback
static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
Definition: mmaldec.c:209
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
av_image_copy2
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
Definition: imgutils.h:184
MMALDecodeContext::waiting_buffers
FFBufferEntry * waiting_buffers
Definition: mmaldec.c:87
AVRational::den
int den
Denominator.
Definition: rational.h:60
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
atomic_fetch_add
#define atomic_fetch_add(object, operand)
Definition: stdatomic.h:131
AVCOL_SPC_FCC
@ AVCOL_SPC_FCC
FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
Definition: pixfmt.h:614
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
FFBufferEntry
Definition: mmaldec.c:49
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
MMALDecodeContext::packets_buffered
atomic_int packets_buffered
Definition: mmaldec.c:92
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
AVPacket
This structure stores compressed data.
Definition: packet.h:501
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
ffmmal_release_frame
static void ffmmal_release_frame(void *opaque, uint8_t *data)
Definition: mmaldec.c:118
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
imgutils.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
FFPoolRef::refcount
atomic_int refcount
Definition: mmaldec.c:62
h
h
Definition: vp9dsp_template.c:2038
ffmmal_add_packet
static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, int is_extradata)
Definition: mmaldec.c:490
atomic_init
#define atomic_init(obj, value)
Definition: stdatomic.h:33
FFBufferRef::pool
FFPoolRef * pool
Definition: mmaldec.c:68
MMALDecodeContext::eos_received
int eos_received
Definition: mmaldec.c:94
AVCOL_SPC_BT709
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
Definition: pixfmt.h:611
AV_CODEC_ID_MPEG2VIDEO
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition: codec_id.h:54
FFBufferRef
Definition: mmaldec.c:66
fourcc
uint32_t fourcc
Definition: vaapi_decode.c:240
FFBufferEntry::length
size_t length
Definition: mmaldec.c:52
ffmmal_dec_class
static const AVClass ffmmal_dec_class
Definition: mmaldec.c:831
AVCodecContext::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel.
Definition: avcodec.h:642
MMALDecodeContext::pool_in
MMAL_POOL_T * pool_in
Definition: mmaldec.c:78
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:345