1 /*
2 * OMX Video encoder
3 * Copyright (C) 2011 Martin Storsjo
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 #include "config.h"
23
24 #if CONFIG_OMX_RPI
25 #define OMX_SKIP64BIT
26 #endif
27
28 #include <dlfcn.h>
29 #include <OMX_Core.h>
30 #include <OMX_Component.h>
31 #include <pthread.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/time.h>
35
42
47
48 #ifdef OMX_SKIP64BIT
50 {
52 s.nLowPart =
value & 0xffffffff;
55 }
57 {
58 return (((int64_t)
value.nHighPart) << 32) |
value.nLowPart;
59 }
60 #else
61 #define to_omx_ticks(x) (x)
62 #define from_omx_ticks(x) (x)
63 #endif
64
65 #define INIT_STRUCT(x) do { \
66 x.nSize = sizeof(x); \
67 x.nVersion = s->version; \
68 } while (0)
69 #define CHECK(x) do { \
70 if (x != OMX_ErrorNone) { \
71 av_log(avctx, AV_LOG_ERROR, \
72 "err %x (%d) on line %d\n", x, x, __LINE__); \
73 return AVERROR_UNKNOWN; \
74 } \
75 } while (0)
76
83 OMX_ERRORTYPE (*
ptr_GetHandle)(OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*);
89
91 {
92 char buf[50];
93 snprintf(buf,
sizeof(buf),
"%s%s", prefix ? prefix :
"", symbol);
94 return dlsym(handle, buf);
95 }
96
98 const char *libname, const char *prefix,
99 const char *libname2)
100 {
101 if (libname2) {
102 s->lib2 = dlopen(libname2, RTLD_NOW | RTLD_GLOBAL);
106 }
107 s->host_init = dlsym(
s->lib2,
"bcm_host_init");
113 }
114 }
115 s->lib = dlopen(libname, RTLD_NOW | RTLD_GLOBAL);
119 }
122 s->ptr_ComponentNameEnum =
dlsym_prefixed(
s->lib,
"OMX_ComponentNameEnum", prefix);
125 s->ptr_GetComponentsOfRole =
dlsym_prefixed(
s->lib,
"OMX_GetComponentsOfRole", prefix);
126 s->ptr_GetRolesOfComponent =
dlsym_prefixed(
s->lib,
"OMX_GetRolesOfComponent", prefix);
127 if (!
s->ptr_Init || !
s->ptr_Deinit || !
s->ptr_ComponentNameEnum ||
128 !
s->ptr_GetHandle || !
s->ptr_FreeHandle ||
129 !
s->ptr_GetComponentsOfRole || !
s->ptr_GetRolesOfComponent) {
137 }
138 return 0;
139 }
140
142 {
143 static const char * const libnames[] = {
144 #if CONFIG_OMX_RPI
145 "/opt/vc/lib/libopenmaxil.so", "/opt/vc/lib/libbcm_host.so",
146 #else
147 "libOMX_Core.so",
NULL,
148 "libOmxCore.so",
NULL,
149 #endif
151 };
152 const char* const* nameptr;
155
156 omx_context =
av_mallocz(
sizeof(*omx_context));
157 if (!omx_context)
159 if (libname) {
164 }
165 } else {
166 for (nameptr = libnames; *nameptr; nameptr += 2)
167 if (!(
ret =
omx_try_load(omx_context, logctx, nameptr[0], prefix, nameptr[1])))
168 break;
169 if (!*nameptr) {
172 }
173 }
174
178 return omx_context;
179 }
180
182 {
183 if (!omx_context)
184 return;
186 dlclose(omx_context->
lib);
188 }
189
195
197
204
216
221
223
225
228
232
233 #define NB_MUTEX_CONDS 6
234 #define OFF(field) offsetof(OMXCodecContext, field)
236 (
OFF(input_mutex),
OFF(output_mutex),
OFF(state_mutex)),
237 (
OFF(input_cond),
OFF(output_cond),
OFF(state_cond)));
238
240 int* array_size, OMX_BUFFERHEADERTYPE **
array,
241 OMX_BUFFERHEADERTYPE *
buffer)
242 {
247 }
248
250 int* array_size, OMX_BUFFERHEADERTYPE **
array,
251 int wait)
252 {
253 OMX_BUFFERHEADERTYPE *
buffer;
255 if (wait) {
256 while (!*array_size)
258 }
259 if (*array_size > 0) {
261 (*array_size)--;
262 memmove(&
array[0], &
array[1], (*array_size) *
sizeof(OMX_BUFFERHEADERTYPE*));
263 } else {
265 }
268 }
269
270 static OMX_ERRORTYPE
event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, OMX_EVENTTYPE event,
271 OMX_U32 data1, OMX_U32 data2, OMX_PTR event_data)
272 {
274 // This uses casts in the printfs, since OMX_U32 actually is a typedef for
275 // unsigned long in official header versions (but there are also modified
276 // versions where it is something else).
277 switch (event) {
278 case OMX_EventError:
284 break;
285 case OMX_EventCmdComplete:
286 if (data1 == OMX_CommandStateSet) {
292 } else if (data1 == OMX_CommandPortDisable) {
294 } else if (data1 == OMX_CommandPortEnable) {
296 } else {
298 (uint32_t) data1, (uint32_t) data2);
299 }
300 break;
301 case OMX_EventPortSettingsChanged:
303 break;
304 default:
306 event, (uint32_t) data1, (uint32_t) data2);
307 break;
308 }
309 return OMX_ErrorNone;
310 }
311
313 OMX_BUFFERHEADERTYPE *
buffer)
314 {
316 if (
s->input_zerocopy) {
317 if (
buffer->pAppPrivate) {
318 if (
buffer->pOutputPortPrivate)
320 else
323 }
324 }
326 &
s->num_free_in_buffers,
s->free_in_buffers,
buffer);
327 return OMX_ErrorNone;
328 }
329
331 OMX_BUFFERHEADERTYPE *
buffer)
332 {
335 &
s->num_done_out_buffers,
s->done_out_buffers,
buffer);
336 return OMX_ErrorNone;
337 }
338
343 };
344
346 const char *role,
char *
str,
int str_size)
347 {
349 char **components;
351
352 #if CONFIG_OMX_RPI
355 return 0;
356 }
357 #endif
359 if (!num) {
362 }
363 components =
av_calloc(num,
sizeof(*components));
364 if (!components)
366 for (
i = 0;
i < num;
i++) {
367 components[
i] =
av_mallocz(OMX_MAX_STRINGNAME_SIZE);
368 if (!components[
i]) {
370 goto end;
371 }
372 }
375 end:
376 for (
i = 0;
i < num;
i++)
380 }
381
383 {
386 while (
s->state !=
state &&
s->error == OMX_ErrorNone)
388 if (
s->error != OMX_ErrorNone)
392 }
393
395 {
397 OMX_PARAM_COMPONENTROLETYPE role_params = { 0 };
398 OMX_PORT_PARAM_TYPE video_port_params = { 0 };
399 OMX_PARAM_PORTDEFINITIONTYPE in_port_params = { 0 }, out_port_params = { 0 };
400 OMX_VIDEO_PARAM_PORTFORMATTYPE video_port_format = { 0 };
401 OMX_VIDEO_PARAM_BITRATETYPE vid_param_bitrate = { 0 };
402 OMX_ERRORTYPE err;
404
405 s->version.s.nVersionMajor = 1;
406 s->version.s.nVersionMinor = 1;
407 s->version.s.nRevision = 2;
408
409 err =
s->omx_context->ptr_GetHandle(&
s->handle,
s->component_name,
s, (OMX_CALLBACKTYPE*) &
callbacks);
410 if (err != OMX_ErrorNone) {
413 }
414
415 // This one crashes the mediaserver on qcom, if used over IOMX
417 av_strlcpy(role_params.cRole, role,
sizeof(role_params.cRole));
418 // Intentionally ignore errors on this one
419 OMX_SetParameter(
s->handle, OMX_IndexParamStandardComponentRole, &role_params);
420
422 err = OMX_GetParameter(
s->handle, OMX_IndexParamVideoInit, &video_port_params);
424
425 s->in_port =
s->out_port = -1;
426 for (
i = 0;
i < video_port_params.nPorts;
i++) {
427 int port = video_port_params.nStartPortNumber +
i;
428 OMX_PARAM_PORTDEFINITIONTYPE port_params = { 0 };
430 port_params.nPortIndex = port;
431 err = OMX_GetParameter(
s->handle, OMX_IndexParamPortDefinition, &port_params);
432 if (err != OMX_ErrorNone) {
434 break;
435 }
436 if (port_params.eDir == OMX_DirInput &&
s->in_port < 0) {
437 in_port_params = port_params;
439 }
else if (port_params.eDir == OMX_DirOutput &&
s->out_port < 0) {
440 out_port_params = port_params;
442 }
443 }
444 if (
s->in_port < 0 ||
s->out_port < 0) {
445 av_log(avctx,
AV_LOG_ERROR,
"No in or out port found (in %d out %d)\n",
s->in_port,
s->out_port);
447 }
448
452 video_port_format.nIndex =
i;
453 video_port_format.nPortIndex =
s->in_port;
454 if (OMX_GetParameter(
s->handle, OMX_IndexParamVideoPortFormat, &video_port_format) != OMX_ErrorNone)
455 break;
456 if (video_port_format.eColorFormat == OMX_COLOR_FormatYUV420Planar ||
457 video_port_format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar) {
458 s->color_format = video_port_format.eColorFormat;
459 break;
460 }
461 }
462 if (
s->color_format == 0) {
465 }
466
467 in_port_params.bEnabled = OMX_TRUE;
468 in_port_params.bPopulated = OMX_FALSE;
469 in_port_params.eDomain = OMX_PortDomainVideo;
470
471 in_port_params.format.video.pNativeRender =
NULL;
472 in_port_params.format.video.bFlagErrorConcealment = OMX_FALSE;
473 in_port_params.format.video.eColorFormat =
s->color_format;
476 // If specific codecs need to manually override the stride/plane_size,
477 // that can be done here.
478 in_port_params.format.video.nStride =
s->stride;
479 in_port_params.format.video.nSliceHeight =
s->plane_size;
480 in_port_params.format.video.nFrameWidth = avctx->
width;
481 in_port_params.format.video.nFrameHeight = avctx->
height;
484 else
486
487 err = OMX_SetParameter(
s->handle, OMX_IndexParamPortDefinition, &in_port_params);
489 err = OMX_GetParameter(
s->handle, OMX_IndexParamPortDefinition, &in_port_params);
491 s->stride = in_port_params.format.video.nStride;
492 s->plane_size = in_port_params.format.video.nSliceHeight;
493 s->num_in_buffers = in_port_params.nBufferCountActual;
494
495 err = OMX_GetParameter(
s->handle, OMX_IndexParamPortDefinition, &out_port_params);
496 out_port_params.bEnabled = OMX_TRUE;
497 out_port_params.bPopulated = OMX_FALSE;
498 out_port_params.eDomain = OMX_PortDomainVideo;
499 out_port_params.format.video.pNativeRender =
NULL;
500 out_port_params.format.video.nFrameWidth = avctx->
width;
501 out_port_params.format.video.nFrameHeight = avctx->
height;
502 out_port_params.format.video.nStride = 0;
503 out_port_params.format.video.nSliceHeight = 0;
504 out_port_params.format.video.nBitrate = avctx->
bit_rate;
505 out_port_params.format.video.xFramerate = in_port_params.format.video.xFramerate;
506 out_port_params.format.video.bFlagErrorConcealment = OMX_FALSE;
508 out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
510 out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
511
512 err = OMX_SetParameter(
s->handle, OMX_IndexParamPortDefinition, &out_port_params);
514 err = OMX_GetParameter(
s->handle, OMX_IndexParamPortDefinition, &out_port_params);
516 s->num_out_buffers = out_port_params.nBufferCountActual;
517
519 vid_param_bitrate.nPortIndex =
s->out_port;
520 vid_param_bitrate.eControlRate = OMX_Video_ControlRateVariable;
521 vid_param_bitrate.nTargetBitrate = avctx->
bit_rate;
522 err = OMX_SetParameter(
s->handle, OMX_IndexParamVideoBitrate, &vid_param_bitrate);
523 if (err != OMX_ErrorNone)
525
527 OMX_VIDEO_PARAM_AVCTYPE avc = { 0 };
529 avc.nPortIndex =
s->out_port;
530 err = OMX_GetParameter(
s->handle, OMX_IndexParamVideoAvc, &avc);
532 avc.nBFrames = 0;
536 avc.eProfile = OMX_VIDEO_AVCProfileBaseline;
537 break;
539 avc.eProfile = OMX_VIDEO_AVCProfileMain;
540 break;
542 avc.eProfile = OMX_VIDEO_AVCProfileHigh;
543 break;
544 default:
545 break;
546 }
547 err = OMX_SetParameter(
s->handle, OMX_IndexParamVideoAvc, &avc);
549 }
550
551 err = OMX_SendCommand(
s->handle, OMX_CommandStateSet, OMX_StateIdle,
NULL);
553
554 s->in_buffer_headers =
av_mallocz(
sizeof(OMX_BUFFERHEADERTYPE*) *
s->num_in_buffers);
555 s->free_in_buffers =
av_mallocz(
sizeof(OMX_BUFFERHEADERTYPE*) *
s->num_in_buffers);
556 s->out_buffer_headers =
av_mallocz(
sizeof(OMX_BUFFERHEADERTYPE*) *
s->num_out_buffers);
557 s->done_out_buffers =
av_mallocz(
sizeof(OMX_BUFFERHEADERTYPE*) *
s->num_out_buffers);
558 if (!
s->in_buffer_headers || !
s->free_in_buffers || !
s->out_buffer_headers || !
s->done_out_buffers)
560 for (
i = 0;
i <
s->num_in_buffers && err == OMX_ErrorNone;
i++) {
561 if (
s->input_zerocopy)
562 err = OMX_UseBuffer(
s->handle, &
s->in_buffer_headers[
i],
s->in_port,
s, in_port_params.nBufferSize,
NULL);
563 else
564 err = OMX_AllocateBuffer(
s->handle, &
s->in_buffer_headers[
i],
s->in_port,
s, in_port_params.nBufferSize);
565 if (err == OMX_ErrorNone)
566 s->in_buffer_headers[
i]->pAppPrivate =
s->in_buffer_headers[
i]->pOutputPortPrivate =
NULL;
567 }
569 s->num_in_buffers =
i;
570 for (
i = 0;
i <
s->num_out_buffers && err == OMX_ErrorNone;
i++)
571 err = OMX_AllocateBuffer(
s->handle, &
s->out_buffer_headers[
i],
s->out_port,
s, out_port_params.nBufferSize);
573 s->num_out_buffers =
i;
574
578 }
579 err = OMX_SendCommand(
s->handle, OMX_CommandStateSet, OMX_StateExecuting,
NULL);
584 }
585
586 for (
i = 0;
i <
s->num_out_buffers && err == OMX_ErrorNone;
i++)
587 err = OMX_FillThisBuffer(
s->handle,
s->out_buffer_headers[
i]);
588 if (err != OMX_ErrorNone) {
589 for (;
i <
s->num_out_buffers;
i++)
590 s->done_out_buffers[
s->num_done_out_buffers++] =
s->out_buffer_headers[
i];
591 }
592 for (
i = 0;
i <
s->num_in_buffers;
i++)
593 s->free_in_buffers[
s->num_free_in_buffers++] =
s->in_buffer_headers[
i];
595 }
596
598 {
599 int executing;
600
601 /* If the mutexes/condition variables have not been properly initialized,
602 * nothing has been initialized and locking the mutex might be unsafe. */
605 executing =
s->state == OMX_StateExecuting;
607
608 if (executing) {
609 OMX_SendCommand(
s->handle, OMX_CommandStateSet, OMX_StateIdle,
NULL);
611 OMX_SendCommand(
s->handle, OMX_CommandStateSet, OMX_StateLoaded,
NULL);
612 for (
int i = 0;
i <
s->num_in_buffers;
i++) {
614 &
s->num_free_in_buffers,
s->free_in_buffers, 1);
615 if (
s->input_zerocopy)
617 OMX_FreeBuffer(
s->handle,
s->in_port,
buffer);
618 }
619 for (
int i = 0;
i <
s->num_out_buffers;
i++) {
621 &
s->num_done_out_buffers,
s->done_out_buffers, 1);
622 OMX_FreeBuffer(
s->handle,
s->out_port,
buffer);
623 }
625 }
627 s->omx_context->ptr_FreeHandle(
s->handle);
629 }
630
632 s->omx_context =
NULL;
638 }
640 }
641
643 {
646 const char *role;
647 OMX_BUFFERHEADERTYPE *
buffer;
648 OMX_ERRORTYPE err;
649
650 /* cleanup relies on the mutexes/conditions being initialized first. */
654 s->omx_context =
omx_init(avctx,
s->libname,
s->libprefix);
657
659 s->state = OMX_StateLoaded;
660 s->error = OMX_ErrorNone;
661
664 role = "video_encoder.mpeg4";
665 break;
667 role = "video_encoder.avc";
668 break;
669 default:
671 }
672
673 if ((
ret =
find_component(
s->omx_context, avctx, role,
s->component_name,
sizeof(
s->component_name))) < 0)
675
677
680
682 while (1) {
684 &
s->num_done_out_buffers,
s->done_out_buffers, 1);
685 if (
buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
689 }
693 }
694 err = OMX_FillThisBuffer(
s->handle,
buffer);
695 if (err != OMX_ErrorNone) {
697 &
s->num_done_out_buffers,
s->done_out_buffers,
buffer);
701 }
703 // For H.264, the extradata can be returned in two separate buffers
704 // (the videocore encoder on raspberry pi does this);
705 // therefore check that we have got both SPS and PPS before continuing.
706 int nals[32] = { 0 };
714 }
715 }
717 break;
718 } else {
720 break;
721 }
722 }
723 }
724
725 return 0;
728 }
729
730
733 {
736 OMX_BUFFERHEADERTYPE*
buffer;
737 OMX_ERRORTYPE err;
738 int had_partial = 0;
739
741 uint8_t *dst[4];
742 int linesize[4];
743 int need_copy;
745 &
s->num_free_in_buffers,
s->free_in_buffers, 1);
746
748
749 if (
s->input_zerocopy) {
751 int src_linesize[4];
753 if (
frame->linesize[0] == src_linesize[0] &&
754 frame->linesize[1] == src_linesize[1] &&
755 frame->linesize[2] == src_linesize[2] &&
758 // If the input frame happens to have all planes stored contiguously,
759 // with the right strides, just clone the frame and set the OMX
760 // buffer header to point to it
762 if (!local) {
763 // Return the buffer to the queue so it's not lost
766 } else {
767 buffer->pAppPrivate = local;
770 need_copy = 0;
771 }
772 } else {
773 // If not, we need to allocate a new buffer with the right
774 // size and copy the input frame into it.
777 if (image_buffer_size >= 0)
779 if (!buf) {
780 // Return the buffer to the queue so it's not lost
783 } else {
784 buffer->pAppPrivate = buf;
785 // Mark that pAppPrivate is an av_malloc'ed buffer, not an AVFrame
786 buffer->pOutputPortPrivate = (
void*) 1;
788 need_copy = 1;
790 }
791 }
792 } else {
793 need_copy = 1;
794 }
795 if (need_copy)
797 buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
799 // Convert the timestamps to microseconds; some encoders can ignore
800 // the framerate and do VFR bit allocation based on timestamps.
803 #if CONFIG_OMX_RPI
804 OMX_CONFIG_BOOLEANTYPE
config = {0, };
806 config.bEnabled = OMX_TRUE;
807 err = OMX_SetConfig(
s->handle, OMX_IndexConfigBrcmVideoRequestIFrame, &
config);
808 if (err != OMX_ErrorNone) {
810 }
811 #else
812 OMX_CONFIG_INTRAREFRESHVOPTYPE
config = {0, };
814 config.nPortIndex =
s->out_port;
815 config.IntraRefreshVOP = OMX_TRUE;
816 err = OMX_SetConfig(
s->handle, OMX_IndexConfigVideoIntraVOPRefresh, &
config);
817 if (err != OMX_ErrorNone) {
819 }
820 #endif
821 }
822 err = OMX_EmptyThisBuffer(
s->handle,
buffer);
823 if (err != OMX_ErrorNone) {
827 }
828 }
else if (!
s->eos_sent) {
830 &
s->num_free_in_buffers,
s->free_in_buffers, 1);
831
833 buffer->nFlags = OMX_BUFFERFLAG_EOS;
835 err = OMX_EmptyThisBuffer(
s->handle,
buffer);
836 if (err != OMX_ErrorNone) {
840 }
842 }
843
844 while (!*got_packet &&
ret == 0 && !
s->got_eos) {
845 // If not flushing, just poll the queue if there's finished packets.
846 // If flushing, do a blocking wait until we either get a completed
847 // packet, or get EOS.
849 &
s->num_done_out_buffers,
s->done_out_buffers,
850 !
frame || had_partial);
852 break;
853
854 if (
buffer->nFlags & OMX_BUFFERFLAG_EOS)
856
860 goto end;
861 }
865 } else {
868 s->output_buf_size = 0;
869 goto end;
870 }
871 memcpy(
s->output_buf +
s->output_buf_size,
buffer->pBuffer +
buffer->nOffset,
buffer->nFilledLen);
872 s->output_buf_size +=
buffer->nFilledLen;
873 if (
buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) {
877 s->output_buf_size = 0;
878 goto end;
879 }
880 s->output_buf =
NULL;
881 s->output_buf_size = 0;
883 // We don't currently enable B-frames for the encoders, so set
884 // pkt->dts = pkt->pts. (The calling code behaves worse if the encoder
885 // doesn't set the dts).
887 if (
buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME)
889 *got_packet = 1;
890 } else {
891 #if CONFIG_OMX_RPI
892 had_partial = 1;
893 #endif
894 }
895 }
896 end:
897 err = OMX_FillThisBuffer(
s->handle,
buffer);
898 if (err != OMX_ErrorNone) {
902 }
903 }
905 }
906
908 {
910
912 return 0;
913 }
914
915 #define OFFSET(x) offsetof(OMXCodecContext, x)
916 #define VDE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM
917 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
921 {
"zerocopy",
"Try to avoid copying input frames if possible",
OFFSET(input_zerocopy),
AV_OPT_TYPE_INT, { .i64 = CONFIG_OMX_RPI }, 0, 1,
VE },
927 };
928
931 };
932
938 };
940 .
p.
name =
"mpeg4_omx",
952 };
953
959 };
961 .
p.
name =
"h264_omx",
973 };