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>
99 #define MAX_DELAYED_FRAMES 16
105 mmal_pool_destroy(
ref->pool);
114 mmal_buffer_header_release(
ref->buffer);
123 MMAL_BUFFER_HEADER_T *
buffer)
135 if (!
frame->buf[0]) {
141 mmal_buffer_header_acquire(
buffer);
152 MMAL_BUFFER_HEADER_T *
buffer;
154 mmal_port_disable(
decoder->input[0]);
155 mmal_port_disable(
decoder->output[0]);
156 mmal_port_disable(
decoder->control);
158 mmal_port_flush(
decoder->input[0]);
159 mmal_port_flush(
decoder->output[0]);
160 mmal_port_flush(
decoder->control);
162 while ((
buffer = mmal_queue_get(
ctx->queue_decoded_frames)))
163 mmal_buffer_header_release(
buffer);
165 while (
ctx->waiting_buffers) {
170 if (
buffer->
flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
176 ctx->waiting_buffers_tail =
NULL;
180 ctx->frames_output =
ctx->eos_received =
ctx->eos_sent =
ctx->packets_sent =
ctx->extradata_sent = 0;
190 mmal_component_destroy(
ctx->decoder);
192 mmal_queue_destroy(
ctx->queue_decoded_frames);
193 mmal_pool_destroy(
ctx->pool_in);
209 if (entry->
flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
213 mmal_buffer_header_release(
buffer);
221 mmal_queue_put(
ctx->queue_decoded_frames,
buffer);
229 if (
buffer->cmd == MMAL_EVENT_ERROR) {
237 mmal_buffer_header_release(
buffer);
244 MMAL_BUFFER_HEADER_T *
buffer;
250 while ((
buffer = mmal_queue_get(
ctx->pool_out->pool->queue))) {
251 if ((
status = mmal_port_send_buffer(
ctx->decoder->output[0],
buffer))) {
252 mmal_buffer_header_release(
buffer);
264 case MMAL_COLOR_SPACE_BT470_2_BG:
265 case MMAL_COLOR_SPACE_BT470_2_M:
280 MMAL_ES_FORMAT_T *format_out =
decoder->output[0]->format;
281 MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type;
293 if ((
status = mmal_port_parameter_set_uint32(
decoder->output[0], MMAL_PARAMETER_EXTRA_BUFFERS,
ctx->extra_buffers)))
296 if ((
status = mmal_port_parameter_set_boolean(
decoder->output[0], MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0)))
300 format_out->encoding = MMAL_ENCODING_OPAQUE;
302 format_out->encoding_variant = format_out->encoding = MMAL_ENCODING_I420;
308 interlace_type.hdr.id = MMAL_PARAMETER_VIDEO_INTERLACE_TYPE;
309 interlace_type.hdr.size =
sizeof(MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T);
310 status = mmal_port_parameter_get(
decoder->output[0], &interlace_type.hdr);
311 if (
status != MMAL_SUCCESS) {
314 ctx->interlaced_frame = (interlace_type.eMode != MMAL_InterlaceProgressive);
315 ctx->top_field_first = (interlace_type.eMode == MMAL_InterlaceFieldsInterleavedUpperFirst);
319 format_out->es->video.crop.y + format_out->es->video.crop.height)) < 0)
322 if (format_out->es->video.par.num && format_out->es->video.par.den) {
326 if (format_out->es->video.frame_rate.num && format_out->es->video.frame_rate.den) {
327 avctx->
framerate.
num = format_out->es->video.frame_rate.num;
328 avctx->
framerate.
den = format_out->es->video.frame_rate.den;
333 decoder->output[0]->buffer_size =
335 decoder->output[0]->buffer_num =
336 FFMAX(
decoder->output[0]->buffer_num_min,
decoder->output[0]->buffer_num_recommended) +
ctx->extra_buffers;
337 ctx->pool_out->pool = mmal_pool_create(
decoder->output[0]->buffer_num,
338 decoder->output[0]->buffer_size);
339 if (!
ctx->pool_out->pool) {
354 MMAL_ES_FORMAT_T *format_in;
360 if (mmal_vc_init()) {
370 if ((
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &
ctx->decoder)))
375 format_in =
decoder->input[0]->format;
376 format_in->type = MMAL_ES_TYPE_VIDEO;
379 format_in->encoding = MMAL_ENCODING_MP2V;
382 format_in->encoding = MMAL_ENCODING_MP4V;
385 format_in->encoding = MMAL_ENCODING_WVC1;
389 format_in->encoding = MMAL_ENCODING_H264;
394 format_in->es->video.crop.width = avctx->
width;
395 format_in->es->video.crop.height = avctx->
height;
396 format_in->es->video.frame_rate.num = 24000;
397 format_in->es->video.frame_rate.den = 1001;
400 format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;
405 #if HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS
406 if (mmal_port_parameter_set_uint32(
decoder->input[0], MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS,
407 -1 -
ctx->extra_decoder_buffers)) {
415 decoder->input[0]->buffer_num =
417 decoder->input[0]->buffer_size =
419 ctx->pool_in = mmal_pool_create(
decoder->input[0]->buffer_num, 0);
428 ctx->queue_decoded_frames = mmal_queue_create();
429 if (!
ctx->queue_decoded_frames)
432 decoder->input[0]->userdata = (
void*)avctx;
433 decoder->output[0]->userdata = (
void*)avctx;
434 decoder->control->userdata = (
void*)avctx;
512 if (!
ctx->packets_sent) {
515 ctx->eos_received = 1;
536 buffer->
flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_START;
545 buffer->
flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
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;
586 mbuffer = mmal_queue_get(
ctx->pool_in->queue);
592 mmal_buffer_header_reset(mbuffer);
595 mbuffer->dts =
buffer->dts;
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 frame->interlaced_frame =
ctx->interlaced_frame;
631 frame->top_field_first =
ctx->top_field_first;
678 if (
ctx->eos_received)
694 (
ctx->packets_sent &&
ctx->eos_sent)) {
699 buffer = mmal_queue_timedwait(
ctx->queue_decoded_frames, 100);
706 buffer = mmal_queue_get(
ctx->queue_decoded_frames);
711 ctx->eos_received |= !!(
buffer->
flags & MMAL_BUFFER_HEADER_FLAG_EOS);
712 if (
ctx->eos_received)
715 if (
buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {
717 MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(
buffer);
718 MMAL_BUFFER_HEADER_T *stale_buffer;
725 while ((stale_buffer = mmal_queue_get(
ctx->queue_decoded_frames)))
726 mmal_buffer_header_release(stale_buffer);
728 mmal_format_copy(
decoder->output[0]->format, ev->format);
742 mmal_buffer_header_release(
buffer);
748 }
else if (
buffer->length == 0) {
750 mmal_buffer_header_release(
buffer);
754 ctx->frames_output++;
765 mmal_buffer_header_release(
buffer);
783 ctx->extradata_sent = 1;
819 {
"extra_decoder_buffers",
"extra MMAL internal buffered frames", offsetof(
MMALDecodeContext, extra_decoder_buffers),
AV_OPT_TYPE_INT, {.i64 = 10}, 0, 256, 0},
823 #define FFMMAL_DEC_CLASS(NAME) \
824 static const AVClass ffmmal_##NAME##_dec_class = { \
825 .class_name = "mmal_" #NAME "_dec", \
826 .item_name = av_default_item_name, \
828 .version = LIBAVUTIL_VERSION_INT, \
831 #define FFMMAL_DEC(NAME, ID) \
832 FFMMAL_DEC_CLASS(NAME) \
833 AVCodec ff_##NAME##_mmal_decoder = { \
834 .name = #NAME "_mmal", \
835 .long_name = NULL_IF_CONFIG_SMALL(#NAME " (mmal)"), \
836 .type = AVMEDIA_TYPE_VIDEO, \
838 .priv_data_size = sizeof(MMALDecodeContext), \
839 .init = ffmmal_init_decoder, \
840 .close = ffmmal_close_decoder, \
841 .decode = ffmmal_decode, \
842 .flush = ffmmal_flush, \
843 .priv_class = &ffmmal_##NAME##_dec_class, \
844 .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \
845 .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \
846 .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MMAL, \
847 AV_PIX_FMT_YUV420P, \
849 .hw_configs = mmal_hw_configs, \
850 .wrapper_name = "mmal", \