]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
media: coda: add read-only h.264 decoder profile/level controls
authorPhilipp Zabel <p.zabel@pengutronix.de>
Thu, 28 Jun 2018 15:47:08 +0000 (11:47 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Wed, 4 Jul 2018 12:06:39 +0000 (08:06 -0400)
The decoder profile/level controls initially can be used to determine
supported profiles and levels. The values are set for a given stream
once the headers are parsed.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/coda/coda-common.c
drivers/media/platform/coda/coda.h

index b86d704ae10c95e009506ba223d91949bbc0aba4..f41f2035204d2f9f963bb8189cfbfe2fca00eb37 100644 (file)
@@ -1395,6 +1395,72 @@ static int coda_buf_prepare(struct vb2_buffer *vb)
        return 0;
 }
 
+static void coda_update_menu_ctrl(struct v4l2_ctrl *ctrl, int value)
+{
+       if (!ctrl)
+               return;
+
+       v4l2_ctrl_lock(ctrl);
+
+       /*
+        * Extend the control range if the parsed stream contains a known but
+        * unsupported value or level.
+        */
+       if (value > ctrl->maximum) {
+               __v4l2_ctrl_modify_range(ctrl, ctrl->minimum, value,
+                       ctrl->menu_skip_mask & ~(1 << value),
+                       ctrl->default_value);
+       } else if (value < ctrl->minimum) {
+               __v4l2_ctrl_modify_range(ctrl, value, ctrl->maximum,
+                       ctrl->menu_skip_mask & ~(1 << value),
+                       ctrl->default_value);
+       }
+
+       __v4l2_ctrl_s_ctrl(ctrl, value);
+
+       v4l2_ctrl_unlock(ctrl);
+}
+
+static void coda_update_h264_profile_ctrl(struct coda_ctx *ctx)
+{
+       const char * const *profile_names;
+       int profile;
+
+       profile = coda_h264_profile(ctx->params.h264_profile_idc);
+       if (profile < 0) {
+               v4l2_warn(&ctx->dev->v4l2_dev, "Invalid H264 Profile: %u\n",
+                         ctx->params.h264_profile_idc);
+               return;
+       }
+
+       coda_update_menu_ctrl(ctx->h264_profile_ctrl, profile);
+
+       profile_names = v4l2_ctrl_get_menu(V4L2_CID_MPEG_VIDEO_H264_PROFILE);
+
+       v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "Parsed H264 Profile: %s\n",
+                profile_names[profile]);
+}
+
+static void coda_update_h264_level_ctrl(struct coda_ctx *ctx)
+{
+       const char * const *level_names;
+       int level;
+
+       level = coda_h264_level(ctx->params.h264_level_idc);
+       if (level < 0) {
+               v4l2_warn(&ctx->dev->v4l2_dev, "Invalid H264 Level: %u\n",
+                         ctx->params.h264_level_idc);
+               return;
+       }
+
+       coda_update_menu_ctrl(ctx->h264_level_ctrl, level);
+
+       level_names = v4l2_ctrl_get_menu(V4L2_CID_MPEG_VIDEO_H264_LEVEL);
+
+       v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "Parsed H264 Level: %s\n",
+                level_names[level]);
+}
+
 static void coda_buf_queue(struct vb2_buffer *vb)
 {
        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
@@ -1423,8 +1489,11 @@ static void coda_buf_queue(struct vb2_buffer *vb)
                         * whether to enable reordering during sequence
                         * initialization.
                         */
-                       if (!ctx->params.h264_profile_idc)
+                       if (!ctx->params.h264_profile_idc) {
                                coda_sps_parse_profile(ctx, vb);
+                               coda_update_h264_profile_ctrl(ctx);
+                               coda_update_h264_level_ctrl(ctx);
+                       }
                }
 
                mutex_lock(&ctx->bitstream_mutex);
@@ -1862,6 +1931,47 @@ static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx)
                V4L2_CID_JPEG_RESTART_INTERVAL, 0, 100, 1, 0);
 }
 
+static void coda_decode_ctrls(struct coda_ctx *ctx)
+{
+       u64 mask;
+       u8 max;
+
+       ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
+               &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+               V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+               ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+                 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+                 (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
+               V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
+       if (ctx->h264_profile_ctrl)
+               ctx->h264_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+       if (ctx->dev->devtype->product == CODA_HX4 ||
+           ctx->dev->devtype->product == CODA_7541) {
+               max = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
+               mask = ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0));
+       } else if (ctx->dev->devtype->product == CODA_960) {
+               max = V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
+               mask = ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+                        (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1));
+       } else {
+               return;
+       }
+       ctx->h264_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
+               &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL, max, mask,
+               max);
+       if (ctx->h264_level_ctrl)
+               ctx->h264_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+}
+
 static int coda_ctrls_setup(struct coda_ctx *ctx)
 {
        v4l2_ctrl_handler_init(&ctx->ctrls, 2);
@@ -1875,6 +1985,9 @@ static int coda_ctrls_setup(struct coda_ctx *ctx)
                        coda_jpeg_encode_ctrls(ctx);
                else
                        coda_encode_ctrls(ctx);
+       } else {
+               if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_H264)
+                       coda_decode_ctrls(ctx);
        }
 
        if (ctx->ctrls.error) {
index c70cfab2433fe84ff6f7407f88858deabffbc153..9f57f73161d657714ff655944b8d7a970feaaeae 100644 (file)
@@ -214,6 +214,8 @@ struct coda_ctx {
        enum v4l2_quantization          quantization;
        struct coda_params              params;
        struct v4l2_ctrl_handler        ctrls;
+       struct v4l2_ctrl                *h264_profile_ctrl;
+       struct v4l2_ctrl                *h264_level_ctrl;
        struct v4l2_fh                  fh;
        int                             gopcounter;
        int                             runcounter;