0017-FFmpeg-omxdec-add-mirror-rotation-and-crop-option.patch 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. From 0c7df7e92eb46143fabeefd42af3023e6b7fc53f Mon Sep 17 00:00:00 2001
  2. From: "arvin.zhu" <arvin.zhu@starfivetech.com>
  3. Date: Fri, 21 Oct 2022 10:39:31 +0800
  4. Subject: [PATCH] FFmpeg:omxdec: add mirror rotation and crop option
  5. add mirror rotation and crop option for mjpeg_omx decoder
  6. Signed-off-by: arvin.zhu <arvin.zhu@starfivetech.com>
  7. ---
  8. libavcodec/omxdec.c | 181 +++++++++++++++++++++++++++++++++++---------
  9. 1 file changed, 146 insertions(+), 35 deletions(-)
  10. diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c
  11. index 87e5a1a..b4a7c96 100755
  12. --- a/libavcodec/omxdec.c
  13. +++ b/libavcodec/omxdec.c
  14. @@ -276,6 +276,15 @@ typedef struct OMXCodecContext {
  15. OMX_U32 scale_width;
  16. OMX_U32 scale_height;
  17. + OMX_U32 rotation;
  18. + OMX_U32 mirror;
  19. + char *crop_expr;
  20. + struct {
  21. + int x;
  22. + int y;
  23. + int w;
  24. + int h;
  25. + } crop;
  26. int input_zerocopy;
  27. int profile;
  28. @@ -359,7 +368,6 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O
  29. av_log(s->avctx, AV_LOG_ERROR, "err %d\n",err);
  30. return AVERROR_UNKNOWN;
  31. }
  32. -
  33. for (i = 0; i < video_port_params.nPorts; i++) {
  34. int port = video_port_params.nStartPortNumber + i;
  35. OMX_PARAM_PORTDEFINITIONTYPE port_params = { 0 };
  36. @@ -571,7 +579,7 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
  37. out_port_params.format.video.nBitrate = avctx->bit_rate;
  38. out_port_params.format.video.xFramerate = in_port_params.format.video.xFramerate;
  39. out_port_params.format.video.bFlagErrorConcealment = OMX_FALSE;
  40. - av_log(avctx, AV_LOG_VERBOSE, "OMX setting pixel_format:%s\n", s->pixel_format);
  41. +
  42. if (avctx->codec->id == AV_CODEC_ID_MPEG4)
  43. out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
  44. else if (avctx->codec->id == AV_CODEC_ID_H264) {
  45. @@ -580,12 +588,12 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
  46. else if (avctx->codec->id == AV_CODEC_ID_HEVC) {
  47. out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC;
  48. }
  49. - else if (avctx->codec->id == AV_CODEC_ID_MJPEG){
  50. + else if (avctx->codec->id == AV_CODEC_ID_MJPEG) {
  51. out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG;
  52. /* Set Scale config setting*/
  53. if (s->scale_width || s->scale_height) {
  54. - av_log(avctx, AV_LOG_TRACE, "mjpeg decoder: scaling width: %ld scaling height: %ld .\n", s->scale_width, s->scale_height);
  55. + av_log(avctx, AV_LOG_TRACE, "mjpeg decoder: scaling width: %d scaling height: %d .\n", s->scale_width, s->scale_height);
  56. OMX_CONFIG_SCALEFACTORTYPE ScaleConfig;
  57. INIT_STRUCT(ScaleConfig);
  58. ScaleConfig.nPortIndex = 1;
  59. @@ -599,38 +607,138 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
  60. out_port_params.format.video.nFrameHeight = avctx->height;
  61. }
  62. - switch (av_get_pix_fmt(s->pixel_format)) {
  63. - case AV_PIX_FMT_NV12:
  64. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
  65. - break;
  66. - case AV_PIX_FMT_NV21:
  67. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYVU420SemiPlanar;
  68. - break;
  69. - case AV_PIX_FMT_YUV420P:
  70. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
  71. - break;
  72. - case AV_PIX_FMT_NV16:
  73. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422SemiPlanar;
  74. - break;
  75. - case AV_PIX_FMT_YUV422P:
  76. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422Planar;
  77. - break;
  78. - case AV_PIX_FMT_YUYV422:
  79. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYCbYCr;
  80. - break;
  81. - case AV_PIX_FMT_YVYU422:
  82. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYCrYCb;
  83. - break;
  84. - case AV_PIX_FMT_UYVY422:
  85. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatCbYCrY;
  86. - break;
  87. - case AV_PIX_FMT_YUV444P:
  88. - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV444Planar;
  89. - break;
  90. - default:
  91. + /* Set pixel format to decoder output*/
  92. + if (s->pixel_format) {
  93. + switch (av_get_pix_fmt(s->pixel_format)) {
  94. + case AV_PIX_FMT_NV12:
  95. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
  96. + break;
  97. + case AV_PIX_FMT_NV21:
  98. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYVU420SemiPlanar;
  99. + break;
  100. + case AV_PIX_FMT_YUV420P:
  101. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
  102. + break;
  103. + case AV_PIX_FMT_NV16:
  104. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422SemiPlanar;
  105. + break;
  106. + case AV_PIX_FMT_YUV422P:
  107. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422Planar;
  108. + break;
  109. + case AV_PIX_FMT_YUYV422:
  110. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYCbYCr;
  111. + break;
  112. + case AV_PIX_FMT_YVYU422:
  113. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYCrYCb;
  114. + break;
  115. + case AV_PIX_FMT_UYVY422:
  116. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatCbYCrY;
  117. + break;
  118. + case AV_PIX_FMT_YUV444P:
  119. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV444Planar;
  120. + break;
  121. + default:
  122. + return AVERROR_OPTION_NOT_FOUND;
  123. + }
  124. + av_log(avctx, AV_LOG_VERBOSE, "OMX setting pixel_format:%s\n", s->pixel_format);
  125. + } else {
  126. + switch (avctx->pix_fmt) {
  127. + case AV_PIX_FMT_YUVJ420P:
  128. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
  129. + break;
  130. + case AV_PIX_FMT_YUVJ422P:
  131. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422Planar;
  132. + break;
  133. + case AV_PIX_FMT_YUVJ444P:
  134. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV444Planar;
  135. + break;
  136. + default:
  137. + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
  138. + break;
  139. + }
  140. + }
  141. +
  142. + /* Set Mirror config setting*/
  143. + if (s->mirror) {
  144. + if (s->pixel_format || s->scale_width || s->scale_height || s->rotation) {
  145. + av_log(avctx, AV_LOG_ERROR, "Mirror cannot work with other option together.\n");
  146. + return AVERROR_INVALIDDATA;
  147. + }
  148. + av_log(avctx, AV_LOG_TRACE, "mjpeg decoder: mirror\n");
  149. + OMX_CONFIG_MIRRORTYPE MirrorConfig;
  150. + INIT_STRUCT(MirrorConfig);
  151. + MirrorConfig.nPortIndex = 1;
  152. + OMX_GetConfig(s->handle, OMX_IndexConfigCommonMirror, &MirrorConfig);
  153. + MirrorConfig.eMirror = s->mirror;
  154. + OMX_SetConfig(s->handle, OMX_IndexConfigCommonMirror, &MirrorConfig);
  155. + }
  156. +
  157. + /* Set Rotation config setting*/
  158. + if (s->rotation) {
  159. + if (s->pixel_format || s->scale_width || s->scale_height || s->mirror) {
  160. + av_log(avctx, AV_LOG_ERROR, "Rotation cannot work with other option together.\n");
  161. + return AVERROR_INVALIDDATA;
  162. + }
  163. + av_log(avctx, AV_LOG_TRACE, "mjpeg decoder: rotation\n");
  164. + OMX_CONFIG_ROTATIONTYPE RotatConfig;
  165. + INIT_STRUCT(RotatConfig);
  166. + RotatConfig.nPortIndex = 1;
  167. + OMX_GetConfig(s->handle, OMX_IndexConfigCommonRotate, &RotatConfig);
  168. + switch (s->rotation) {
  169. + case 1:
  170. + RotatConfig.nRotation = 90;
  171. + break;
  172. + case 2:
  173. + RotatConfig.nRotation = 180;
  174. + break;
  175. + case 3:
  176. + RotatConfig.nRotation = 270;
  177. + break;
  178. + default:
  179. + RotatConfig.nRotation = 0;
  180. + break;
  181. + }
  182. + OMX_SetConfig(s->handle, OMX_IndexConfigCommonRotate, &RotatConfig);
  183. + }
  184. +
  185. + /* Set Roi config setting*/
  186. + if (s->crop_expr && sscanf(s->crop_expr, "%d,%d,%d,%d",
  187. + &s->crop.x, &s->crop.y,
  188. + &s->crop.w, &s->crop.h) != 4) {
  189. + av_log(avctx, AV_LOG_ERROR, "Invalid cropping expressions.\n");
  190. return AVERROR_OPTION_NOT_FOUND;
  191. }
  192. +
  193. + if (s->crop.w && s->crop.h) {
  194. + if (s->pixel_format || s->scale_width || s->scale_height || s->mirror || s->rotation) {
  195. + av_log(avctx, AV_LOG_ERROR, "Crop cannot work with other option together.\n");
  196. + return AVERROR_INVALIDDATA;
  197. + }
  198. + if ((s->crop.x < 0) || (s->crop.x > (avctx->width - s->crop.w)) ||
  199. + (s->crop.y < 0) || (s->crop.y > (avctx->height - s->crop.h)) ||
  200. + (s->crop.w < 16) || (s->crop.w > (avctx->width - s->crop.x)) ||
  201. + (s->crop.h < 16) || (s->crop.h > (avctx->height - s->crop.y))) {
  202. + av_log(avctx, AV_LOG_ERROR, "Invalid cropping range.\n");
  203. + return AVERROR_INVALIDDATA;
  204. + }
  205. + if (s->crop.w % 16 != 0 || s->crop.h % 16 != 0) {
  206. + av_log(avctx, AV_LOG_ERROR, "The width/height must be an integer multiple of 16\n");
  207. + return AVERROR_INVALIDDATA;
  208. + }
  209. +
  210. + OMX_CONFIG_RECTTYPE RectConfig;
  211. + INIT_STRUCT(RectConfig);
  212. + RectConfig.nPortIndex = 1;
  213. + OMX_GetConfig(s->handle, OMX_IndexConfigCommonOutputCrop, &RectConfig);
  214. + RectConfig.nLeft = s->crop.x;
  215. + RectConfig.nTop = s->crop.y;
  216. + RectConfig.nWidth = s->crop.w;
  217. + RectConfig.nHeight = s->crop.h;
  218. + OMX_SetConfig(s->handle, OMX_IndexConfigCommonOutputCrop, &RectConfig);
  219. + av_log(avctx, AV_LOG_ERROR, "mjpeg decoder:roi x: %d y: %d w: %d h: %d .\n", s->crop.x, s->crop.y, s->crop.w, s->crop.h);
  220. + }
  221. }
  222. +
  223. if (avctx->codec->id == AV_CODEC_ID_H264 || avctx->codec->id == AV_CODEC_ID_HEVC) {
  224. /* Set Scale config setting*/
  225. if ((s->scale_width != 0) && ((s->scale_width < avctx->width/8) ||
  226. @@ -675,6 +783,7 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
  227. s->done_out_buffers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers);
  228. if (!s->in_buffer_headers || !s->free_in_buffers || !s->out_buffer_headers || !s->done_out_buffers)
  229. return AVERROR(ENOMEM);
  230. +
  231. for (i = 0; i < s->num_in_buffers && err == OMX_ErrorNone; i++) {
  232. if (s->input_zerocopy)
  233. err = OMX_UseBuffer(s->handle, &s->in_buffer_headers[i], s->in_port, s, in_port_params.nBufferSize, NULL);
  234. @@ -699,7 +808,6 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
  235. av_log(avctx, AV_LOG_ERROR, "Didn't get OMX_StateExecuting\n");
  236. return AVERROR_UNKNOWN;
  237. }
  238. -
  239. for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++)
  240. err = OMX_FillThisBuffer(s->handle, s->out_buffer_headers[i]);
  241. if (err != OMX_ErrorNone) {
  242. @@ -1055,9 +1163,12 @@ static const AVOption options_mjpeg[] = {
  243. { "omx_libname", "OpenMAX library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
  244. { "omx_libprefix", "OpenMAX library prefix", OFFSET(libprefix), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
  245. { "zerocopy", "Try to avoid copying input frames if possible", OFFSET(input_zerocopy), AV_OPT_TYPE_INT, { .i64 = CONFIG_OMX_RPI }, 0, 1, VD },
  246. - { "omx_pix_fmt", "Set the decoding pixel format for mjpeg_omx decoder. The following formats are supported: yuv420p, nv12, nv21, nv16, yuv422p, yuyv422, yvyu422, uyvy422, yuv444p.", OFFSET(pixel_format), AV_OPT_TYPE_STRING, { .str = "yuv420p" }, 0, 0, VD },
  247. + { "omx_pix_fmt", "Set the decoding pixel format for mjpeg_omx decoder. The following formats are supported: yuv420p, nv12, nv21, nv16, yuv422p, yuyv422, yvyu422, uyvy422, yuv444p.", OFFSET(pixel_format), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD },
  248. { "scale_width", "Set the scaling width for omx (Only zoom out is support, Horizontal downscale: 0(none), 1(1/2), 2(1/4), 3(1/8)) and minimum 1/8)", OFFSET(scale_width), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, VD },
  249. { "scale_height", "Set the scaling height for omx (Only zoom out is support, Vertical downscale: 0(none), 1(1/2), 2(1/4), 3(1/8)) and minimum 1/8)", OFFSET(scale_height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, VD },
  250. + { "mirror", "mirror 0(none), 1(V), 2(H) or 3(VH), cannot be set at the same time as pixel format conversion, rotation and crop", OFFSET(mirror), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, VD },
  251. + { "rotation", "rotation 0(0), 1(90), 2(180) or 3(270), cannot be set at the same time as pixel format conversion, mirror and crop", OFFSET(rotation), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, VD },
  252. + { "crop", "crop <x>,<y>,<w>,<h>: crop coord and width/height(from left/top, must be an integer multiple of 16), cannot be set at the same time as pixel format conversion, mirror and rotation", OFFSET(crop_expr), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD },
  253. { NULL },
  254. };
  255. --
  256. 2.17.1