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