123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- From 0c7df7e92eb46143fabeefd42af3023e6b7fc53f Mon Sep 17 00:00:00 2001
- From: "arvin.zhu" <arvin.zhu@starfivetech.com>
- Date: Fri, 21 Oct 2022 10:39:31 +0800
- Subject: [PATCH] FFmpeg:omxdec: add mirror rotation and crop option
- add mirror rotation and crop option for mjpeg_omx decoder
- Signed-off-by: arvin.zhu <arvin.zhu@starfivetech.com>
- ---
- libavcodec/omxdec.c | 181 +++++++++++++++++++++++++++++++++++---------
- 1 file changed, 146 insertions(+), 35 deletions(-)
- diff --git a/libavcodec/omxdec.c b/libavcodec/omxdec.c
- index 87e5a1a..b4a7c96 100755
- --- a/libavcodec/omxdec.c
- +++ b/libavcodec/omxdec.c
- @@ -276,6 +276,15 @@ typedef struct OMXCodecContext {
-
- OMX_U32 scale_width;
- OMX_U32 scale_height;
- + OMX_U32 rotation;
- + OMX_U32 mirror;
- + char *crop_expr;
- + struct {
- + int x;
- + int y;
- + int w;
- + int h;
- + } crop;
-
- int input_zerocopy;
- int profile;
- @@ -359,7 +368,6 @@ static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, O
- av_log(s->avctx, AV_LOG_ERROR, "err %d\n",err);
- return AVERROR_UNKNOWN;
- }
- -
- for (i = 0; i < video_port_params.nPorts; i++) {
- int port = video_port_params.nStartPortNumber + i;
- OMX_PARAM_PORTDEFINITIONTYPE port_params = { 0 };
- @@ -571,7 +579,7 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
- out_port_params.format.video.nBitrate = avctx->bit_rate;
- out_port_params.format.video.xFramerate = in_port_params.format.video.xFramerate;
- out_port_params.format.video.bFlagErrorConcealment = OMX_FALSE;
- - av_log(avctx, AV_LOG_VERBOSE, "OMX setting pixel_format:%s\n", s->pixel_format);
- +
- if (avctx->codec->id == AV_CODEC_ID_MPEG4)
- out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
- else if (avctx->codec->id == AV_CODEC_ID_H264) {
- @@ -580,12 +588,12 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
- else if (avctx->codec->id == AV_CODEC_ID_HEVC) {
- out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC;
- }
- - else if (avctx->codec->id == AV_CODEC_ID_MJPEG){
- + else if (avctx->codec->id == AV_CODEC_ID_MJPEG) {
- out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG;
-
- /* Set Scale config setting*/
- if (s->scale_width || s->scale_height) {
- - av_log(avctx, AV_LOG_TRACE, "mjpeg decoder: scaling width: %ld scaling height: %ld .\n", s->scale_width, s->scale_height);
- + av_log(avctx, AV_LOG_TRACE, "mjpeg decoder: scaling width: %d scaling height: %d .\n", s->scale_width, s->scale_height);
- OMX_CONFIG_SCALEFACTORTYPE ScaleConfig;
- INIT_STRUCT(ScaleConfig);
- ScaleConfig.nPortIndex = 1;
- @@ -599,38 +607,138 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
- out_port_params.format.video.nFrameHeight = avctx->height;
- }
-
- - switch (av_get_pix_fmt(s->pixel_format)) {
- - case AV_PIX_FMT_NV12:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
- - break;
- - case AV_PIX_FMT_NV21:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYVU420SemiPlanar;
- - break;
- - case AV_PIX_FMT_YUV420P:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
- - break;
- - case AV_PIX_FMT_NV16:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422SemiPlanar;
- - break;
- - case AV_PIX_FMT_YUV422P:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422Planar;
- - break;
- - case AV_PIX_FMT_YUYV422:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYCbYCr;
- - break;
- - case AV_PIX_FMT_YVYU422:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYCrYCb;
- - break;
- - case AV_PIX_FMT_UYVY422:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatCbYCrY;
- - break;
- - case AV_PIX_FMT_YUV444P:
- - out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV444Planar;
- - break;
- - default:
- + /* Set pixel format to decoder output*/
- + if (s->pixel_format) {
- + switch (av_get_pix_fmt(s->pixel_format)) {
- + case AV_PIX_FMT_NV12:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
- + break;
- + case AV_PIX_FMT_NV21:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYVU420SemiPlanar;
- + break;
- + case AV_PIX_FMT_YUV420P:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
- + break;
- + case AV_PIX_FMT_NV16:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422SemiPlanar;
- + break;
- + case AV_PIX_FMT_YUV422P:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422Planar;
- + break;
- + case AV_PIX_FMT_YUYV422:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYCbYCr;
- + break;
- + case AV_PIX_FMT_YVYU422:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYCrYCb;
- + break;
- + case AV_PIX_FMT_UYVY422:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatCbYCrY;
- + break;
- + case AV_PIX_FMT_YUV444P:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV444Planar;
- + break;
- + default:
- + return AVERROR_OPTION_NOT_FOUND;
- + }
- + av_log(avctx, AV_LOG_VERBOSE, "OMX setting pixel_format:%s\n", s->pixel_format);
- + } else {
- + switch (avctx->pix_fmt) {
- + case AV_PIX_FMT_YUVJ420P:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
- + break;
- + case AV_PIX_FMT_YUVJ422P:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV422Planar;
- + break;
- + case AV_PIX_FMT_YUVJ444P:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV444Planar;
- + break;
- + default:
- + out_port_params.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
- + break;
- + }
- + }
- +
- + /* Set Mirror config setting*/
- + if (s->mirror) {
- + if (s->pixel_format || s->scale_width || s->scale_height || s->rotation) {
- + av_log(avctx, AV_LOG_ERROR, "Mirror cannot work with other option together.\n");
- + return AVERROR_INVALIDDATA;
- + }
- + av_log(avctx, AV_LOG_TRACE, "mjpeg decoder: mirror\n");
- + OMX_CONFIG_MIRRORTYPE MirrorConfig;
- + INIT_STRUCT(MirrorConfig);
- + MirrorConfig.nPortIndex = 1;
- + OMX_GetConfig(s->handle, OMX_IndexConfigCommonMirror, &MirrorConfig);
- + MirrorConfig.eMirror = s->mirror;
- + OMX_SetConfig(s->handle, OMX_IndexConfigCommonMirror, &MirrorConfig);
- + }
- +
- + /* Set Rotation config setting*/
- + if (s->rotation) {
- + if (s->pixel_format || s->scale_width || s->scale_height || s->mirror) {
- + av_log(avctx, AV_LOG_ERROR, "Rotation cannot work with other option together.\n");
- + return AVERROR_INVALIDDATA;
- + }
- + av_log(avctx, AV_LOG_TRACE, "mjpeg decoder: rotation\n");
- + OMX_CONFIG_ROTATIONTYPE RotatConfig;
- + INIT_STRUCT(RotatConfig);
- + RotatConfig.nPortIndex = 1;
- + OMX_GetConfig(s->handle, OMX_IndexConfigCommonRotate, &RotatConfig);
- + switch (s->rotation) {
- + case 1:
- + RotatConfig.nRotation = 90;
- + break;
- + case 2:
- + RotatConfig.nRotation = 180;
- + break;
- + case 3:
- + RotatConfig.nRotation = 270;
- + break;
- + default:
- + RotatConfig.nRotation = 0;
- + break;
- + }
- + OMX_SetConfig(s->handle, OMX_IndexConfigCommonRotate, &RotatConfig);
- + }
- +
- + /* Set Roi config setting*/
- + if (s->crop_expr && sscanf(s->crop_expr, "%d,%d,%d,%d",
- + &s->crop.x, &s->crop.y,
- + &s->crop.w, &s->crop.h) != 4) {
- + av_log(avctx, AV_LOG_ERROR, "Invalid cropping expressions.\n");
- return AVERROR_OPTION_NOT_FOUND;
- }
- +
- + if (s->crop.w && s->crop.h) {
- + if (s->pixel_format || s->scale_width || s->scale_height || s->mirror || s->rotation) {
- + av_log(avctx, AV_LOG_ERROR, "Crop cannot work with other option together.\n");
- + return AVERROR_INVALIDDATA;
- + }
- + if ((s->crop.x < 0) || (s->crop.x > (avctx->width - s->crop.w)) ||
- + (s->crop.y < 0) || (s->crop.y > (avctx->height - s->crop.h)) ||
- + (s->crop.w < 16) || (s->crop.w > (avctx->width - s->crop.x)) ||
- + (s->crop.h < 16) || (s->crop.h > (avctx->height - s->crop.y))) {
- + av_log(avctx, AV_LOG_ERROR, "Invalid cropping range.\n");
- + return AVERROR_INVALIDDATA;
- + }
- + if (s->crop.w % 16 != 0 || s->crop.h % 16 != 0) {
- + av_log(avctx, AV_LOG_ERROR, "The width/height must be an integer multiple of 16\n");
- + return AVERROR_INVALIDDATA;
- + }
- +
- + OMX_CONFIG_RECTTYPE RectConfig;
- + INIT_STRUCT(RectConfig);
- + RectConfig.nPortIndex = 1;
- + OMX_GetConfig(s->handle, OMX_IndexConfigCommonOutputCrop, &RectConfig);
- + RectConfig.nLeft = s->crop.x;
- + RectConfig.nTop = s->crop.y;
- + RectConfig.nWidth = s->crop.w;
- + RectConfig.nHeight = s->crop.h;
- + OMX_SetConfig(s->handle, OMX_IndexConfigCommonOutputCrop, &RectConfig);
- + 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);
- + }
- }
- +
- if (avctx->codec->id == AV_CODEC_ID_H264 || avctx->codec->id == AV_CODEC_ID_HEVC) {
- /* Set Scale config setting*/
- if ((s->scale_width != 0) && ((s->scale_width < avctx->width/8) ||
- @@ -675,6 +783,7 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
- s->done_out_buffers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers);
- if (!s->in_buffer_headers || !s->free_in_buffers || !s->out_buffer_headers || !s->done_out_buffers)
- return AVERROR(ENOMEM);
- +
- for (i = 0; i < s->num_in_buffers && err == OMX_ErrorNone; i++) {
- if (s->input_zerocopy)
- err = OMX_UseBuffer(s->handle, &s->in_buffer_headers[i], s->in_port, s, in_port_params.nBufferSize, NULL);
- @@ -699,7 +808,6 @@ static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
- av_log(avctx, AV_LOG_ERROR, "Didn't get OMX_StateExecuting\n");
- return AVERROR_UNKNOWN;
- }
- -
- for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++)
- err = OMX_FillThisBuffer(s->handle, s->out_buffer_headers[i]);
- if (err != OMX_ErrorNone) {
- @@ -1055,9 +1163,12 @@ static const AVOption options_mjpeg[] = {
- { "omx_libname", "OpenMAX library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
- { "omx_libprefix", "OpenMAX library prefix", OFFSET(libprefix), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
- { "zerocopy", "Try to avoid copying input frames if possible", OFFSET(input_zerocopy), AV_OPT_TYPE_INT, { .i64 = CONFIG_OMX_RPI }, 0, 1, VD },
- - { "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 },
- + { "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 },
- { "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 },
- { "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 },
- + { "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 },
- + { "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 },
- + { "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 },
- { NULL },
- };
-
- --
- 2.17.1
|