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>
103#define MAX_DELAYED_FRAMES 16
113 mmal_pool_destroy(
ref->pool);
122 mmal_buffer_header_release(
ref->buffer);
131 MMAL_BUFFER_HEADER_T *
buffer)
143 if (!
frame->buf[0]) {
149 mmal_buffer_header_acquire(
buffer);
152 frame->data[3] = (uint8_t *)
ref->buffer;
160 MMAL_BUFFER_HEADER_T *
buffer;
162 mmal_port_disable(
decoder->input[0]);
163 mmal_port_disable(
decoder->output[0]);
164 mmal_port_disable(
decoder->control);
166 mmal_port_flush(
decoder->input[0]);
167 mmal_port_flush(
decoder->output[0]);
168 mmal_port_flush(
decoder->control);
170 while ((
buffer = mmal_queue_get(
ctx->queue_decoded_frames)))
171 mmal_buffer_header_release(
buffer);
173 while (
ctx->waiting_buffers) {
178 if (
buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
184 ctx->waiting_buffers_tail =
NULL;
188 ctx->frames_output =
ctx->eos_received =
ctx->eos_sent =
ctx->packets_sent =
ctx->extradata_sent = 0;
198 mmal_component_destroy(
ctx->decoder);
200 mmal_queue_destroy(
ctx->queue_decoded_frames);
201 mmal_pool_destroy(
ctx->pool_in);
217 if (
entry->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
221 mmal_buffer_header_release(
buffer);
229 mmal_queue_put(
ctx->queue_decoded_frames,
buffer);
235 MMAL_STATUS_T status;
237 if (
buffer->cmd == MMAL_EVENT_ERROR) {
238 status = *(uint32_t *)
buffer->data;
245 mmal_buffer_header_release(
buffer);
252 MMAL_BUFFER_HEADER_T *
buffer;
253 MMAL_STATUS_T status;
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);
272 case MMAL_COLOR_SPACE_BT470_2_BG:
273 case MMAL_COLOR_SPACE_BT470_2_M:
285 MMAL_STATUS_T status;
288 MMAL_ES_FORMAT_T *format_out =
decoder->output[0]->format;
289 MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type;
301 if ((status = mmal_port_parameter_set_uint32(
decoder->output[0], MMAL_PARAMETER_EXTRA_BUFFERS,
ctx->extra_buffers)))
304 if ((status = mmal_port_parameter_set_boolean(
decoder->output[0], MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0)))
308 format_out->encoding = MMAL_ENCODING_OPAQUE;
310 format_out->encoding_variant = format_out->encoding = MMAL_ENCODING_I420;
313 if ((status = mmal_port_format_commit(
decoder->output[0])))
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) {
322 ctx->interlaced_frame = (interlace_type.eMode != MMAL_InterlaceProgressive);
323 ctx->top_field_first = (interlace_type.eMode == MMAL_InterlaceFieldsInterleavedUpperFirst);
327 format_out->es->video.crop.y + format_out->es->video.crop.height)) < 0)
330 if (format_out->es->video.par.num && format_out->es->video.par.den) {
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;
341 decoder->output[0]->buffer_size =
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) {
361 MMAL_STATUS_T status;
362 MMAL_ES_FORMAT_T *format_in;
370 if (mmal_vc_init()) {
380 if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &
ctx->decoder)))
385 format_in =
decoder->input[0]->format;
386 format_in->type = MMAL_ES_TYPE_VIDEO;
389 format_in->encoding = MMAL_ENCODING_MP2V;
392 format_in->encoding = MMAL_ENCODING_MP4V;
395 format_in->encoding = MMAL_ENCODING_WVC1;
399 format_in->encoding = MMAL_ENCODING_H264;
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;
410 format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;
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)) {
422 if ((status = mmal_port_format_commit(
decoder->input[0])))
425 decoder->input[0]->buffer_num =
427 decoder->input[0]->buffer_size =
429 ctx->pool_in = mmal_pool_create(
decoder->input[0]->buffer_num, 0);
438 ctx->queue_decoded_frames = mmal_queue_create();
439 if (!
ctx->queue_decoded_frames)
442 decoder->input[0]->userdata = (
void*)avctx;
443 decoder->output[0]->userdata = (
void*)avctx;
444 decoder->control->userdata = (
void*)avctx;
453 if ((status = mmal_component_enable(
decoder)))
467 MMAL_STATUS_T status;
496 uint8_t *
data = (uint8_t *)
"";
512 if (!
ctx->packets_sent) {
515 ctx->eos_received = 1;
533 buffer->flags |= MMAL_BUFFER_HEADER_FLAG_CONFIG;
536 buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_START;
545 buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
550 buffer->flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
564 if (!
ctx->waiting_buffers)
566 if (
ctx->waiting_buffers_tail)
567 ctx->waiting_buffers_tail->next =
buffer;
581 while (
ctx->waiting_buffers) {
582 MMAL_BUFFER_HEADER_T *mbuffer;
584 MMAL_STATUS_T status;
586 mbuffer = mmal_queue_get(
ctx->pool_in->queue);
592 mmal_buffer_header_reset(mbuffer);
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;
605 ctx->waiting_buffers_tail =
NULL;
607 if ((status = mmal_port_send_buffer(
ctx->decoder->input[0], mbuffer))) {
608 mmal_buffer_header_release(mbuffer);
610 if (
buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
625 MMAL_BUFFER_HEADER_T *
buffer)
630 if (
ctx->interlaced_frame)
632 if (
ctx->top_field_first)
678 MMAL_STATUS_T status = 0;
681 if (
ctx->eos_received)
697 (
ctx->packets_sent &&
ctx->eos_sent)) {
702 buffer = mmal_queue_timedwait(
ctx->queue_decoded_frames, 100);
709 buffer = mmal_queue_get(
ctx->queue_decoded_frames);
714 ctx->eos_received |= !!(
buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS);
715 if (
ctx->eos_received)
718 if (
buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {
720 MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(
buffer);
721 MMAL_BUFFER_HEADER_T *stale_buffer;
725 if ((status = mmal_port_disable(
decoder->output[0])))
728 while ((stale_buffer = mmal_queue_get(
ctx->queue_decoded_frames)))
729 mmal_buffer_header_release(stale_buffer);
731 mmal_format_copy(
decoder->output[0]->format, ev->format);
745 mmal_buffer_header_release(
buffer);
751 }
else if (
buffer->length == 0) {
753 mmal_buffer_header_release(
buffer);
757 ctx->frames_output++;
768 mmal_buffer_header_release(
buffer);
769 if (status && ret >= 0)
784 ctx->extradata_sent = 1;
793 }
else if (ret < 0 && !(ret ==
AVERROR(EAGAIN)))
814 if (!got_frame && ret == 0)
827 {
"extra_decoder_buffers",
"extra MMAL internal buffered frames", offsetof(
MMALDecodeContext, extra_decoder_buffers),
AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0},
832 .class_name =
"mmal_dec",
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, \
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", \
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Libavcodec external API header.
refcounted data buffer API
common internal and external API header
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
Set various frame properties from the codec context / packet data.
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
Called by decoders to get the next packet for decoding.
int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
Select the (possibly hardware accelerated) pixel format.
int ff_set_dimensions(AVCodecContext *s, int width, int height)
#define atomic_fetch_add_explicit(object, operand, order)
#define atomic_load(object)
#define atomic_init(obj, value)
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
int av_packet_make_refcounted(AVPacket *pkt)
Ensure the data described by a given packet is reference counted.
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
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.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
#define av_fourcc2str(fourcc)
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.
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 ...
#define AV_NOPTS_VALUE
Undefined timestamp value.
#define LIBAVUTIL_VERSION_INT
#define HW_CONFIG_INTERNAL(format)
static const chunk_decoder decoder[8]
common internal api header.
Memory handling functions.
static av_cold int ffmmal_close_decoder(AVCodecContext *avctx)
static int ffmmal_fill_input_port(AVCodecContext *avctx)
static int ffmal_update_format(AVCodecContext *avctx)
static av_cold int ffmmal_init_decoder(AVCodecContext *avctx)
static void ffmmal_release_frame(void *opaque, uint8_t *data)
static void output_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
#define FFMMAL_DEC(NAME, ID)
static const AVClass ffmmal_dec_class
static void input_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
static int ffmmal_set_ref(AVFrame *frame, FFPoolRef *pool, MMAL_BUFFER_HEADER_T *buffer)
#define MAX_DELAYED_FRAMES
static int ffmal_copy_frame(AVCodecContext *avctx, AVFrame *frame, MMAL_BUFFER_HEADER_T *buffer)
static const AVCodecHWConfigInternal *const mmal_hw_configs[]
static void ffmmal_poolref_unref(FFPoolRef *ref)
static void ffmmal_stop_decoder(AVCodecContext *avctx)
static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)
static void ffmmal_flush(AVCodecContext *avctx)
static enum AVPixelFormat mmal_pixfmts[]
static enum AVColorSpace ffmmal_csp_to_av_csp(MMAL_FOURCC_T fourcc)
static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, int is_extradata)
static int ffmmal_fill_output_port(AVCodecContext *avctx)
static int ffmmal_receive_frame(AVCodecContext *avctx, AVFrame *frame)
static void control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
@ AV_PIX_FMT_MMAL
HW acceleration though MMAL, data[3] contains a pointer to the MMAL_BUFFER_HEADER_T structure.
AVColorSpace
YUV colorspace type.
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
@ AVCOL_SPC_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
@ AVCOL_SPC_FCC
FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
@ AVCOL_SPC_SMPTE240M
derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries
A reference to a data buffer.
Describe the class of an AVClass context structure.
main external API structure.
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int width
picture width / height.
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel.
enum AVColorSpace colorspace
YUV colorspace type.
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
struct AVCodecInternal * internal
Private context used for internal data.
AVPacket * in_pkt
This packet is used to hold the packet given to decoders implementing the .decode API; it is unused b...
This structure describes decoded (raw) audio or video data.
This structure stores compressed data.
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
struct FFBufferEntry * next
MMAL_BUFFER_HEADER_T * buffer
FFBufferEntry * waiting_buffers_tail
MMAL_QUEUE_T * queue_decoded_frames
FFBufferEntry * waiting_buffers
atomic_int packets_buffered
MMAL_COMPONENT_T * decoder
int extra_decoder_buffers
static int ref[MAX_W *MAX_W]
static AVFormatContext * ctx
#define atomic_fetch_add(object, operand)