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