36d91e66e0
Set chroma_qp_offset hfi to firmware only for client set cases. Supported value: 0 & -12 If hfi not set, firmware proceeds with its own default value. 10-bit: default: 0 8-bit : default: Adaptive chroma_qp Change-Id: I40262aae87b2a385c6cd7d60faa19b6adfe8b151 Signed-off-by: Govindaraj Rajagopal <grajagop@codeaurora.org>
4932 lines
131 KiB
C
4932 lines
131 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
|
*/
|
|
#include "msm_venc.h"
|
|
#include "msm_vidc_internal.h"
|
|
#include "msm_vidc_common.h"
|
|
#include "vidc_hfi.h"
|
|
#include "vidc_hfi_helper.h"
|
|
#include "vidc_hfi_api.h"
|
|
#include "msm_vidc_debug.h"
|
|
#include "msm_vidc_clocks.h"
|
|
#include "msm_vidc_buffer_calculations.h"
|
|
|
|
#define MIN_BIT_RATE 32000
|
|
#define MAX_BIT_RATE 1200000000
|
|
#define DEFAULT_BIT_RATE 64000
|
|
#define MIN_BIT_RATE_RATIO 0
|
|
#define MAX_BIT_RATE_RATIO 100
|
|
#define MAX_HIER_CODING_LAYER 6
|
|
#define BIT_RATE_STEP 1
|
|
#define MAX_BASE_LAYER_PRIORITY_ID 63
|
|
#define MAX_SLICE_BYTE_SIZE ((MAX_BIT_RATE)>>3)
|
|
#define MIN_SLICE_BYTE_SIZE 512
|
|
#define MAX_SLICE_MB_SIZE (((4096 + 15) >> 4) * ((2304 + 15) >> 4))
|
|
#define QP_ENABLE_I 0x1
|
|
#define QP_ENABLE_P 0x2
|
|
#define QP_ENABLE_B 0x4
|
|
#define MIN_QP 0
|
|
#define MAX_QP 0x7F
|
|
#define MAX_QP_PACKED 0x7F7F7F
|
|
#define DEFAULT_QP 0xA
|
|
#define DEFAULT_QP_PACKED 0xA0A0A
|
|
#define MIN_CHROMA_QP_OFFSET -12
|
|
#define MAX_INTRA_REFRESH_MBS ((7680 * 4320) >> 8)
|
|
#define MAX_LTR_FRAME_COUNT 10
|
|
#define MAX_NUM_B_FRAMES 1
|
|
#define MIN_CBRPLUS_W 640
|
|
#define MIN_CBRPLUS_H 480
|
|
#define MAX_CBR_W 1280
|
|
#define MAX_CBR_H 720
|
|
#define LEGACY_CBR_BUF_SIZE 500
|
|
#define CBR_PLUS_BUF_SIZE 1000
|
|
#define MAX_GOP 0xFFFFFFF
|
|
|
|
#define MIN_NUM_ENC_OUTPUT_BUFFERS 4
|
|
#define MIN_NUM_ENC_CAPTURE_BUFFERS 5
|
|
#define VENC_MAX_TIMESTAMP_LIST_SIZE 2
|
|
|
|
static const char *const mpeg_video_rate_control[] = {
|
|
"VBR",
|
|
"CBR",
|
|
"CBR VFR",
|
|
"MBR",
|
|
"MBR VFR",
|
|
"CQ",
|
|
NULL
|
|
};
|
|
|
|
static const char *const mpeg_video_h264_profile[] = {
|
|
"Baseline",
|
|
"Constrained Baseline",
|
|
"Main",
|
|
"Extended",
|
|
"High",
|
|
"High 10",
|
|
"High 422",
|
|
"High 444 Predictive",
|
|
"High 10 Intra",
|
|
"High 422 Intra",
|
|
"High 444 Intra",
|
|
"CAVLC 444 Intra",
|
|
"Scalable Baseline",
|
|
"Scalable High",
|
|
"Scalable High Intra",
|
|
"Stereo High",
|
|
"Multiview High",
|
|
"Constrained High",
|
|
NULL,
|
|
};
|
|
|
|
static const char *const mpeg_video_h264_level[] = {
|
|
"1",
|
|
"1b",
|
|
"1.1",
|
|
"1.2",
|
|
"1.3",
|
|
"2",
|
|
"2.1",
|
|
"2.2",
|
|
"3",
|
|
"3.1",
|
|
"3.2",
|
|
"4",
|
|
"4.1",
|
|
"4.2",
|
|
"5",
|
|
"5.1",
|
|
"5.2",
|
|
"6.0",
|
|
"6.1",
|
|
"6.2",
|
|
NULL,
|
|
};
|
|
|
|
static const char *const mpeg_video_stream_format[] = {
|
|
"NAL Format Start Codes",
|
|
"NAL Format One NAL Per Buffer",
|
|
"NAL Format One Byte Length",
|
|
"NAL Format Two Byte Length",
|
|
"NAL Format Four Byte Length",
|
|
NULL
|
|
};
|
|
|
|
static const char *const roi_map_type[] = {
|
|
"None",
|
|
"2-bit",
|
|
"2-bit",
|
|
};
|
|
|
|
static struct msm_vidc_ctrl msm_venc_ctrls[] = {
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_UNKNOWN,
|
|
.name = "Invalid control",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 0,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.menu_skip_mask = 0,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
|
|
.name = "Intra Period for P frames",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = MAX_GOP,
|
|
.default_value = 2*DEFAULT_FPS-1,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
|
|
.name = "HEVC I Frame Quantization",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_QP,
|
|
.maximum = MAX_QP,
|
|
.default_value = DEFAULT_QP,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
|
|
.name = "HEVC P Frame Quantization",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_QP,
|
|
.maximum = MAX_QP,
|
|
.default_value = DEFAULT_QP,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
|
|
.name = "HEVC B Frame Quantization",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_QP,
|
|
.maximum = MAX_QP,
|
|
.default_value = DEFAULT_QP,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
|
|
.name = "HEVC Quantization Range Minimum",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_QP,
|
|
.maximum = MAX_QP_PACKED,
|
|
.default_value = DEFAULT_QP_PACKED,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
|
|
.name = "HEVC Quantization Range Maximum",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_QP,
|
|
.maximum = MAX_QP_PACKED,
|
|
.default_value = DEFAULT_QP_PACKED,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
|
|
.name = "Intra Period for B frames",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = MAX_NUM_B_FRAMES,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
|
|
.name = "CAPTURE Count",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = SINGLE_OUTPUT_BUFFER,
|
|
.maximum = MAX_NUM_OUTPUT_BUFFERS,
|
|
.default_value = SINGLE_OUTPUT_BUFFER,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
|
|
.name = "OUTPUT Count",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = SINGLE_INPUT_BUFFER,
|
|
.maximum = MAX_NUM_INPUT_BUFFERS,
|
|
.default_value = SINGLE_INPUT_BUFFER,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
|
|
.name = "Request I Frame",
|
|
.type = V4L2_CTRL_TYPE_BUTTON,
|
|
.minimum = 0,
|
|
.maximum = 0,
|
|
.default_value = 0,
|
|
.step = 0,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
|
|
.name = "Video Bitrate Control",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
|
|
.maximum = V4L2_MPEG_VIDEO_BITRATE_MODE_CQ,
|
|
.default_value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
|
|
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) |
|
|
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_MBR) |
|
|
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR) |
|
|
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR) |
|
|
(1 << V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
|
|
),
|
|
.qmenu = mpeg_video_rate_control,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY,
|
|
.name = "Compression quality",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_FRAME_QUALITY,
|
|
.maximum = MAX_FRAME_QUALITY,
|
|
.default_value = DEFAULT_FRAME_QUALITY,
|
|
.step = FRAME_QUALITY_STEP,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE,
|
|
.name = "Image grid size",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = HEIC_GRID_DIMENSION,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE,
|
|
.name = "Frame Rate",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = (MINIMUM_FPS << 16),
|
|
.maximum = (MAXIMUM_FPS << 16),
|
|
.default_value = (DEFAULT_FPS << 16),
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_BITRATE,
|
|
.name = "Bit Rate",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_BIT_RATE,
|
|
.maximum = MAX_BIT_RATE,
|
|
.default_value = DEFAULT_BIT_RATE,
|
|
.step = BIT_RATE_STEP,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
|
|
.name = "Entropy Mode",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
|
|
.maximum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
|
|
.default_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
|
|
),
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
|
|
.name = "H264 Profile",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
|
|
.maximum = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
|
|
.default_value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH)
|
|
),
|
|
.qmenu = mpeg_video_h264_profile,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
|
|
.name = "H264 Level",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
|
|
.maximum = V4L2_MPEG_VIDEO_H264_LEVEL_6_2,
|
|
.default_value = V4L2_MPEG_VIDEO_H264_LEVEL_6_2,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
|
|
(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) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_1) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_5_2) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_6_0) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_6_1) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_6_2)
|
|
),
|
|
.qmenu = mpeg_video_h264_level,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
|
|
.name = "HEVC Profile",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
|
|
.maximum = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
|
|
.default_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10)
|
|
),
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
|
|
.name = "HEVC Level",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
|
|
.maximum = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
|
|
.default_value =
|
|
V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_5) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_6) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2)
|
|
),
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_TIER,
|
|
.name = "HEVC Tier",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
|
|
.maximum = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
|
|
.default_value = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_TIER_HIGH)
|
|
),
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_ROTATE,
|
|
.name = "Rotation",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 270,
|
|
.default_value = 0,
|
|
.step = 90,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
|
|
.name = "Slice Mode",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
|
|
.maximum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES,
|
|
.default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) |
|
|
(1 << V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) |
|
|
(1 << V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES)
|
|
),
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
|
|
.name = "Slice Byte Size",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_SLICE_BYTE_SIZE,
|
|
.maximum = MAX_SLICE_BYTE_SIZE,
|
|
.default_value = MIN_SLICE_BYTE_SIZE,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
|
|
.name = "Slice MB Size",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 1,
|
|
.maximum = MAX_SLICE_MB_SIZE,
|
|
.default_value = 1,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM,
|
|
.name = "Random Intra Refresh MBs",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = MAX_INTRA_REFRESH_MBS,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.menu_skip_mask = 0,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
|
|
.name = "Cyclic Intra Refresh MBs",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = MAX_INTRA_REFRESH_MBS,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
|
|
.name = "H.264 Loop Filter Alpha Offset",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = -6,
|
|
.maximum = 6,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
|
|
.name = "H.264 Loop Filter Beta Offset",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = -6,
|
|
.maximum = 6,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
|
|
.name = "H.264 Loop Filter Mode",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
|
|
.maximum = DB_DISABLE_SLICE_BOUNDARY,
|
|
.default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED) |
|
|
(1 << V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED) |
|
|
(1 << DB_DISABLE_SLICE_BOUNDARY)
|
|
),
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR,
|
|
.name = "Prepend SPS/PPS to IDR",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE,
|
|
.name = "Secure mode",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA,
|
|
.name = "Extradata Type",
|
|
.type = V4L2_CTRL_TYPE_BITMASK,
|
|
.minimum = EXTRADATA_NONE,
|
|
.maximum = EXTRADATA_ADVANCED | EXTRADATA_ENC_INPUT_ROI |
|
|
EXTRADATA_ENC_INPUT_HDR10PLUS |
|
|
EXTRADATA_ENC_INPUT_CVP,
|
|
.default_value = EXTRADATA_NONE,
|
|
.menu_skip_mask = 0,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_VUI_TIMING_INFO,
|
|
.name = "H264 VUI Timing Info",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_AU_DELIMITER,
|
|
.name = "AU Delimiter",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.step = 1,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME,
|
|
.name = "H264 Use LTR",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = ((1 << MAX_LTR_FRAME_COUNT) - 1),
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
|
|
.name = "Ltr Count",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = MAX_LTR_FRAME_COUNT,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME,
|
|
.name = "H264 Mark LTR",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = (MAX_LTR_FRAME_COUNT - 1),
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER,
|
|
.name = "Set Hier layers",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = MAX_HIER_CODING_LAYER,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER,
|
|
.name = "Set Hier max layers",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_0,
|
|
.maximum = V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_6,
|
|
.default_value =
|
|
V4L2_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER_0,
|
|
.step = 1,
|
|
.menu_skip_mask = 0,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
|
|
.name = "Set Hier coding type",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
|
|
.maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
|
|
.default_value = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P)
|
|
),
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP,
|
|
.name = "Set layer0 QP",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 51,
|
|
.default_value = 51,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP,
|
|
.name = "Set layer1 QP",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 51,
|
|
.default_value = 51,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP,
|
|
.name = "Set layer2 QP",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 51,
|
|
.default_value = 51,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP,
|
|
.name = "Set layer3 QP",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 51,
|
|
.default_value = 51,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP,
|
|
.name = "Set layer4 QP",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 51,
|
|
.default_value = 51,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP,
|
|
.name = "Set layer5 QP",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 51,
|
|
.default_value = 51,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR,
|
|
.name = "Set layer0 BR",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_BIT_RATE_RATIO,
|
|
.maximum = MAX_BIT_RATE_RATIO,
|
|
.default_value = MIN_BIT_RATE_RATIO,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR,
|
|
.name = "Set layer1 BR",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_BIT_RATE_RATIO,
|
|
.maximum = MAX_BIT_RATE_RATIO,
|
|
.default_value = MIN_BIT_RATE_RATIO,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR,
|
|
.name = "Set layer2 BR",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_BIT_RATE_RATIO,
|
|
.maximum = MAX_BIT_RATE_RATIO,
|
|
.default_value = MIN_BIT_RATE_RATIO,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR,
|
|
.name = "Set layer3 BR",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_BIT_RATE_RATIO,
|
|
.maximum = MAX_BIT_RATE_RATIO,
|
|
.default_value = MIN_BIT_RATE_RATIO,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR,
|
|
.name = "Set layer4 BR",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_BIT_RATE_RATIO,
|
|
.maximum = MAX_BIT_RATE_RATIO,
|
|
.default_value = MIN_BIT_RATE_RATIO,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR,
|
|
.name = "Set layer5 BR",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_BIT_RATE_RATIO,
|
|
.maximum = MAX_BIT_RATE_RATIO,
|
|
.default_value = MIN_BIT_RATE_RATIO,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID,
|
|
.name = "Set Base Layer Priority ID for Hier-P",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = MAX_BASE_LAYER_PRIORITY_ID,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,
|
|
.name = "SAR Width",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 7680,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT,
|
|
.name = "SAR Height",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 7680,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY,
|
|
.name = "Session Priority",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE,
|
|
.name = "Encoder Operating rate",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = (DEFAULT_FPS << 16),/* Power Vote min fps */
|
|
.maximum = INT_MAX,
|
|
.default_value = (DEFAULT_FPS << 16),
|
|
.step = 1,
|
|
.menu_skip_mask = 0,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC,
|
|
.name = "Set VPE Color space conversion coefficients",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE,
|
|
.name = "Low Latency Mode",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_BLUR_DIMENSIONS,
|
|
.name = "Set Blur width/height",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = S32_MAX,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
|
|
.name = "Transform 8x8",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE,
|
|
.name = "Set Color space",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MSM_VIDC_RESERVED_1,
|
|
.maximum = MSM_VIDC_BT2020,
|
|
.default_value = MSM_VIDC_RESERVED_1,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE,
|
|
.name = "Set Color space range",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS,
|
|
.name = "Set Color space transfer characterstics",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MSM_VIDC_TRANSFER_BT709_5,
|
|
.maximum = MSM_VIDC_TRANSFER_HLG,
|
|
.default_value = MSM_VIDC_TRANSFER_601_6_625,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS,
|
|
.name = "Set Color space matrix coefficients",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MSM_VIDC_MATRIX_BT_709_5,
|
|
.maximum = MSM_VIDC_MATRIX_BT_2020_CONST,
|
|
.default_value = MSM_VIDC_MATRIX_601_6_625,
|
|
.step = 1,
|
|
.qmenu = NULL,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
|
|
.name = "Frame Rate based Rate Control",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = 0,
|
|
.maximum = 1,
|
|
.default_value = 1,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VENC_RC_TIMESTAMP_DISABLE,
|
|
.name = "RC Timestamp disable",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_CUSTOM_MATRIX,
|
|
.name = "Enable/Disable CSC Custom Matrix",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_HFLIP,
|
|
.name = "Enable/Disable Horizontal Flip",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_VFLIP,
|
|
.name = "Enable/Disable Vertical Flip",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VENC_HDR_INFO,
|
|
.name = "HDR PQ information",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = INT_MIN,
|
|
.maximum = INT_MAX,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
|
|
.name = "NAL Format",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_MPEG_VIDEO_HEVC_SIZE_0,
|
|
.maximum = V4L2_MPEG_VIDEO_HEVC_SIZE_4,
|
|
.default_value = V4L2_MPEG_VIDEO_HEVC_SIZE_0,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_SIZE_0) |
|
|
(1 << V4L2_MPEG_VIDEO_HEVC_SIZE_4)
|
|
),
|
|
.qmenu = mpeg_video_stream_format,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET,
|
|
.name = "Chroma QP Index Offset",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = MIN_CHROMA_QP_OFFSET,
|
|
.maximum = INT_MAX,
|
|
.default_value = INT_MAX,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VENC_NATIVE_RECORDER,
|
|
.name = "Enable/Disable Native Recorder",
|
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
.minimum = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.maximum = V4L2_MPEG_MSM_VIDC_ENABLE,
|
|
.default_value = V4L2_MPEG_MSM_VIDC_DISABLE,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VENC_BITRATE_SAVINGS,
|
|
.name = "Enable/Disable bitrate savings",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = V4L2_MPEG_VIDC_VIDEO_BRS_DISABLE,
|
|
.maximum = V4L2_MPEG_VIDC_VIDEO_BRS_ENABLE_ALL,
|
|
.default_value = V4L2_MPEG_VIDC_VIDEO_BRS_ENABLE_ALL,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VENC_BITRATE_BOOST,
|
|
.name = "Bitrate boost margin",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 100,
|
|
.default_value = 25,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDEO_VBV_DELAY,
|
|
.name = "Set Vbv Delay",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = 1000,
|
|
.default_value = 0,
|
|
.step = 500,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_SUPERFRAME,
|
|
.name = "Superframe",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = 0,
|
|
.maximum = VIDC_SUPERFRAME_MAX,
|
|
.default_value = 0,
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_CAPTURE_FRAME_RATE,
|
|
.name = "Capture Frame Rate",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = (MINIMUM_FPS << 16),
|
|
.maximum = (MAXIMUM_FPS << 16),
|
|
.default_value = (DEFAULT_FPS << 16),
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_CVP_FRAME_RATE,
|
|
.name = "CVP Frame Rate",
|
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
|
.minimum = (MINIMUM_FPS << 16),
|
|
.maximum = (MAXIMUM_FPS << 16),
|
|
.default_value = (DEFAULT_FPS << 16),
|
|
.step = 1,
|
|
},
|
|
{
|
|
.id = V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE,
|
|
.name = "ROI Type",
|
|
.type = V4L2_CTRL_TYPE_MENU,
|
|
.minimum = V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_NONE,
|
|
.maximum = V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_2BYTE,
|
|
.default_value = V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_NONE,
|
|
.menu_skip_mask = ~(
|
|
(1 << V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_NONE) |
|
|
(1 << V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_2BIT) |
|
|
(1 << V4L2_CID_MPEG_VIDC_VIDEO_ROI_TYPE_2BYTE)
|
|
),
|
|
.qmenu = roi_map_type,
|
|
},
|
|
};
|
|
|
|
#define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
|
|
|
|
static struct msm_vidc_format_desc venc_input_formats[] = {
|
|
{
|
|
.name = "YCbCr Semiplanar 4:2:0",
|
|
.description = "Y/CbCr 4:2:0",
|
|
.fourcc = V4L2_PIX_FMT_NV12,
|
|
},
|
|
{
|
|
.name = "UBWC YCbCr Semiplanar 4:2:0",
|
|
.description = "UBWC Y/CbCr 4:2:0",
|
|
.fourcc = V4L2_PIX_FMT_NV12_UBWC,
|
|
},
|
|
{
|
|
.name = "YCrCb Semiplanar 4:2:0",
|
|
.description = "Y/CrCb 4:2:0",
|
|
.fourcc = V4L2_PIX_FMT_NV21,
|
|
},
|
|
{
|
|
.name = "TP10 UBWC 4:2:0",
|
|
.description = "TP10 UBWC 4:2:0",
|
|
.fourcc = V4L2_PIX_FMT_NV12_TP10_UBWC,
|
|
},
|
|
{
|
|
.name = "YCbCr Semiplanar 4:2:0 10bit",
|
|
.description = "Y/CbCr 4:2:0 10bit",
|
|
.fourcc = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS,
|
|
},
|
|
{
|
|
.name = "YCbCr Semiplanar 4:2:0 512 aligned",
|
|
.description = "Y/CbCr 4:2:0 512 aligned",
|
|
.fourcc = V4L2_PIX_FMT_NV12_512,
|
|
},
|
|
{
|
|
.name = "32bit RGBA UBWC 8:8:8:8",
|
|
.description = "32-bit RGBA UBWC 8:8:8:8",
|
|
.fourcc = V4L2_PIX_FMT_RGBA8888_UBWC,
|
|
},
|
|
};
|
|
|
|
static struct msm_vidc_format_desc venc_output_formats[] = {
|
|
{
|
|
.name = "H264",
|
|
.description = "H264 compressed format",
|
|
.fourcc = V4L2_PIX_FMT_H264,
|
|
},
|
|
{
|
|
.name = "HEVC",
|
|
.description = "HEVC compressed format",
|
|
.fourcc = V4L2_PIX_FMT_HEVC,
|
|
},
|
|
};
|
|
|
|
struct msm_vidc_format_constraint enc_pix_format_constraints[] = {
|
|
{
|
|
.fourcc = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS,
|
|
.num_planes = 2,
|
|
.y_max_stride = 8192,
|
|
.y_buffer_alignment = 256,
|
|
.uv_max_stride = 8192,
|
|
.uv_buffer_alignment = 256,
|
|
},
|
|
{
|
|
.fourcc = V4L2_PIX_FMT_NV12_512,
|
|
.num_planes = 2,
|
|
.y_max_stride = 16384,
|
|
.y_buffer_alignment = 512,
|
|
.uv_max_stride = 16384,
|
|
.uv_buffer_alignment = 256,
|
|
},
|
|
{
|
|
.fourcc = V4L2_PIX_FMT_NV12,
|
|
.num_planes = 2,
|
|
.y_max_stride = 16384,
|
|
.y_buffer_alignment = 512,
|
|
.uv_max_stride = 16384,
|
|
.uv_buffer_alignment = 256,
|
|
},
|
|
{
|
|
.fourcc = V4L2_PIX_FMT_NV21,
|
|
.num_planes = 2,
|
|
.y_max_stride = 8192,
|
|
.y_buffer_alignment = 512,
|
|
.uv_max_stride = 8192,
|
|
.uv_buffer_alignment = 256,
|
|
},
|
|
};
|
|
|
|
u32 v4l2_to_hfi_flip(struct msm_vidc_inst *inst)
|
|
{
|
|
struct v4l2_ctrl *hflip = NULL;
|
|
struct v4l2_ctrl *vflip = NULL;
|
|
u32 flip = HFI_FLIP_NONE;
|
|
|
|
hflip = get_ctrl(inst, V4L2_CID_HFLIP);
|
|
vflip = get_ctrl(inst, V4L2_CID_VFLIP);
|
|
|
|
if ((hflip->val == V4L2_MPEG_MSM_VIDC_ENABLE) &&
|
|
(vflip->val == V4L2_MPEG_MSM_VIDC_ENABLE))
|
|
flip = HFI_FLIP_HORIZONTAL | HFI_FLIP_VERTICAL;
|
|
else if (hflip->val == V4L2_MPEG_MSM_VIDC_ENABLE)
|
|
flip = HFI_FLIP_HORIZONTAL;
|
|
else if (vflip->val == V4L2_MPEG_MSM_VIDC_ENABLE)
|
|
flip = HFI_FLIP_VERTICAL;
|
|
|
|
return flip;
|
|
}
|
|
|
|
inline bool vidc_scalar_enabled(struct msm_vidc_inst *inst)
|
|
{
|
|
struct v4l2_format *f;
|
|
u32 output_height, output_width, input_height, input_width;
|
|
bool scalar_enable = false;
|
|
|
|
f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
output_height = f->fmt.pix_mp.height;
|
|
output_width = f->fmt.pix_mp.width;
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
input_height = f->fmt.pix_mp.height;
|
|
input_width = f->fmt.pix_mp.width;
|
|
|
|
if (output_height != input_height || output_width != input_width)
|
|
scalar_enable = true;
|
|
|
|
return scalar_enable;
|
|
}
|
|
|
|
|
|
static int msm_venc_set_csc(struct msm_vidc_inst *inst,
|
|
u32 color_primaries, u32 custom_matrix);
|
|
|
|
int msm_venc_inst_init(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct msm_vidc_format_desc *fmt_desc = NULL;
|
|
struct v4l2_format *f = NULL;
|
|
uint32_t vpu;
|
|
|
|
if (!inst) {
|
|
d_vpr_e("Invalid input = %pK\n", inst);
|
|
return -EINVAL;
|
|
}
|
|
vpu = inst->core->platform_data->vpu_ver;
|
|
f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
f->type = OUTPUT_MPLANE;
|
|
f->fmt.pix_mp.height = DEFAULT_HEIGHT;
|
|
f->fmt.pix_mp.width = DEFAULT_WIDTH;
|
|
f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
|
|
f->fmt.pix_mp.num_planes = 1;
|
|
f->fmt.pix_mp.plane_fmt[0].sizeimage =
|
|
msm_vidc_calculate_enc_output_frame_size(inst);
|
|
fmt_desc = msm_comm_get_pixel_fmt_fourcc(venc_output_formats,
|
|
ARRAY_SIZE(venc_output_formats),
|
|
f->fmt.pix_mp.pixelformat, inst->sid);
|
|
if (!fmt_desc) {
|
|
s_vpr_e(inst->sid, "Invalid fmt set : %x\n",
|
|
f->fmt.pix_mp.pixelformat);
|
|
return -EINVAL;
|
|
}
|
|
strlcpy(inst->fmts[OUTPUT_PORT].name, fmt_desc->name,
|
|
sizeof(inst->fmts[OUTPUT_PORT].name));
|
|
strlcpy(inst->fmts[OUTPUT_PORT].description, fmt_desc->description,
|
|
sizeof(inst->fmts[OUTPUT_PORT].description));
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
f->type = INPUT_MPLANE;
|
|
f->fmt.pix_mp.height = DEFAULT_HEIGHT;
|
|
f->fmt.pix_mp.width = DEFAULT_WIDTH;
|
|
f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12_UBWC;
|
|
f->fmt.pix_mp.num_planes = 1;
|
|
if (vpu == VPU_VERSION_IRIS2)
|
|
f->fmt.pix_mp.num_planes = 2;
|
|
f->fmt.pix_mp.plane_fmt[0].sizeimage =
|
|
msm_vidc_calculate_enc_input_frame_size(inst);
|
|
f->fmt.pix_mp.plane_fmt[1].sizeimage =
|
|
msm_vidc_calculate_enc_input_extra_size(inst);
|
|
fmt_desc = msm_comm_get_pixel_fmt_fourcc(venc_input_formats,
|
|
ARRAY_SIZE(venc_input_formats), f->fmt.pix_mp.pixelformat,
|
|
inst->sid);
|
|
if (!fmt_desc) {
|
|
s_vpr_e(inst->sid, "Invalid fmt set : %x\n",
|
|
f->fmt.pix_mp.pixelformat);
|
|
return -EINVAL;
|
|
}
|
|
strlcpy(inst->fmts[INPUT_PORT].name, fmt_desc->name,
|
|
sizeof(inst->fmts[INPUT_PORT].name));
|
|
strlcpy(inst->fmts[INPUT_PORT].description, fmt_desc->description,
|
|
sizeof(inst->fmts[INPUT_PORT].description));
|
|
inst->prop.extradata_ctrls = EXTRADATA_NONE;
|
|
inst->buffer_mode_set[INPUT_PORT] = HAL_BUFFER_MODE_DYNAMIC;
|
|
inst->buffer_mode_set[OUTPUT_PORT] = HAL_BUFFER_MODE_STATIC;
|
|
inst->clk_data.frame_rate = (DEFAULT_FPS << 16);
|
|
|
|
inst->clk_data.operating_rate = (DEFAULT_FPS << 16);
|
|
inst->clk_data.is_legacy_cbr = false;
|
|
|
|
inst->buff_req.buffer[1].buffer_type = HAL_BUFFER_INPUT;
|
|
inst->buff_req.buffer[1].buffer_count_min_host =
|
|
inst->buff_req.buffer[1].buffer_count_actual =
|
|
MIN_NUM_ENC_OUTPUT_BUFFERS;
|
|
inst->buff_req.buffer[2].buffer_type = HAL_BUFFER_OUTPUT;
|
|
inst->buff_req.buffer[2].buffer_count_min_host =
|
|
inst->buff_req.buffer[2].buffer_count_actual =
|
|
MIN_NUM_ENC_CAPTURE_BUFFERS;
|
|
inst->buff_req.buffer[3].buffer_type = HAL_BUFFER_OUTPUT2;
|
|
inst->buff_req.buffer[3].buffer_count_min_host =
|
|
inst->buff_req.buffer[3].buffer_count_actual =
|
|
MIN_NUM_ENC_CAPTURE_BUFFERS;
|
|
inst->buff_req.buffer[4].buffer_type = HAL_BUFFER_EXTRADATA_INPUT;
|
|
inst->buff_req.buffer[5].buffer_type = HAL_BUFFER_EXTRADATA_OUTPUT;
|
|
inst->buff_req.buffer[6].buffer_type = HAL_BUFFER_EXTRADATA_OUTPUT2;
|
|
inst->buff_req.buffer[7].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH;
|
|
inst->buff_req.buffer[8].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH_1;
|
|
inst->buff_req.buffer[9].buffer_type = HAL_BUFFER_INTERNAL_SCRATCH_2;
|
|
inst->buff_req.buffer[10].buffer_type = HAL_BUFFER_INTERNAL_PERSIST;
|
|
inst->buff_req.buffer[11].buffer_type = HAL_BUFFER_INTERNAL_PERSIST_1;
|
|
inst->buff_req.buffer[12].buffer_type = HAL_BUFFER_INTERNAL_CMD_QUEUE;
|
|
inst->buff_req.buffer[13].buffer_type = HAL_BUFFER_INTERNAL_RECON;
|
|
msm_vidc_init_buffer_size_calculators(inst);
|
|
inst->static_rotation_flip_enabled = false;
|
|
inst->external_blur = false;
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
|
|
{
|
|
const struct msm_vidc_format_desc *fmt_desc = NULL;
|
|
int rc = 0;
|
|
|
|
if (!inst || !f) {
|
|
d_vpr_e("Invalid input, inst = %pK, f = %pK\n", inst, f);
|
|
return -EINVAL;
|
|
}
|
|
if (f->type == OUTPUT_MPLANE) {
|
|
fmt_desc = msm_comm_get_pixel_fmt_index(venc_output_formats,
|
|
ARRAY_SIZE(venc_output_formats), f->index, inst->sid);
|
|
f->flags = V4L2_FMT_FLAG_COMPRESSED;
|
|
} else if (f->type == INPUT_MPLANE) {
|
|
fmt_desc = msm_comm_get_pixel_fmt_index(venc_input_formats,
|
|
ARRAY_SIZE(venc_input_formats), f->index, inst->sid);
|
|
}
|
|
|
|
memset(f->reserved, 0, sizeof(f->reserved));
|
|
if (fmt_desc) {
|
|
strlcpy(f->description, fmt_desc->description,
|
|
sizeof(f->description));
|
|
f->pixelformat = fmt_desc->fourcc;
|
|
} else {
|
|
s_vpr_h(inst->sid, "No more formats found\n");
|
|
rc = -EINVAL;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
static int msm_venc_set_csc(struct msm_vidc_inst *inst,
|
|
u32 color_primaries, u32 custom_matrix)
|
|
{
|
|
int rc = 0;
|
|
int count = 0;
|
|
struct hfi_vpe_color_space_conversion vpe_csc;
|
|
struct msm_vidc_platform_resources *resources;
|
|
u32 *bias_coeff = NULL;
|
|
u32 *csc_limit = NULL;
|
|
u32 *csc_matrix = NULL;
|
|
struct hfi_device *hdev;
|
|
|
|
hdev = inst->core->device;
|
|
resources = &(inst->core->resources);
|
|
bias_coeff =
|
|
resources->csc_coeff_data->vpe_csc_custom_bias_coeff;
|
|
csc_limit =
|
|
resources->csc_coeff_data->vpe_csc_custom_limit_coeff;
|
|
csc_matrix =
|
|
resources->csc_coeff_data->vpe_csc_custom_matrix_coeff;
|
|
|
|
vpe_csc.input_color_primaries = color_primaries;
|
|
/* Custom bias, matrix & limit */
|
|
vpe_csc.custom_matrix_enabled = custom_matrix ? 7 : 0;
|
|
|
|
if (vpe_csc.custom_matrix_enabled && bias_coeff != NULL
|
|
&& csc_limit != NULL && csc_matrix != NULL) {
|
|
while (count < HAL_MAX_MATRIX_COEFFS) {
|
|
if (count < HAL_MAX_BIAS_COEFFS)
|
|
vpe_csc.csc_bias[count] =
|
|
bias_coeff[count];
|
|
if (count < HAL_MAX_LIMIT_COEFFS)
|
|
vpe_csc.csc_limit[count] =
|
|
csc_limit[count];
|
|
vpe_csc.csc_matrix[count] =
|
|
csc_matrix[count];
|
|
count = count + 1;
|
|
}
|
|
}
|
|
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VPE_COLOR_SPACE_CONVERSION,
|
|
&vpe_csc, sizeof(vpe_csc));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
|
|
{
|
|
int rc = 0;
|
|
struct msm_vidc_format *fmt = NULL;
|
|
struct msm_vidc_format_desc *fmt_desc = NULL;
|
|
struct v4l2_pix_format_mplane *mplane = NULL;
|
|
u32 color_format;
|
|
|
|
if (!inst || !f) {
|
|
d_vpr_e("Invalid input, inst = %pK, format = %pK\n", inst, f);
|
|
return -EINVAL;
|
|
}
|
|
|
|
/*
|
|
* First update inst format with new width/height/format
|
|
* Recalculate sizes/strides etc
|
|
* Perform necessary checks to continue with session
|
|
* Copy recalculated info into user format
|
|
*/
|
|
if (f->type == OUTPUT_MPLANE) {
|
|
fmt = &inst->fmts[OUTPUT_PORT];
|
|
fmt_desc = msm_comm_get_pixel_fmt_fourcc(venc_output_formats,
|
|
ARRAY_SIZE(venc_output_formats),
|
|
f->fmt.pix_mp.pixelformat, inst->sid);
|
|
if (!fmt_desc) {
|
|
s_vpr_e(inst->sid, "Invalid fmt set : %x\n",
|
|
f->fmt.pix_mp.pixelformat);
|
|
return -EINVAL;
|
|
}
|
|
strlcpy(fmt->name, fmt_desc->name, sizeof(fmt->name));
|
|
strlcpy(fmt->description, fmt_desc->description,
|
|
sizeof(fmt->description));
|
|
|
|
fmt->v4l2_fmt.type = f->type;
|
|
mplane = &fmt->v4l2_fmt.fmt.pix_mp;
|
|
mplane->width = f->fmt.pix_mp.width;
|
|
mplane->height = f->fmt.pix_mp.height;
|
|
mplane->pixelformat = f->fmt.pix_mp.pixelformat;
|
|
|
|
if (!inst->profile) {
|
|
rc = msm_venc_set_default_profile(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: Failed to set default profile type\n",
|
|
__func__);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "Failed to open instance\n");
|
|
goto exit;
|
|
}
|
|
|
|
mplane->plane_fmt[0].sizeimage =
|
|
msm_vidc_calculate_enc_output_frame_size(inst);
|
|
if (mplane->num_planes > 1)
|
|
mplane->plane_fmt[1].sizeimage =
|
|
msm_vidc_calculate_enc_output_extra_size(inst);
|
|
|
|
rc = msm_vidc_check_session_supported(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: session not supported\n", __func__);
|
|
goto exit;
|
|
}
|
|
update_log_ctxt(inst->sid, inst->session_type,
|
|
mplane->pixelformat);
|
|
memcpy(f, &fmt->v4l2_fmt, sizeof(struct v4l2_format));
|
|
} else if (f->type == INPUT_MPLANE) {
|
|
fmt = &inst->fmts[INPUT_PORT];
|
|
fmt_desc = msm_comm_get_pixel_fmt_fourcc(venc_input_formats,
|
|
ARRAY_SIZE(venc_input_formats),
|
|
f->fmt.pix_mp.pixelformat, inst->sid);
|
|
if (!fmt_desc) {
|
|
s_vpr_e(inst->sid, "Invalid fmt set : %x\n",
|
|
f->fmt.pix_mp.pixelformat);
|
|
return -EINVAL;
|
|
}
|
|
strlcpy(fmt->name, fmt_desc->name, sizeof(fmt->name));
|
|
strlcpy(fmt->description, fmt_desc->description,
|
|
sizeof(fmt->description));
|
|
|
|
inst->clk_data.opb_fourcc = f->fmt.pix_mp.pixelformat;
|
|
|
|
fmt->v4l2_fmt.type = f->type;
|
|
mplane = &fmt->v4l2_fmt.fmt.pix_mp;
|
|
mplane->width = f->fmt.pix_mp.width;
|
|
mplane->height = f->fmt.pix_mp.height;
|
|
mplane->pixelformat = f->fmt.pix_mp.pixelformat;
|
|
mplane->plane_fmt[0].sizeimage =
|
|
msm_vidc_calculate_enc_input_frame_size(inst);
|
|
if (mplane->num_planes > 1)
|
|
mplane->plane_fmt[1].sizeimage =
|
|
msm_vidc_calculate_enc_input_extra_size(inst);
|
|
color_format = msm_comm_convert_color_fmt(
|
|
f->fmt.pix_mp.pixelformat, inst->sid);
|
|
mplane->plane_fmt[0].bytesperline =
|
|
VENUS_Y_STRIDE(color_format, f->fmt.pix_mp.width);
|
|
mplane->plane_fmt[0].reserved[0] =
|
|
VENUS_Y_SCANLINES(color_format, f->fmt.pix_mp.height);
|
|
inst->bit_depth = MSM_VIDC_BIT_DEPTH_8;
|
|
if ((f->fmt.pix_mp.pixelformat ==
|
|
V4L2_PIX_FMT_NV12_TP10_UBWC) ||
|
|
(f->fmt.pix_mp.pixelformat ==
|
|
V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS)) {
|
|
inst->bit_depth = MSM_VIDC_BIT_DEPTH_10;
|
|
}
|
|
|
|
rc = msm_vidc_calculate_buffer_counts(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid,
|
|
"%s failed to calculate buffer count\n",
|
|
__func__);
|
|
return rc;
|
|
}
|
|
|
|
rc = msm_vidc_check_session_supported(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: session not supported\n", __func__);
|
|
goto exit;
|
|
}
|
|
|
|
memcpy(f, &fmt->v4l2_fmt, sizeof(struct v4l2_format));
|
|
} else {
|
|
s_vpr_e(inst->sid, "%s: Unsupported buf type: %d\n",
|
|
__func__, f->type);
|
|
rc = -EINVAL;
|
|
goto exit;
|
|
}
|
|
exit:
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_default_profile(struct msm_vidc_inst *inst)
|
|
{
|
|
if (!inst) {
|
|
d_vpr_e("%s: invalid params\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (get_v4l2_codec(inst) == V4L2_PIX_FMT_HEVC)
|
|
inst->profile = HFI_HEVC_PROFILE_MAIN;
|
|
else if (get_v4l2_codec(inst) == V4L2_PIX_FMT_H264)
|
|
inst->profile = HFI_H264_PROFILE_HIGH;
|
|
else
|
|
s_vpr_e(inst->sid, "%s: Invalid codec type %#x\n",
|
|
__func__, get_v4l2_codec(inst));
|
|
return 0;
|
|
}
|
|
|
|
int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
|
|
{
|
|
struct v4l2_format *fmt;
|
|
|
|
if (f->type == OUTPUT_MPLANE) {
|
|
fmt = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
fmt->fmt.pix_mp.plane_fmt[0].sizeimage =
|
|
msm_vidc_calculate_enc_output_frame_size(inst);
|
|
if (fmt->fmt.pix_mp.num_planes > 1)
|
|
fmt->fmt.pix_mp.plane_fmt[1].sizeimage =
|
|
msm_vidc_calculate_enc_output_extra_size(inst);
|
|
memcpy(f, fmt, sizeof(struct v4l2_format));
|
|
} else if (f->type == INPUT_MPLANE) {
|
|
fmt = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
fmt->fmt.pix_mp.plane_fmt[0].sizeimage =
|
|
msm_vidc_calculate_enc_input_frame_size(inst);
|
|
if (fmt->fmt.pix_mp.num_planes > 1) {
|
|
fmt->fmt.pix_mp.plane_fmt[1].sizeimage =
|
|
msm_vidc_calculate_enc_input_extra_size(inst);
|
|
}
|
|
memcpy(f, fmt, sizeof(struct v4l2_format));
|
|
} else {
|
|
s_vpr_e(inst->sid, "%s: Unsupported buf type: %d\n",
|
|
__func__, f->type);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int msm_venc_ctrl_init(struct msm_vidc_inst *inst,
|
|
const struct v4l2_ctrl_ops *ctrl_ops)
|
|
{
|
|
return msm_comm_ctrl_init(inst, msm_venc_ctrls,
|
|
ARRAY_SIZE(msm_venc_ctrls), ctrl_ops);
|
|
}
|
|
|
|
static int msm_venc_resolve_rc_enable(struct msm_vidc_inst *inst,
|
|
struct v4l2_ctrl *ctrl)
|
|
{
|
|
struct v4l2_ctrl *rc_mode;
|
|
u32 codec;
|
|
|
|
if (!ctrl->val) {
|
|
s_vpr_h(inst->sid, "RC is not enabled. Setting RC OFF\n");
|
|
inst->rc_type = RATE_CONTROL_OFF;
|
|
} else {
|
|
rc_mode = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE_MODE);
|
|
inst->rc_type = rc_mode->val;
|
|
}
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (msm_vidc_lossless_encode
|
|
&& (codec == V4L2_PIX_FMT_HEVC ||
|
|
codec == V4L2_PIX_FMT_H264)) {
|
|
s_vpr_h(inst->sid,
|
|
"Reset RC mode to RC_LOSSLESS for HEVC lossless encoding\n");
|
|
inst->rc_type = RATE_CONTROL_LOSSLESS;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int msm_venc_resolve_rate_control(struct msm_vidc_inst *inst,
|
|
struct v4l2_ctrl *ctrl)
|
|
{
|
|
if (inst->rc_type == RATE_CONTROL_LOSSLESS) {
|
|
s_vpr_h(inst->sid,
|
|
"Skip RC mode when enabling lossless encoding\n");
|
|
return 0;
|
|
}
|
|
|
|
if (inst->rc_type == RATE_CONTROL_OFF) {
|
|
s_vpr_e(inst->sid, "RC is not enabled.\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) &&
|
|
get_v4l2_codec(inst) != V4L2_PIX_FMT_HEVC) {
|
|
s_vpr_e(inst->sid, "CQ supported only for HEVC\n");
|
|
return -EINVAL;
|
|
}
|
|
inst->rc_type = ctrl->val;
|
|
return 0;
|
|
}
|
|
|
|
static int msm_venc_update_bitrate(struct msm_vidc_inst *inst)
|
|
{
|
|
u32 cabac_max_bitrate = 0;
|
|
|
|
if (!inst) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (get_v4l2_codec(inst) == V4L2_PIX_FMT_H264) {
|
|
cabac_max_bitrate = inst->capability.cap[CAP_CABAC_BITRATE].max;
|
|
if ((inst->clk_data.bitrate > cabac_max_bitrate) &&
|
|
(inst->entropy_mode == HFI_H264_ENTROPY_CABAC)) {
|
|
s_vpr_h(inst->sid,
|
|
"%s: update bitrate %u to max allowed cabac bitrate %u\n",
|
|
__func__, inst->clk_data.bitrate,
|
|
cabac_max_bitrate);
|
|
inst->clk_data.bitrate = cabac_max_bitrate;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
|
|
{
|
|
int rc = 0;
|
|
struct msm_vidc_mastering_display_colour_sei_payload *mdisp_sei = NULL;
|
|
struct msm_vidc_content_light_level_sei_payload *cll_sei = NULL;
|
|
u32 i_qp_min, i_qp_max, p_qp_min, p_qp_max, b_qp_min, b_qp_max;
|
|
struct v4l2_format *f;
|
|
u32 codec;
|
|
u32 sid;
|
|
|
|
if (!inst || !inst->core || !inst->core->device || !ctrl) {
|
|
d_vpr_e("%s: invalid parameters\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
mdisp_sei = &(inst->hdr10_sei_params.disp_color_sei);
|
|
cll_sei = &(inst->hdr10_sei_params.cll_sei);
|
|
codec = get_v4l2_codec(inst);
|
|
sid = inst->sid;
|
|
|
|
s_vpr_h(sid, "%s: name %s, id 0x%x value %d\n",
|
|
__func__, ctrl->name, ctrl->id, ctrl->val);
|
|
|
|
switch (ctrl->id) {
|
|
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
if (inst->all_intra) {
|
|
s_vpr_h(sid,
|
|
"%s: ignore dynamic gop size for all intra\n",
|
|
__func__);
|
|
break;
|
|
}
|
|
rc = msm_venc_set_intra_period(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set intra period failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_request_keyframe(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set bitrate failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
|
|
{
|
|
rc = msm_venc_resolve_rate_control(inst, ctrl);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set bitrate mode failed\n", __func__);
|
|
if (inst->state < MSM_VIDC_LOAD_RESOURCES)
|
|
msm_vidc_calculate_buffer_counts(inst);
|
|
break;
|
|
}
|
|
case V4L2_CID_MPEG_VIDEO_BITRATE:
|
|
inst->clk_data.bitrate = ctrl->val;
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_update_bitrate(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: Update bitrate failed\n",
|
|
__func__);
|
|
rc = msm_venc_set_bitrate(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set bitrate failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE:
|
|
inst->clk_data.frame_rate = ctrl->val;
|
|
/* For HEIC image encode, set fps to 1 */
|
|
if (is_grid_session(inst)) {
|
|
s_vpr_h(sid, "%s: set fps to 1 for HEIC\n",
|
|
__func__);
|
|
inst->clk_data.frame_rate = 1 << 16;
|
|
}
|
|
if (inst->state < MSM_VIDC_LOAD_RESOURCES)
|
|
msm_vidc_calculate_buffer_counts(inst);
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_frame_rate(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set frame rate failed\n",
|
|
__func__);
|
|
msm_comm_release_timestamps(inst);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
|
|
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
|
|
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
|
|
if (codec != V4L2_PIX_FMT_HEVC && codec != V4L2_PIX_FMT_H264) {
|
|
s_vpr_e(sid,
|
|
"Slice mode not supported for encoder %#x\n",
|
|
codec);
|
|
rc = -ENOTSUPP;
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
|
|
inst->flags &= ~VIDC_SECURE;
|
|
if (ctrl->val)
|
|
inst->flags |= VIDC_SECURE;
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
f->fmt.pix_mp.num_planes = 1;
|
|
s_vpr_h(sid, "%s: num planes %d for secure sessions\n",
|
|
__func__, f->fmt.pix_mp.num_planes);
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_ltr_useframe(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: ltr useframe failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_ltr_markframe(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: ltr markframe failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE:
|
|
inst->flags &= ~VIDC_TURBO;
|
|
if (ctrl->val == INT_MAX)
|
|
inst->flags |= VIDC_TURBO;
|
|
else
|
|
inst->clk_data.operating_rate = ctrl->val;
|
|
/* For HEIC image encode, set operating rate to 1 */
|
|
if (is_grid_session(inst)) {
|
|
s_vpr_h(sid, "%s: set operating rate to 1 for HEIC\n",
|
|
__func__);
|
|
inst->clk_data.operating_rate = 1 << 16;
|
|
}
|
|
if (inst->state < MSM_VIDC_LOAD_RESOURCES)
|
|
msm_vidc_calculate_buffer_counts(inst);
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_operating_rate(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set operating rate failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE:
|
|
inst->clk_data.low_latency_mode = !!ctrl->val;
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VENC_HDR_INFO: {
|
|
u32 info_type = ((u32)ctrl->val >> 28) & 0xF;
|
|
u32 val = (ctrl->val & 0xFFFFFFF);
|
|
|
|
s_vpr_h(sid, "Ctrl:%d, HDR Info with value %u (%#X)",
|
|
info_type, val, ctrl->val);
|
|
switch (info_type) {
|
|
case MSM_VIDC_RGB_PRIMARY_00:
|
|
mdisp_sei->nDisplayPrimariesX[0] = val;
|
|
break;
|
|
case MSM_VIDC_RGB_PRIMARY_01:
|
|
mdisp_sei->nDisplayPrimariesY[0] = val;
|
|
break;
|
|
case MSM_VIDC_RGB_PRIMARY_10:
|
|
mdisp_sei->nDisplayPrimariesX[1] = val;
|
|
break;
|
|
case MSM_VIDC_RGB_PRIMARY_11:
|
|
mdisp_sei->nDisplayPrimariesY[1] = val;
|
|
break;
|
|
case MSM_VIDC_RGB_PRIMARY_20:
|
|
mdisp_sei->nDisplayPrimariesX[2] = val;
|
|
break;
|
|
case MSM_VIDC_RGB_PRIMARY_21:
|
|
mdisp_sei->nDisplayPrimariesY[2] = val;
|
|
break;
|
|
case MSM_VIDC_WHITEPOINT_X:
|
|
mdisp_sei->nWhitePointX = val;
|
|
break;
|
|
case MSM_VIDC_WHITEPOINT_Y:
|
|
mdisp_sei->nWhitePointY = val;
|
|
break;
|
|
case MSM_VIDC_MAX_DISP_LUM:
|
|
mdisp_sei->nMaxDisplayMasteringLuminance = val;
|
|
break;
|
|
case MSM_VIDC_MIN_DISP_LUM:
|
|
mdisp_sei->nMinDisplayMasteringLuminance = val;
|
|
break;
|
|
case MSM_VIDC_RGB_MAX_CLL:
|
|
cll_sei->nMaxContentLight = val;
|
|
break;
|
|
case MSM_VIDC_RGB_MAX_FLL:
|
|
cll_sei->nMaxPicAverageLight = val;
|
|
break;
|
|
default:
|
|
s_vpr_e(sid,
|
|
"Unknown Ctrl:%d, not part of HDR Info with value %u",
|
|
info_type, val);
|
|
}
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA:
|
|
if (ctrl->val == EXTRADATA_NONE)
|
|
inst->prop.extradata_ctrls = 0;
|
|
else
|
|
inst->prop.extradata_ctrls |= ctrl->val;
|
|
|
|
if ((inst->prop.extradata_ctrls & EXTRADATA_ENC_INPUT_ROI) ||
|
|
(inst->prop.extradata_ctrls & EXTRADATA_ENC_INPUT_HDR10PLUS)) {
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
f->fmt.pix_mp.num_planes = 2;
|
|
f->fmt.pix_mp.plane_fmt[1].sizeimage =
|
|
msm_vidc_calculate_enc_input_extra_size(inst);
|
|
}
|
|
|
|
if (inst->prop.extradata_ctrls & EXTRADATA_ADVANCED) {
|
|
f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
f->fmt.pix_mp.num_planes = 2;
|
|
f->fmt.pix_mp.plane_fmt[1].sizeimage =
|
|
msm_vidc_calculate_enc_output_extra_size(inst);
|
|
}
|
|
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
|
|
rc = msm_venc_resolve_rc_enable(inst, ctrl);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set rc enable failed\n", __func__);
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
|
|
inst->profile = msm_comm_v4l2_to_hfi(ctrl->id, ctrl->val, sid);
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
|
|
inst->level = msm_comm_v4l2_to_hfi(ctrl->id, ctrl->val, sid);
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
|
|
inst->level |=
|
|
(msm_comm_v4l2_to_hfi(ctrl->id, ctrl->val, sid) << 28);
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
|
|
i_qp_min = inst->capability.cap[CAP_I_FRAME_QP].min;
|
|
i_qp_max = inst->capability.cap[CAP_I_FRAME_QP].max;
|
|
p_qp_min = inst->capability.cap[CAP_P_FRAME_QP].min;
|
|
p_qp_max = inst->capability.cap[CAP_P_FRAME_QP].max;
|
|
b_qp_min = inst->capability.cap[CAP_B_FRAME_QP].min;
|
|
b_qp_max = inst->capability.cap[CAP_B_FRAME_QP].max;
|
|
if ((ctrl->val & 0xff) < i_qp_min ||
|
|
((ctrl->val >> 8) & 0xff) < p_qp_min ||
|
|
((ctrl->val >> 16) & 0xff) < b_qp_min ||
|
|
(ctrl->val & 0xff) > i_qp_max ||
|
|
((ctrl->val >> 8) & 0xff) > p_qp_max ||
|
|
((ctrl->val >> 16) & 0xff) > b_qp_max) {
|
|
s_vpr_e(sid, "Invalid QP %#x\n", ctrl->val);
|
|
return -EINVAL;
|
|
}
|
|
if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP)
|
|
inst->client_set_ctrls |= CLIENT_SET_MIN_QP;
|
|
else
|
|
inst->client_set_ctrls |= CLIENT_SET_MAX_QP;
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
|
|
i_qp_min = inst->capability.cap[CAP_I_FRAME_QP].min;
|
|
i_qp_max = inst->capability.cap[CAP_I_FRAME_QP].max;
|
|
if (ctrl->val < i_qp_min || ctrl->val > i_qp_max) {
|
|
s_vpr_e(sid, "Invalid I QP %#x\n", ctrl->val);
|
|
return -EINVAL;
|
|
}
|
|
inst->client_set_ctrls |= CLIENT_SET_I_QP;
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_dyn_qp(inst, ctrl);
|
|
if (rc)
|
|
s_vpr_e(sid,
|
|
"%s: setting dyn frame QP failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
|
|
p_qp_min = inst->capability.cap[CAP_P_FRAME_QP].min;
|
|
p_qp_max = inst->capability.cap[CAP_P_FRAME_QP].max;
|
|
if (ctrl->val < p_qp_min || ctrl->val > p_qp_max) {
|
|
s_vpr_e(sid, "Invalid P QP %#x\n", ctrl->val);
|
|
return -EINVAL;
|
|
}
|
|
inst->client_set_ctrls |= CLIENT_SET_P_QP;
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
|
|
b_qp_min = inst->capability.cap[CAP_B_FRAME_QP].min;
|
|
b_qp_max = inst->capability.cap[CAP_B_FRAME_QP].max;
|
|
if (ctrl->val < b_qp_min || ctrl->val > b_qp_max) {
|
|
s_vpr_e(sid, "Invalid B QP %#x\n", ctrl->val);
|
|
return -EINVAL;
|
|
}
|
|
inst->client_set_ctrls |= CLIENT_SET_B_QP;
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_hp_layer(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set dyn hp layer failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_base_layer_priority_id(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set baselayer id failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_layer_bitrate(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set layer bitrate failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_B_FRAMES:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
s_vpr_e(sid,
|
|
"%s: Dynamic setting of Bframe is not supported\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_DIMENSIONS:
|
|
if (inst->state < MSM_VIDC_START_DONE) {
|
|
if ((ctrl->val != MSM_VIDC_BLUR_INTERNAL) &&
|
|
(ctrl->val != MSM_VIDC_BLUR_DISABLE)) {
|
|
inst->external_blur = true;
|
|
}
|
|
} else if (inst->state == MSM_VIDC_START_DONE) {
|
|
if (!inst->external_blur) {
|
|
s_vpr_e(sid, "external blur not enabled");
|
|
break;
|
|
}
|
|
if (ctrl->val == MSM_VIDC_BLUR_EXTERNAL_DYNAMIC) {
|
|
s_vpr_h(sid,
|
|
"external blur setting already enabled\n",
|
|
__func__);
|
|
break;
|
|
} else if (ctrl->val == MSM_VIDC_BLUR_INTERNAL) {
|
|
s_vpr_e(sid,
|
|
"cannot change to internal blur config dynamically\n",
|
|
__func__);
|
|
break;
|
|
} else {
|
|
rc = msm_venc_set_blur_resolution(inst);
|
|
if (rc)
|
|
s_vpr_e(sid,
|
|
"%s: set blur resolution failed\n",
|
|
__func__);
|
|
}
|
|
}
|
|
break;
|
|
case V4L2_CID_HFLIP:
|
|
case V4L2_CID_VFLIP:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_dynamic_flip(inst);
|
|
if (rc)
|
|
s_vpr_e(sid, "%s: set flip failed\n", __func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_CVP_FRAME_RATE:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_cvp_skipratio(inst);
|
|
if (rc)
|
|
s_vpr_e(sid,
|
|
"%s: set cvp skip ratio failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY:
|
|
if (inst->state == MSM_VIDC_START_DONE) {
|
|
rc = msm_venc_set_frame_quality(inst);
|
|
if (rc)
|
|
s_vpr_e(sid,
|
|
"%s: set frame quality failed\n",
|
|
__func__);
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE:
|
|
/* For HEIC image encode, set fps to 1 */
|
|
if (ctrl->val) {
|
|
s_vpr_h(sid, "%s: set fps to 1 for HEIC\n",
|
|
__func__);
|
|
inst->clk_data.frame_rate = 1 << 16;
|
|
s_vpr_h(sid, "%s: set operating rate to 1 for HEIC\n",
|
|
__func__);
|
|
inst->clk_data.operating_rate = 1 << 16;
|
|
}
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE:
|
|
inst->full_range = ctrl->val;
|
|
break;
|
|
case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
|
|
inst->entropy_mode = msm_comm_v4l2_to_hfi(
|
|
V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
|
|
ctrl->val, inst->sid);
|
|
break;
|
|
case V4L2_CID_MPEG_VIDC_CAPTURE_FRAME_RATE:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE:
|
|
case V4L2_CID_ROTATE:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT:
|
|
case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
|
|
case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
|
|
case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_AU_DELIMITER:
|
|
case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_CUSTOM_MATRIX:
|
|
case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_VUI_TIMING_INFO:
|
|
case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
|
|
case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
|
|
case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY:
|
|
case V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM:
|
|
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
|
|
case V4L2_CID_MPEG_VIDC_VENC_NATIVE_RECORDER:
|
|
case V4L2_CID_MPEG_VIDC_VENC_RC_TIMESTAMP_DISABLE:
|
|
case V4L2_CID_MPEG_VIDEO_VBV_DELAY:
|
|
case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET:
|
|
case V4L2_CID_MPEG_VIDC_VENC_BITRATE_SAVINGS:
|
|
case V4L2_CID_MPEG_VIDC_VENC_BITRATE_BOOST:
|
|
case V4L2_CID_MPEG_VIDC_SUPERFRAME:
|
|
s_vpr_h(sid, "Control set: ID : 0x%x Val : %d\n",
|
|
ctrl->id, ctrl->val);
|
|
break;
|
|
default:
|
|
s_vpr_e(sid, "Unsupported index: 0x%x\n", ctrl->id);
|
|
rc = -ENOTSUPP;
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_frame_size(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_frame_size frame_sz;
|
|
struct v4l2_format *f;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
frame_sz.buffer_type = HFI_BUFFER_INPUT;
|
|
frame_sz.width = f->fmt.pix_mp.width;
|
|
frame_sz.height = f->fmt.pix_mp.height;
|
|
s_vpr_h(inst->sid, "%s: input %d %d\n", __func__,
|
|
frame_sz.width, frame_sz.height);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_FRAME_SIZE, &frame_sz, sizeof(frame_sz));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: failed to set input frame size %d %d\n",
|
|
__func__, frame_sz.width, frame_sz.height);
|
|
return rc;
|
|
}
|
|
|
|
f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
frame_sz.buffer_type = HFI_BUFFER_OUTPUT;
|
|
frame_sz.width = f->fmt.pix_mp.width;
|
|
frame_sz.height = f->fmt.pix_mp.height;
|
|
/* firmware needs grid size in output where as
|
|
* client sends out full resolution in output port */
|
|
if (is_grid_session(inst)) {
|
|
frame_sz.width = frame_sz.height = HEIC_GRID_DIMENSION;
|
|
}
|
|
s_vpr_h(inst->sid, "%s: output %d %d\n", __func__,
|
|
frame_sz.width, frame_sz.height);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_FRAME_SIZE, &frame_sz, sizeof(frame_sz));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: failed to set output frame size %d %d\n",
|
|
__func__, frame_sz.width, frame_sz.height);
|
|
return rc;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_frame_rate(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_frame_rate frame_rate;
|
|
struct msm_vidc_capability *capability;
|
|
u32 fps_max;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
capability = &inst->capability;
|
|
|
|
/* Check frame rate */
|
|
if (inst->all_intra)
|
|
fps_max = capability->cap[CAP_ALLINTRA_MAX_FPS].max;
|
|
else
|
|
fps_max = capability->cap[CAP_FRAMERATE].max;
|
|
|
|
if (inst->clk_data.frame_rate >> 16 > fps_max) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: Unsupported frame rate, fps %u, max_fps %u\n",
|
|
__func__, inst->clk_data.frame_rate >> 16, fps_max);
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
frame_rate.buffer_type = HFI_BUFFER_OUTPUT;
|
|
frame_rate.frame_rate = inst->clk_data.frame_rate;
|
|
|
|
s_vpr_h(inst->sid, "%s: %#x\n", __func__, frame_rate.frame_rate);
|
|
|
|
rc = call_hfi_op(hdev, session_set_property,
|
|
inst->session, HFI_PROPERTY_CONFIG_FRAME_RATE,
|
|
&frame_rate, sizeof(frame_rate));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_store_timestamp(struct msm_vidc_inst *inst, u64 timestamp_us)
|
|
{
|
|
struct msm_vidc_timestamps *entry, *node, *prev = NULL;
|
|
int count = 0;
|
|
int rc = 0;
|
|
struct v4l2_ctrl *superframe_ctrl = NULL;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid parameters\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!inst->core->resources.enc_auto_dynamic_fps ||
|
|
is_image_session(inst))
|
|
return rc;
|
|
|
|
mutex_lock(&inst->timestamps.lock);
|
|
list_for_each_entry(node, &inst->timestamps.list, list) {
|
|
count++;
|
|
if (timestamp_us <= node->timestamp_us) {
|
|
s_vpr_e(inst->sid, "%s: invalid ts %llu, exist %llu\n",
|
|
__func__, timestamp_us, node->timestamp_us);
|
|
goto unlock;
|
|
}
|
|
}
|
|
|
|
/* Maintain a sliding window */
|
|
entry = NULL;
|
|
if (count >= VENC_MAX_TIMESTAMP_LIST_SIZE) {
|
|
entry = list_first_entry(&inst->timestamps.list,
|
|
struct msm_vidc_timestamps, list);
|
|
list_del_init(&entry->list);
|
|
}
|
|
if (!entry) {
|
|
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
|
if (!entry) {
|
|
s_vpr_e(inst->sid, "%s: ts malloc failure\n",
|
|
__func__);
|
|
rc = -ENOMEM;
|
|
goto unlock;
|
|
}
|
|
}
|
|
|
|
entry->timestamp_us = timestamp_us;
|
|
entry->framerate = inst->clk_data.frame_rate;
|
|
prev = list_last_entry(&inst->timestamps.list,
|
|
struct msm_vidc_timestamps, list);
|
|
list_add_tail(&entry->list, &inst->timestamps.list);
|
|
|
|
if (!count)
|
|
goto unlock;
|
|
|
|
entry->framerate = msm_comm_calc_framerate(inst,
|
|
timestamp_us, prev->timestamp_us);
|
|
|
|
/* if framerate changed and stable for 2 frames, set to firmware */
|
|
if (entry->framerate == prev->framerate &&
|
|
entry->framerate != inst->clk_data.frame_rate) {
|
|
superframe_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_SUPERFRAME);
|
|
if (superframe_ctrl->val > 1)
|
|
inst->clk_data.frame_rate = entry->framerate * superframe_ctrl->val;
|
|
else
|
|
inst->clk_data.frame_rate = entry->framerate;
|
|
s_vpr_l(inst->sid, "%s: updated fps to %u\n",
|
|
__func__, (inst->clk_data.frame_rate >> 16));
|
|
msm_venc_set_frame_rate(inst);
|
|
}
|
|
|
|
unlock:
|
|
mutex_unlock(&inst->timestamps.lock);
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_color_format(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct msm_vidc_format_constraint *fmt_constraints;
|
|
struct v4l2_format *f;
|
|
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
rc = msm_comm_set_color_format(inst, HAL_BUFFER_INPUT,
|
|
f->fmt.pix_mp.pixelformat);
|
|
if (rc)
|
|
return rc;
|
|
|
|
fmt_constraints = msm_comm_get_pixel_fmt_constraints(
|
|
enc_pix_format_constraints,
|
|
ARRAY_SIZE(enc_pix_format_constraints),
|
|
f->fmt.pix_mp.pixelformat, inst->sid);
|
|
if (fmt_constraints) {
|
|
rc = msm_comm_set_color_format_constraints(inst,
|
|
HAL_BUFFER_INPUT,
|
|
fmt_constraints);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "Set constraints for %d failed\n",
|
|
f->fmt.pix_mp.pixelformat);
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_buffer_counts(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct msm_vidc_format *fmt;
|
|
enum hal_buffer buffer_type;
|
|
|
|
if (!inst) {
|
|
d_vpr_e("%s: invalid params\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
buffer_type = HAL_BUFFER_INPUT;
|
|
fmt = &inst->fmts[INPUT_PORT];
|
|
rc = msm_comm_set_buffer_count(inst,
|
|
fmt->count_min,
|
|
fmt->count_actual,
|
|
buffer_type);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: failed to set bufcounts(%#x)\n",
|
|
__func__, buffer_type);
|
|
return -EINVAL;
|
|
}
|
|
|
|
buffer_type = HAL_BUFFER_OUTPUT;
|
|
fmt = &inst->fmts[OUTPUT_PORT];
|
|
rc = msm_comm_set_buffer_count(inst,
|
|
fmt->count_min,
|
|
fmt->count_actual,
|
|
buffer_type);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: failed to set buf counts(%#x)\n",
|
|
__func__, buffer_type);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_secure_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_enable enable;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_SECURE);
|
|
enable.enable = !!ctrl->val;
|
|
|
|
if (enable.enable) {
|
|
codec = get_v4l2_codec(inst);
|
|
if (!(codec == V4L2_PIX_FMT_H264 ||
|
|
codec == V4L2_PIX_FMT_HEVC)) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: Secure mode only allowed for HEVC/H264\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_SECURE_SESSION, &enable, sizeof(enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_priority(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_enable enable;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
enable.enable = is_realtime_session(inst);
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_REALTIME, &enable, sizeof(enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_operating_rate(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_operating_rate op_rate;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
|
|
hdev = inst->core->device;
|
|
op_rate.operating_rate = inst->clk_data.operating_rate;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, op_rate.operating_rate >> 16);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_OPERATING_RATE, &op_rate, sizeof(op_rate));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_profile_level(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_profile_level profile_level;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (!inst->profile) {
|
|
s_vpr_e(inst->sid, "%s: skip as client did not set profile\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
profile_level.profile = inst->profile;
|
|
profile_level.level = inst->level;
|
|
|
|
s_vpr_h(inst->sid, "%s: %#x %#x\n", __func__,
|
|
profile_level.profile, profile_level.level);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT, &profile_level,
|
|
sizeof(profile_level));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_idr_period(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_idr_period idr_period;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
idr_period.idr_period = 1;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, idr_period.idr_period);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD, &idr_period,
|
|
sizeof(idr_period));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_adaptive_bframes(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_enable enable;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
enable.enable = true;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_ADAPTIVE_B, &enable, sizeof(enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
void msm_venc_adjust_gop_size(struct msm_vidc_inst *inst)
|
|
{
|
|
struct v4l2_ctrl *hier_ctrl;
|
|
struct v4l2_ctrl *gop_size_ctrl;
|
|
s32 val;
|
|
|
|
gop_size_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE);
|
|
|
|
/*
|
|
* Layer encoding needs GOP size to be multiple of subgop size
|
|
* And subgop size is 2 ^ number of enhancement layers
|
|
*/
|
|
hier_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
if (hier_ctrl->val > 1) {
|
|
u32 min_gop_size;
|
|
u32 num_subgops;
|
|
|
|
min_gop_size = (1 << (hier_ctrl->val - 1));
|
|
num_subgops = (gop_size_ctrl->val + (min_gop_size >> 1)) /
|
|
min_gop_size;
|
|
if (num_subgops)
|
|
val = num_subgops * min_gop_size;
|
|
else
|
|
val = min_gop_size;
|
|
|
|
update_ctrl(gop_size_ctrl, val, inst->sid);
|
|
}
|
|
}
|
|
|
|
int msm_venc_set_intra_period(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *gop_size = NULL;
|
|
struct v4l2_ctrl *bframes = NULL;
|
|
struct v4l2_ctrl *max_layer = NULL;
|
|
struct v4l2_ctrl *frame_t = NULL;
|
|
struct hfi_intra_period intra_period = {
|
|
.pframes = 0,
|
|
.bframes = 0
|
|
};
|
|
struct hfi_adaptive_p_b_intra_period adaptive_p_b_intra_period = {
|
|
.nframes = 0
|
|
};
|
|
u32 codec;
|
|
bool adaptive_bframes = false;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
|
|
gop_size = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE);
|
|
max_layer = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
codec = get_v4l2_codec(inst);
|
|
|
|
intra_period.pframes = gop_size->val;
|
|
|
|
if (!max_layer->val && codec == V4L2_PIX_FMT_H264) {
|
|
/*
|
|
* At this point we've already made decision on bframe.
|
|
* Control value gives updated bframe value.
|
|
*/
|
|
bframes = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES);
|
|
intra_period.bframes = bframes->val;
|
|
if (intra_period.bframes)
|
|
adaptive_bframes = true;
|
|
}
|
|
|
|
if (max_layer->val > 1) {
|
|
if (frame_t->val ==
|
|
V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) {
|
|
if (codec == V4L2_PIX_FMT_HEVC) {
|
|
adaptive_p_b_intra_period.nframes =
|
|
gop_size->val;
|
|
adaptive_bframes = true;
|
|
} else {
|
|
d_vpr_e("%s: Hier-B supported for HEVC only\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
} else if (frame_t->val ==
|
|
V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) {
|
|
msm_venc_adjust_gop_size(inst);
|
|
intra_period.pframes = gop_size->val;
|
|
intra_period.bframes = 0;
|
|
adaptive_bframes = false;
|
|
}
|
|
}
|
|
|
|
if (inst->state == MSM_VIDC_START_DONE &&
|
|
!intra_period.pframes && !intra_period.bframes) {
|
|
s_vpr_h(inst->sid,
|
|
"%s: Switch from IPPP to All Intra is not allowed\n",
|
|
__func__);
|
|
return rc;
|
|
}
|
|
|
|
if (frame_t->val ==
|
|
V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B &&
|
|
codec == V4L2_PIX_FMT_HEVC) {
|
|
s_vpr_h(inst->sid, "%s: nframes: %d\n",
|
|
__func__, adaptive_p_b_intra_period.nframes);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD,
|
|
&adaptive_p_b_intra_period,
|
|
sizeof(adaptive_p_b_intra_period));
|
|
|
|
} else {
|
|
s_vpr_h(inst->sid, "%s: pframes: %d bframes: %d\n",
|
|
__func__, intra_period.pframes,
|
|
intra_period.bframes);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD,
|
|
&intra_period, sizeof(intra_period));
|
|
}
|
|
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
if (adaptive_bframes) {
|
|
rc = msm_venc_set_adaptive_bframes(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: set property failed\n",
|
|
__func__);
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_request_keyframe(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
s_vpr_h(inst->sid, "%s\n", __func__);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME, NULL, 0);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_rate_control(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
u32 hfi_rc, codec;
|
|
u32 height, width, mbpf;
|
|
struct v4l2_format *f;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
|
|
hdev = inst->core->device;
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
codec = get_v4l2_codec(inst);
|
|
height = f->fmt.pix_mp.height;
|
|
width = f->fmt.pix_mp.width;
|
|
mbpf = NUM_MBS_PER_FRAME(height, width);
|
|
|
|
if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_MBR_VFR)
|
|
inst->rc_type = V4L2_MPEG_VIDEO_BITRATE_MODE_MBR;
|
|
else if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
|
|
inst->clk_data.low_latency_mode)
|
|
inst->rc_type = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
|
|
|
|
if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR ||
|
|
inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR)
|
|
inst->clk_data.low_latency_mode = true;
|
|
|
|
switch (inst->rc_type) {
|
|
case RATE_CONTROL_OFF:
|
|
case RATE_CONTROL_LOSSLESS:
|
|
hfi_rc = HFI_RATE_CONTROL_OFF;
|
|
break;
|
|
case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
|
|
hfi_rc = HFI_RATE_CONTROL_CBR_CFR;
|
|
break;
|
|
case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
|
|
hfi_rc = HFI_RATE_CONTROL_VBR_CFR;
|
|
break;
|
|
case V4L2_MPEG_VIDEO_BITRATE_MODE_MBR:
|
|
hfi_rc = HFI_RATE_CONTROL_MBR_CFR;
|
|
break;
|
|
case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR:
|
|
hfi_rc = HFI_RATE_CONTROL_CBR_VFR;
|
|
break;
|
|
case V4L2_MPEG_VIDEO_BITRATE_MODE_CQ:
|
|
hfi_rc = HFI_RATE_CONTROL_CQ;
|
|
break;
|
|
default:
|
|
hfi_rc = HFI_RATE_CONTROL_OFF;
|
|
s_vpr_e(inst->sid,
|
|
"Invalid Rate control setting: %d Default RCOFF\n",
|
|
inst->rc_type);
|
|
break;
|
|
}
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, inst->rc_type);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_RATE_CONTROL, &hfi_rc,
|
|
sizeof(u32));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
int msm_venc_set_vbv_delay(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
bool is_legacy_cbr;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
u32 codec, height, width, buf_size;
|
|
struct hfi_vbv_hrd_buf_size hrd_buf_size;
|
|
struct v4l2_format *f;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
|
|
hdev = inst->core->device;
|
|
f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
codec = get_v4l2_codec(inst);
|
|
height = f->fmt.pix_mp.height;
|
|
width = f->fmt.pix_mp.width;
|
|
|
|
/* vbv delay is required for CBR_CFR and CBR_VFR only */
|
|
if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR &&
|
|
inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR)
|
|
return 0;
|
|
|
|
/* Default behavior */
|
|
is_legacy_cbr = false;
|
|
buf_size = CBR_PLUS_BUF_SIZE;
|
|
|
|
/*
|
|
* Client can set vbv delay only when
|
|
* resolution is between VGA and 720p
|
|
*/
|
|
if (res_is_greater_than_or_equal_to(width, height, MIN_CBRPLUS_W,
|
|
MIN_CBRPLUS_H) && res_is_less_than_or_equal_to(width, height,
|
|
MAX_CBR_W, MAX_CBR_H)) {
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_VBV_DELAY);
|
|
if (ctrl->val == LEGACY_CBR_BUF_SIZE) {
|
|
is_legacy_cbr = true;
|
|
buf_size = LEGACY_CBR_BUF_SIZE;
|
|
goto set_vbv_delay;
|
|
} else if (ctrl->val == CBR_PLUS_BUF_SIZE) {
|
|
is_legacy_cbr = false;
|
|
buf_size = CBR_PLUS_BUF_SIZE;
|
|
goto set_vbv_delay;
|
|
}
|
|
}
|
|
|
|
/* Enable legacy cbr if resolution < MIN_CBRPLUS (720p) */
|
|
if (res_is_less_than(width, height, MAX_CBR_W, MAX_CBR_H)) {
|
|
is_legacy_cbr = true;
|
|
buf_size = LEGACY_CBR_BUF_SIZE;
|
|
goto set_vbv_delay;
|
|
}
|
|
|
|
set_vbv_delay:
|
|
inst->clk_data.is_legacy_cbr = is_legacy_cbr;
|
|
hrd_buf_size.vbv_hrd_buf_size = buf_size;
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, hrd_buf_size.vbv_hrd_buf_size);
|
|
rc = call_hfi_op(hdev, session_set_property,
|
|
(void *)inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_VBV_HRD_BUF_SIZE,
|
|
(void *)&hrd_buf_size, sizeof(hrd_buf_size));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
int msm_venc_set_input_timestamp_rc(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_enable enable;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VENC_RC_TIMESTAMP_DISABLE);
|
|
/*
|
|
* HFI values:
|
|
* 0 - time delta is calculated based on buffer timestamp
|
|
* 1 - ignores buffer timestamp and fw derives time delta based
|
|
* on input frame rate.
|
|
*/
|
|
enable.enable = !!ctrl->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_DISABLE_RC_TIMESTAMP, &enable,
|
|
sizeof(enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_bitrate(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_bitrate bitrate;
|
|
struct hfi_enable enable;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
|
|
return 0;
|
|
|
|
if (inst->layer_bitrate) {
|
|
s_vpr_h(inst->sid, "%s: Layer bitrate is enabled\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
enable.enable = 0;
|
|
s_vpr_h(inst->sid, "%s: bitrate type: %d\n",
|
|
__func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_BITRATE_TYPE, &enable,
|
|
sizeof(enable));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
bitrate.bit_rate = inst->clk_data.bitrate;
|
|
bitrate.layer_id = MSM_VIDC_ALL_LAYER_ID;
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, bitrate.bit_rate);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE, &bitrate,
|
|
sizeof(bitrate));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_layer_bitrate(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0, i = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *layer = NULL;
|
|
struct v4l2_ctrl *max_layer = NULL;
|
|
struct v4l2_ctrl *layer_br_ratios[MAX_HIER_CODING_LAYER] = {NULL};
|
|
struct hfi_bitrate layer_br;
|
|
struct hfi_enable enable;
|
|
u32 bitrate;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
max_layer = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
layer = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
|
|
|
|
if (!max_layer->val || !layer->val) {
|
|
s_vpr_h(inst->sid,
|
|
"%s: Hier-P layer not set. Ignore layer bitrate\n",
|
|
__func__);
|
|
goto error;
|
|
}
|
|
|
|
if (max_layer->val < layer->val) {
|
|
s_vpr_h(inst->sid,
|
|
"%s: Hier-P layer greater than max isn't allowed\n",
|
|
__func__);
|
|
goto error;
|
|
}
|
|
|
|
layer_br_ratios[0] = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR);
|
|
layer_br_ratios[1] = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR);
|
|
layer_br_ratios[2] = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR);
|
|
layer_br_ratios[3] = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR);
|
|
layer_br_ratios[4] = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR);
|
|
layer_br_ratios[5] = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR);
|
|
|
|
/* Set layer bitrates only when highest layer br ratio is 100. */
|
|
if (layer_br_ratios[layer->val-1]->val != MAX_BIT_RATE_RATIO ||
|
|
layer_br_ratios[0]->val == 0) {
|
|
s_vpr_h(inst->sid, "%s: Improper layer bitrate ratio\n",
|
|
__func__);
|
|
goto error;
|
|
}
|
|
|
|
for (i = layer->val - 1; i > 0; --i) {
|
|
if (layer_br_ratios[i]->val == 0) {
|
|
s_vpr_h(inst->sid, "%s: Layer ratio must be non-zero\n",
|
|
__func__);
|
|
goto error;
|
|
}
|
|
layer_br_ratios[i]->val -= layer_br_ratios[i-1]->val;
|
|
}
|
|
|
|
enable.enable = 1;
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_BITRATE_TYPE, &enable,
|
|
sizeof(enable));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
goto error;
|
|
}
|
|
|
|
bitrate = inst->clk_data.bitrate;
|
|
for (i = 0; i < layer->val; ++i) {
|
|
layer_br.bit_rate =
|
|
bitrate * layer_br_ratios[i]->val / 100;
|
|
layer_br.layer_id = i;
|
|
s_vpr_h(inst->sid, "%s: Bitrate for Layer[%u]: [%u]\n",
|
|
__func__, layer_br.layer_id, layer_br.bit_rate);
|
|
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE, &layer_br,
|
|
sizeof(layer_br));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: set property failed for layer: %u\n",
|
|
__func__, layer_br.layer_id);
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
inst->layer_bitrate = true;
|
|
return rc;
|
|
|
|
error:
|
|
inst->layer_bitrate = false;
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_frame_qp(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *i_qp = NULL;
|
|
struct v4l2_ctrl *p_qp = NULL;
|
|
struct v4l2_ctrl *b_qp = NULL;
|
|
struct hfi_quantization qp;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
qp.layer_id = MSM_VIDC_ALL_LAYER_ID;
|
|
qp.enable = 0;
|
|
qp.enable = QP_ENABLE_I | QP_ENABLE_P | QP_ENABLE_B;
|
|
|
|
i_qp = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP);
|
|
p_qp = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP);
|
|
b_qp = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP);
|
|
|
|
/*
|
|
* When RC is ON:
|
|
* Enable QP types which have been set by client.
|
|
* When RC is OFF:
|
|
* I_QP value must be set by client.
|
|
* If other QP value is invalid, then, assign I_QP value to it.
|
|
*/
|
|
if (inst->rc_type != RATE_CONTROL_OFF) {
|
|
if (!(inst->client_set_ctrls & CLIENT_SET_I_QP))
|
|
qp.enable &= ~QP_ENABLE_I;
|
|
if (!(inst->client_set_ctrls & CLIENT_SET_P_QP))
|
|
qp.enable &= ~QP_ENABLE_P;
|
|
if (!(inst->client_set_ctrls & CLIENT_SET_B_QP))
|
|
qp.enable &= ~QP_ENABLE_B;
|
|
|
|
if (!qp.enable)
|
|
return 0;
|
|
} else {
|
|
if (!(inst->client_set_ctrls & CLIENT_SET_I_QP)) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: Client value is not valid\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
if (!(inst->client_set_ctrls & CLIENT_SET_P_QP))
|
|
p_qp->val = i_qp->val;
|
|
if (!(inst->client_set_ctrls & CLIENT_SET_B_QP))
|
|
b_qp->val = i_qp->val;
|
|
}
|
|
|
|
qp.qp_packed = i_qp->val | p_qp->val << 8 | b_qp->val << 16;
|
|
|
|
s_vpr_h(inst->sid, "%s: layers %#x frames %#x qp_packed %#x\n",
|
|
__func__, qp.layer_id, qp.enable, qp.qp_packed);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_FRAME_QP, &qp, sizeof(qp));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_qp_range(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_quantization_range qp_range;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (!(inst->client_set_ctrls & CLIENT_SET_MIN_QP) &&
|
|
!(inst->client_set_ctrls & CLIENT_SET_MAX_QP)) {
|
|
s_vpr_h(inst->sid,
|
|
"%s: Client didn't set QP range\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
qp_range.min_qp.layer_id = MSM_VIDC_ALL_LAYER_ID;
|
|
qp_range.max_qp.layer_id = MSM_VIDC_ALL_LAYER_ID;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP);
|
|
qp_range.min_qp.qp_packed = ctrl->val;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP);
|
|
qp_range.max_qp.qp_packed = ctrl->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: layers %#x qp_min %#x qp_max %#x\n",
|
|
__func__, qp_range.min_qp.layer_id,
|
|
qp_range.min_qp.qp_packed, qp_range.max_qp.qp_packed);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE, &qp_range,
|
|
sizeof(qp_range));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static void set_all_intra_preconditions(struct msm_vidc_inst *inst)
|
|
{
|
|
struct v4l2_ctrl *ctrl = NULL, *ctrl_t = NULL;
|
|
|
|
/* Disable multi slice */
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
|
|
if (ctrl->val) {
|
|
d_vpr_h("Disable multi slice for all intra\n");
|
|
update_ctrl(ctrl, V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
|
|
inst->sid);
|
|
}
|
|
|
|
/* Disable LTR */
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT);
|
|
if (ctrl->val) {
|
|
s_vpr_h(inst->sid, "Disable LTR for all intra\n");
|
|
update_ctrl(ctrl, 0, inst->sid);
|
|
}
|
|
|
|
/* Disable Layer encoding */
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
|
|
ctrl_t = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
if (ctrl->val || ctrl_t->val) {
|
|
s_vpr_h(inst->sid, "Disable layer encoding for all intra\n");
|
|
update_ctrl(ctrl, 0, inst->sid);
|
|
update_ctrl(ctrl_t, 0, inst->sid);
|
|
}
|
|
|
|
/* Disable IR */
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM);
|
|
ctrl_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB);
|
|
if (ctrl->val || ctrl_t->val) {
|
|
s_vpr_h(inst->sid, "Disable IR for all intra\n");
|
|
update_ctrl(ctrl, 0, inst->sid);
|
|
update_ctrl(ctrl_t, 0, inst->sid);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void set_heif_preconditions(struct msm_vidc_inst *inst)
|
|
{
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
|
|
/* Reset PFrames */
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE);
|
|
if (ctrl->val) {
|
|
d_vpr_h("Reset P-frame count for HEIF\n");
|
|
update_ctrl(ctrl, 0, inst->sid);
|
|
}
|
|
|
|
/* Reset BFrames */
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES);
|
|
if (ctrl->val) {
|
|
s_vpr_h(inst->sid, "Reset B-frame count for HEIF\n");
|
|
update_ctrl(ctrl, 0, inst->sid);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int msm_venc_set_frame_quality(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_heic_frame_quality frame_quality;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_COMPRESSION_QUALITY);
|
|
frame_quality.frame_quality = ctrl->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: frame quality: %d\n", __func__,
|
|
frame_quality.frame_quality);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY, &frame_quality,
|
|
sizeof(frame_quality));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set frame quality failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_image_grid(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_heic_grid_enable grid_enable;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_IMG_GRID_SIZE);
|
|
|
|
/* Need a change in HFI if we want to pass size */
|
|
if (!ctrl->val)
|
|
grid_enable.grid_enable = false;
|
|
else
|
|
grid_enable.grid_enable = true;
|
|
|
|
s_vpr_h(inst->sid, "%s: grid enable: %d\n", __func__,
|
|
grid_enable.grid_enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_HEIC_GRID_ENABLE, &grid_enable,
|
|
sizeof(grid_enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set grid enable failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_image_properties(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
|
|
if (!inst) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!is_image_session(inst) && !is_grid_session(inst))
|
|
return 0;
|
|
|
|
if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) {
|
|
d_vpr_e("%s: invalid rate control mode\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = msm_venc_set_frame_quality(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: set image property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
rc = msm_venc_set_image_grid(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: set image property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
set_all_intra_preconditions(inst);
|
|
set_heif_preconditions(inst);
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_entropy_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_h264_entropy_control entropy;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (get_v4l2_codec(inst) != V4L2_PIX_FMT_H264)
|
|
return 0;
|
|
|
|
entropy.entropy_mode = inst->entropy_mode;
|
|
entropy.cabac_model = HFI_H264_CABAC_MODEL_2;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, entropy.entropy_mode);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL, &entropy,
|
|
sizeof(entropy));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_slice_control_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct v4l2_ctrl *ctrl_t;
|
|
struct hfi_multi_slice_control multi_slice_control;
|
|
struct v4l2_format *f;
|
|
int temp = 0;
|
|
u32 mb_per_frame, fps, mbps, bitrate, max_slices;
|
|
u32 slice_val, slice_mode, max_avg_slicesize;
|
|
u32 rc_mode, output_width, output_height;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (codec != V4L2_PIX_FMT_HEVC && codec != V4L2_PIX_FMT_H264)
|
|
return 0;
|
|
|
|
slice_mode = HFI_MULTI_SLICE_OFF;
|
|
slice_val = 0;
|
|
|
|
bitrate = inst->clk_data.bitrate;
|
|
fps = inst->clk_data.frame_rate >> 16;
|
|
rc_mode = inst->rc_type;
|
|
if (fps > 60 || (!(rc_mode == RATE_CONTROL_OFF ||
|
|
rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR ||
|
|
rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))) {
|
|
goto set_and_exit;
|
|
}
|
|
|
|
f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
output_width = f->fmt.pix_mp.width;
|
|
output_height = f->fmt.pix_mp.height;
|
|
if ((codec == V4L2_PIX_FMT_HEVC) &&
|
|
(output_height < 128 || output_width < 384))
|
|
goto set_and_exit;
|
|
|
|
if ((codec == V4L2_PIX_FMT_H264) &&
|
|
(output_height < 128 || output_width < 192))
|
|
goto set_and_exit;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
|
|
if (ctrl->val == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
|
|
temp = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
|
|
slice_mode = HFI_MULTI_SLICE_BY_MB_COUNT;
|
|
} else if (ctrl->val == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
|
|
temp = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
|
|
slice_mode = HFI_MULTI_SLICE_BY_BYTE_COUNT;
|
|
} else {
|
|
goto set_and_exit;
|
|
}
|
|
|
|
ctrl_t = get_ctrl(inst, temp);
|
|
slice_val = ctrl_t->val;
|
|
|
|
/* Update Slice Config */
|
|
mb_per_frame = NUM_MBS_PER_FRAME(output_height, output_width);
|
|
mbps = NUM_MBS_PER_SEC(output_height, output_width, fps);
|
|
|
|
if (slice_mode == HFI_MULTI_SLICE_BY_MB_COUNT) {
|
|
if (output_width <= 4096 || output_height <= 4096 ||
|
|
mb_per_frame <= NUM_MBS_PER_FRAME(4096, 2160) ||
|
|
mbps <= NUM_MBS_PER_SEC(4096, 2160, 60)) {
|
|
max_slices = inst->capability.cap[CAP_SLICE_MB].max ?
|
|
inst->capability.cap[CAP_SLICE_MB].max : 1;
|
|
slice_val = max(slice_val, mb_per_frame / max_slices);
|
|
}
|
|
} else {
|
|
if (output_width <= 1920 || output_height <= 1920 ||
|
|
mb_per_frame <= NUM_MBS_PER_FRAME(1088, 1920) ||
|
|
mbps <= NUM_MBS_PER_SEC(1088, 1920, 60)) {
|
|
max_slices = inst->capability.cap[CAP_SLICE_BYTE].max ?
|
|
inst->capability.cap[CAP_SLICE_BYTE].max : 1;
|
|
if (rc_mode != RATE_CONTROL_OFF) {
|
|
max_avg_slicesize =
|
|
((bitrate / fps) / 8) / max_slices;
|
|
slice_val = max(slice_val, max_avg_slicesize);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (slice_mode == HFI_MULTI_SLICE_OFF) {
|
|
update_ctrl(ctrl, V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
|
|
inst->sid);
|
|
update_ctrl(ctrl_t, 0, inst->sid);
|
|
}
|
|
|
|
set_and_exit:
|
|
multi_slice_control.multi_slice = slice_mode;
|
|
multi_slice_control.slice_size = slice_val;
|
|
|
|
hdev = inst->core->device;
|
|
s_vpr_h(inst->sid, "%s: %d %d\n", __func__,
|
|
multi_slice_control.multi_slice,
|
|
multi_slice_control.slice_size);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_CONTROL,
|
|
&multi_slice_control, sizeof(multi_slice_control));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_intra_refresh_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
struct hfi_intra_refresh intra_refresh;
|
|
struct v4l2_format *f;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (!(inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR ||
|
|
inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))
|
|
return 0;
|
|
|
|
/* Firmware supports only random mode */
|
|
intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM);
|
|
intra_refresh.mbs = 0;
|
|
f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
if (ctrl->val) {
|
|
u32 num_mbs_per_frame = 0;
|
|
u32 width = f->fmt.pix_mp.width;
|
|
u32 height = f->fmt.pix_mp.height;
|
|
|
|
num_mbs_per_frame = NUM_MBS_PER_FRAME(height, width);
|
|
intra_refresh.mbs = num_mbs_per_frame / ctrl->val;
|
|
if (num_mbs_per_frame % ctrl->val) {
|
|
intra_refresh.mbs++;
|
|
}
|
|
} else {
|
|
ctrl = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB);
|
|
intra_refresh.mbs = ctrl->val;
|
|
}
|
|
if (!intra_refresh.mbs) {
|
|
intra_refresh.mode = HFI_INTRA_REFRESH_NONE;
|
|
intra_refresh.mbs = 0;
|
|
}
|
|
|
|
s_vpr_h(inst->sid, "%s: %d %d\n", __func__,
|
|
intra_refresh.mode, intra_refresh.mbs);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH, &intra_refresh,
|
|
sizeof(intra_refresh));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_chroma_qp_offset(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *chr;
|
|
struct v4l2_ctrl *ctrl_cs;
|
|
struct hfi_chroma_qp_offset chroma_qp;
|
|
struct v4l2_format *f;
|
|
u32 codec, width, height, mbpf;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
chr = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET);
|
|
if (chr->val == INT_MAX || (chr->val != 0 && chr->val != -12))
|
|
return 0;
|
|
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
width = f->fmt.pix_mp.width;
|
|
height = f->fmt.pix_mp.height;
|
|
mbpf = NUM_MBS_PER_FRAME(width, height);
|
|
ctrl_cs = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
|
|
codec = get_v4l2_codec(inst);
|
|
|
|
/**
|
|
* Set chroma qp offset to HEVC & VBR_CFR rc
|
|
* 10 bit: only BT2020
|
|
* 8 bit: only mbpf >= num_mbs(7680, 3840)
|
|
*/
|
|
if (codec != V4L2_PIX_FMT_HEVC ||
|
|
inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
|
|
return 0;
|
|
|
|
if ((inst->bit_depth == MSM_VIDC_BIT_DEPTH_10 &&
|
|
ctrl_cs->val != MSM_VIDC_BT2020) ||
|
|
(inst->bit_depth == MSM_VIDC_BIT_DEPTH_8 &&
|
|
mbpf < NUM_MBS_PER_FRAME(7680, 3840)))
|
|
return 0;
|
|
|
|
/**
|
|
* client sets one chroma offset only in range [-12, 0]
|
|
* firmware expects chroma cb offset and cr offset in
|
|
* range [0, 12], firmware subtracts 12 from driver set values.
|
|
*/
|
|
chroma_qp.chroma_offset = (chr->val + 12) << 16 | (chr->val + 12);
|
|
s_vpr_h(inst->sid, "%s: %x\n", __func__, chroma_qp.chroma_offset);
|
|
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_HEVC_PPS_CB_CR_OFFSET, &chroma_qp,
|
|
sizeof(chroma_qp));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_bitrate_savings_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *cac = NULL;
|
|
struct v4l2_ctrl *profile = NULL;
|
|
struct hfi_enable enable;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
enable.enable = 0;
|
|
if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
|
|
s_vpr_h(inst->sid,
|
|
"Disable bitrate savings for non-VBR_CFR\n");
|
|
goto setprop;
|
|
}
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
profile = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_PROFILE);
|
|
cac = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VENC_BITRATE_SAVINGS);
|
|
|
|
if (codec == V4L2_PIX_FMT_HEVC &&
|
|
profile->val == V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10)
|
|
enable.enable = !!(cac->val & V4L2_MPEG_VIDC_VIDEO_BRS_ENABLE_10BIT);
|
|
else
|
|
enable.enable = !!(cac->val & V4L2_MPEG_VIDC_VIDEO_BRS_ENABLE_8BIT);
|
|
|
|
setprop:
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_BITRATE_SAVINGS, &enable,
|
|
sizeof(enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
else
|
|
rc = msm_venc_set_bitrate_boost_margin(inst, enable.enable);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_bitrate_boost_margin(struct msm_vidc_inst *inst, u32 enable)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
struct hfi_bitrate_boost_margin boost_margin;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (!enable) {
|
|
boost_margin.margin = 0;
|
|
goto setprop;
|
|
}
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VENC_BITRATE_BOOST);
|
|
/* Mapped value to 0, 25 or 50*/
|
|
if (ctrl->val >= 50)
|
|
boost_margin.margin = 50;
|
|
else
|
|
boost_margin.margin = (u32)(ctrl->val/25) * 25;
|
|
|
|
setprop:
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, boost_margin.margin);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_BITRATE_BOOST, &boost_margin,
|
|
sizeof(boost_margin));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
int msm_venc_set_loop_filter_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct v4l2_ctrl *ctrl_a;
|
|
struct v4l2_ctrl *ctrl_b;
|
|
struct hfi_h264_db_control h264_db_control;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE);
|
|
ctrl_a = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA);
|
|
ctrl_b = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA);
|
|
h264_db_control.mode = msm_comm_v4l2_to_hfi(
|
|
V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
|
|
ctrl->val, inst->sid);
|
|
h264_db_control.slice_alpha_offset = ctrl_a->val;
|
|
h264_db_control.slice_beta_offset = ctrl_b->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d %d %d\n", __func__,
|
|
h264_db_control.mode, h264_db_control.slice_alpha_offset,
|
|
h264_db_control.slice_beta_offset);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL, &h264_db_control,
|
|
sizeof(h264_db_control));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_sequence_header_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_enable enable;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (!(codec == V4L2_PIX_FMT_H264 || codec == V4L2_PIX_FMT_HEVC))
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR);
|
|
if (ctrl->val)
|
|
enable.enable = true;
|
|
else
|
|
enable.enable = false;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER, &enable,
|
|
sizeof(enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_au_delimiter_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_enable enable;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (!(codec == V4L2_PIX_FMT_H264 || codec == V4L2_PIX_FMT_HEVC))
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_AU_DELIMITER);
|
|
enable.enable = !!ctrl->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_GENERATE_AUDNAL, &enable,
|
|
sizeof(enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_enable_hybrid_hp(struct msm_vidc_inst *inst)
|
|
{
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
struct v4l2_ctrl *layer = NULL;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (get_v4l2_codec(inst) != V4L2_PIX_FMT_H264)
|
|
return 0;
|
|
|
|
if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT);
|
|
if (ctrl->val)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
layer = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
|
|
if (ctrl->val == 0 || ctrl->val != layer->val)
|
|
return 0;
|
|
|
|
/*
|
|
* Hybrid HP is enabled only for H264 when
|
|
* LTR and B-frame are both disabled,
|
|
* Layer encoding has higher priority over B-frame
|
|
* Hence, no need to check for B-frame
|
|
* Rate control type is VBR and
|
|
* Max layer equals layer count.
|
|
*/
|
|
|
|
inst->hybrid_hp = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int msm_venc_set_base_layer_priority_id(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
struct v4l2_ctrl *max_layer = NULL;
|
|
u32 baselayerid;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
max_layer = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
if (max_layer->val <= 0) {
|
|
s_vpr_h(inst->sid, "%s: Layer id can only be set with Hier-P\n",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_BASELAYER_ID);
|
|
baselayerid = ctrl->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, baselayerid);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_BASELAYER_PRIORITYID, &baselayerid,
|
|
sizeof(baselayerid));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_hb_max_layer(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *frame_t = NULL;
|
|
struct v4l2_ctrl *max_layer = NULL;
|
|
u32 hb_layer = 0;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (codec != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
max_layer = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
|
|
if (max_layer->val < 2 ||
|
|
frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) {
|
|
s_vpr_h(inst->sid,
|
|
"%s: Hier-B not requested for this session\n",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
hb_layer = max_layer->val - 1;
|
|
|
|
s_vpr_h(inst->sid, "%s: Hier-B max layer: %d\n",
|
|
__func__, hb_layer);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_HIER_B_MAX_NUM_ENH_LAYER,
|
|
&hb_layer, sizeof(hb_layer));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_hp_max_layer(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *frame_t = NULL;
|
|
struct v4l2_ctrl *max_layer = NULL;
|
|
u32 hp_layer = 0;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
max_layer = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
|
|
if (max_layer->val < 2 ||
|
|
frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) {
|
|
s_vpr_h(inst->sid,
|
|
"%s: Hier-P not requested for this session\n",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
|
|
rc = msm_venc_enable_hybrid_hp(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: get hybrid hier-P decision failed\n",
|
|
__func__);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* We send enhancement layer count to FW,
|
|
* hence, input 0/1 indicates absence of layer encoding.
|
|
*/
|
|
if (max_layer->val)
|
|
hp_layer = max_layer->val - 1;
|
|
|
|
if (inst->hybrid_hp) {
|
|
s_vpr_h(inst->sid, "%s: Hybrid hier-P layer: %d\n",
|
|
__func__, hp_layer);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_HIER_P_HYBRID_MODE,
|
|
&hp_layer, sizeof(hp_layer));
|
|
} else {
|
|
s_vpr_h(inst->sid, "%s: Hier-P max layer: %d\n",
|
|
__func__, hp_layer);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER,
|
|
&hp_layer, sizeof(hp_layer));
|
|
}
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_hp_layer(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *frame_t = NULL;
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
struct v4l2_ctrl *max_layer = NULL;
|
|
u32 hp_layer = 0;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
frame_t = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE);
|
|
if (frame_t->val != V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P) {
|
|
s_vpr_h(inst->sid,
|
|
"%s: Hier-P layer can be set for P type frame only\n",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
if (inst->hybrid_hp) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: Setting layer isn't allowed with hybrid hp\n",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
|
|
max_layer = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_HEVC_MAX_HIER_CODING_LAYER);
|
|
ctrl = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER);
|
|
s_vpr_h(inst->sid, "%s: heir_layer: %d, max_hier_layer: %d\n",
|
|
__func__, ctrl->val, max_layer->val);
|
|
if (max_layer->val < ctrl->val) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: HP layer count greater than max isn't allowed\n",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* We send enhancement layer count to FW,
|
|
* hence, input 0/1 indicates absence of layer encoding.
|
|
*/
|
|
if (ctrl->val)
|
|
hp_layer = ctrl->val - 1;
|
|
|
|
s_vpr_h(inst->sid, "%s: Hier-P enhancement layer: %d\n",
|
|
__func__, hp_layer);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER,
|
|
&hp_layer, sizeof(hp_layer));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_video_signal_info(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl_cs;
|
|
struct v4l2_ctrl *ctrl_fr;
|
|
struct v4l2_ctrl *ctrl_tr;
|
|
struct v4l2_ctrl *ctrl_mc;
|
|
struct hfi_video_signal_metadata signal_info;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (!(codec == V4L2_PIX_FMT_H264 || codec == V4L2_PIX_FMT_HEVC))
|
|
return 0;
|
|
|
|
ctrl_cs = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
|
|
ctrl_fr = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_FULL_RANGE);
|
|
ctrl_tr = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_TRANSFER_CHARS);
|
|
ctrl_mc = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS);
|
|
|
|
memset(&signal_info, 0, sizeof(struct hfi_video_signal_metadata));
|
|
if (inst->full_range == COLOR_RANGE_UNSPECIFIED &&
|
|
ctrl_cs->val == MSM_VIDC_RESERVED_1)
|
|
signal_info.enable = false;
|
|
else
|
|
signal_info.enable = true;
|
|
|
|
if (signal_info.enable) {
|
|
signal_info.video_format = MSM_VIDC_NTSC;
|
|
signal_info.video_full_range = ctrl_fr->val;
|
|
if (ctrl_cs->val != MSM_VIDC_RESERVED_1) {
|
|
signal_info.color_description = 1;
|
|
signal_info.color_primaries = ctrl_cs->val;
|
|
signal_info.transfer_characteristics = ctrl_tr->val;
|
|
signal_info.matrix_coeffs = ctrl_mc->val;
|
|
}
|
|
}
|
|
|
|
s_vpr_h(inst->sid, "%s: %d %d %d %d\n", __func__,
|
|
signal_info.color_primaries, signal_info.video_full_range,
|
|
signal_info.transfer_characteristics,
|
|
signal_info.matrix_coeffs);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_VIDEO_SIGNAL_INFO, &signal_info,
|
|
sizeof(signal_info));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_rotation(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct v4l2_ctrl *rotation = NULL;
|
|
struct hfi_device *hdev;
|
|
struct hfi_vpe_rotation_type vpe_rotation;
|
|
|
|
hdev = inst->core->device;
|
|
rotation = get_ctrl(inst, V4L2_CID_ROTATE);
|
|
|
|
vpe_rotation.rotation = HFI_ROTATE_NONE;
|
|
if (rotation->val == 90)
|
|
vpe_rotation.rotation = HFI_ROTATE_90;
|
|
else if (rotation->val == 180)
|
|
vpe_rotation.rotation = HFI_ROTATE_180;
|
|
else if (rotation->val == 270)
|
|
vpe_rotation.rotation = HFI_ROTATE_270;
|
|
|
|
vpe_rotation.flip = v4l2_to_hfi_flip(inst);
|
|
|
|
s_vpr_h(inst->sid, "Set rotation = %d, flip = %d\n",
|
|
vpe_rotation.rotation, vpe_rotation.flip);
|
|
rc = call_hfi_op(hdev, session_set_property,
|
|
(void *)inst->session,
|
|
HFI_PROPERTY_PARAM_VPE_ROTATION,
|
|
&vpe_rotation, sizeof(vpe_rotation));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "Set rotation/flip failed\n");
|
|
return rc;
|
|
}
|
|
|
|
/* Mark static rotation/flip set */
|
|
inst->static_rotation_flip_enabled = false;
|
|
if ((vpe_rotation.rotation != HFI_ROTATE_NONE ||
|
|
vpe_rotation.flip != HFI_FLIP_NONE) &&
|
|
inst->state < MSM_VIDC_START_DONE)
|
|
inst->static_rotation_flip_enabled = true;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_check_dynamic_flip_constraints(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct v4l2_ctrl *blur = NULL;
|
|
struct v4l2_format *f = NULL;
|
|
bool scalar_enable = false;
|
|
bool blur_enable = false;
|
|
u32 input_height, input_width;
|
|
|
|
/* Dynamic flip is not allowed with scalar when static
|
|
* rotation/flip is disabled
|
|
*/
|
|
scalar_enable = vidc_scalar_enabled(inst);
|
|
|
|
/* Check blur configs
|
|
* blur value = 0 -> enable auto blur
|
|
* blur value = 2 or input resolution -> disable all blur
|
|
* For other values -> enable external blur
|
|
* Dynamic flip is not allowed with external blur enabled
|
|
*/
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
input_height = f->fmt.pix_mp.height;
|
|
input_width = f->fmt.pix_mp.width;
|
|
|
|
blur = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_BLUR_DIMENSIONS);
|
|
if (blur->val != 0 && blur->val != 2 &&
|
|
((blur->val & 0xFFFF) != input_height ||
|
|
(blur->val & 0x7FFF0000) >> 16 != input_width))
|
|
blur_enable = true;
|
|
s_vpr_h(inst->sid, "Blur = %u, height = %u, width = %u\n",
|
|
blur->val, input_height, input_width);
|
|
if (blur_enable) {
|
|
/* Reject dynamic flip with external blur enabled */
|
|
s_vpr_e(inst->sid,
|
|
"Unsupported dynamic flip with external blur\n");
|
|
rc = -EINVAL;
|
|
} else if (scalar_enable && !inst->static_rotation_flip_enabled) {
|
|
/* Reject dynamic flip with scalar enabled */
|
|
s_vpr_e(inst->sid, "Unsupported dynamic flip with scalar\n");
|
|
rc = -EINVAL;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_dynamic_flip(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
u32 dynamic_flip;
|
|
|
|
hdev = inst->core->device;
|
|
|
|
rc = msm_venc_check_dynamic_flip_constraints(inst);
|
|
if (rc) {
|
|
d_vpr_e("%s: Dynamic flip unsupported\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
/* Require IDR frame first */
|
|
s_vpr_h(inst->sid, "Set dynamic IDR frame\n");
|
|
rc = msm_venc_set_request_keyframe(inst);
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "%s: Dynamic IDR failed\n", __func__);
|
|
return rc;
|
|
}
|
|
|
|
dynamic_flip = v4l2_to_hfi_flip(inst);
|
|
s_vpr_h(inst->sid, "Dynamic flip = %d\n", dynamic_flip);
|
|
rc = call_hfi_op(hdev, session_set_property,
|
|
(void *)inst->session,
|
|
HFI_PROPERTY_CONFIG_VPE_FLIP,
|
|
&dynamic_flip, sizeof(dynamic_flip));
|
|
if (rc) {
|
|
s_vpr_e(inst->sid, "Set dynamic flip failed\n");
|
|
return rc;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_video_csc(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct v4l2_ctrl *ctrl_cs;
|
|
struct v4l2_ctrl *ctrl_cm;
|
|
u32 color_primaries, custom_matrix;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (get_v4l2_codec(inst) != V4L2_PIX_FMT_H264 &&
|
|
get_v4l2_codec(inst) != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC);
|
|
if (ctrl->val == V4L2_MPEG_MSM_VIDC_DISABLE)
|
|
return 0;
|
|
|
|
ctrl_cs = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_COLOR_SPACE);
|
|
ctrl_cm = get_ctrl(inst,
|
|
V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_CUSTOM_MATRIX);
|
|
|
|
color_primaries = ctrl_cs->val;
|
|
custom_matrix = ctrl_cm->val;
|
|
rc = msm_venc_set_csc(inst, color_primaries, custom_matrix);
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: msm_venc_set_csc failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_8x8_transform(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
struct hfi_enable enable;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (get_v4l2_codec(inst) != V4L2_PIX_FMT_H264) {
|
|
s_vpr_h(inst->sid, "%s: skip as codec is not H264\n",
|
|
__func__);
|
|
return 0;
|
|
}
|
|
|
|
if (inst->profile != HFI_H264_PROFILE_HIGH &&
|
|
inst->profile != HFI_H264_PROFILE_CONSTRAINED_HIGH) {
|
|
s_vpr_h(inst->sid, "%s: skip due to %#x\n",
|
|
__func__, inst->profile);
|
|
return 0;
|
|
}
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM);
|
|
enable.enable = !!ctrl->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, enable.enable);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_H264_8X8_TRANSFORM, &enable,
|
|
sizeof(enable));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_vui_timing_info(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_vui_timing_info timing_info;
|
|
bool cfr;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_VUI_TIMING_INFO);
|
|
if (ctrl->val == V4L2_MPEG_MSM_VIDC_DISABLE)
|
|
return 0;
|
|
|
|
switch (inst->rc_type) {
|
|
case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
|
|
case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
|
|
case V4L2_MPEG_VIDEO_BITRATE_MODE_MBR:
|
|
cfr = true;
|
|
break;
|
|
default:
|
|
cfr = false;
|
|
break;
|
|
}
|
|
|
|
timing_info.enable = 1;
|
|
timing_info.fixed_frame_rate = cfr;
|
|
timing_info.time_scale = NSEC_PER_SEC;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d %d\n", __func__, timing_info.enable,
|
|
timing_info.fixed_frame_rate);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_VUI_TIMING_INFO, &timing_info,
|
|
sizeof(timing_info));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_nal_stream_format(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_nal_stream_format_select stream_format;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (codec != V4L2_PIX_FMT_H264 && codec != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD);
|
|
stream_format.nal_stream_format_select = BIT(ctrl->val);
|
|
|
|
/*
|
|
* Secure encode session supports 0x00000001 satrtcode based
|
|
* encoding only
|
|
*/
|
|
if (is_secure_session(inst) &&
|
|
ctrl->val != V4L2_MPEG_VIDEO_HEVC_SIZE_0) {
|
|
s_vpr_e(inst->sid,
|
|
"%s: Invalid stream format setting for secure session\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (ctrl->val) {
|
|
case V4L2_MPEG_VIDEO_HEVC_SIZE_0:
|
|
stream_format.nal_stream_format_select =
|
|
HFI_NAL_FORMAT_STARTCODES;
|
|
break;
|
|
case V4L2_MPEG_VIDEO_HEVC_SIZE_4:
|
|
stream_format.nal_stream_format_select =
|
|
HFI_NAL_FORMAT_FOUR_BYTE_LENGTH;
|
|
break;
|
|
default:
|
|
s_vpr_e(inst->sid,
|
|
"%s: Invalid stream format setting. Setting default\n",
|
|
__func__);
|
|
stream_format.nal_stream_format_select =
|
|
HFI_NAL_FORMAT_STARTCODES;
|
|
break;
|
|
}
|
|
|
|
s_vpr_h(inst->sid, "%s: %#x\n", __func__,
|
|
stream_format.nal_stream_format_select);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT, &stream_format,
|
|
sizeof(stream_format));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_ltr_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
bool is_ltr = true;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_ltr_mode ltr;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT);
|
|
if (!ctrl->val)
|
|
return 0;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (!(codec == V4L2_PIX_FMT_HEVC || codec == V4L2_PIX_FMT_H264)) {
|
|
is_ltr = false;
|
|
goto disable_ltr;
|
|
}
|
|
|
|
if (!(inst->rc_type == RATE_CONTROL_OFF ||
|
|
inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR ||
|
|
inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR)) {
|
|
is_ltr = false;
|
|
goto disable_ltr;
|
|
}
|
|
|
|
if (ctrl->val > inst->capability.cap[CAP_LTR_COUNT].max) {
|
|
s_vpr_e(inst->sid, "%s: invalid ltr count %d, max %d\n",
|
|
__func__, ctrl->val,
|
|
inst->capability.cap[CAP_LTR_COUNT].max);
|
|
return -EINVAL;
|
|
}
|
|
ltr.ltr_count = ctrl->val;
|
|
ltr.ltr_mode = HFI_LTR_MODE_MANUAL;
|
|
ltr.trust_mode = 1;
|
|
s_vpr_h(inst->sid, "%s: %d %d\n", __func__,
|
|
ltr.ltr_mode, ltr.ltr_count);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_LTRMODE, <r, sizeof(ltr));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
disable_ltr:
|
|
/*
|
|
* Forcefully setting LTR count to zero when
|
|
* client sets unsupported codec/rate control.
|
|
*/
|
|
if (!is_ltr) {
|
|
update_ctrl(ctrl, 0, inst->sid);
|
|
s_vpr_h(inst->sid, "LTR is forcefully disabled!\n");
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_ltr_useframe(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_ltr_use use_ltr;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT);
|
|
if (!ctrl->val)
|
|
return 0;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (!(codec == V4L2_PIX_FMT_HEVC || codec == V4L2_PIX_FMT_H264))
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME);
|
|
use_ltr.ref_ltr = ctrl->val;
|
|
use_ltr.use_constrnt = true;
|
|
use_ltr.frames = 0;
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, use_ltr.ref_ltr);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_USELTRFRAME, &use_ltr,
|
|
sizeof(use_ltr));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_ltr_markframe(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_ltr_mark mark_ltr;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT);
|
|
if (!ctrl->val)
|
|
return 0;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (!(codec == V4L2_PIX_FMT_HEVC || codec == V4L2_PIX_FMT_H264))
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME);
|
|
mark_ltr.mark_frame = ctrl->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d\n", __func__, mark_ltr.mark_frame);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_MARKLTRFRAME, &mark_ltr,
|
|
sizeof(mark_ltr));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_dyn_qp(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_quantization qp;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (inst->rc_type != RATE_CONTROL_OFF) {
|
|
s_vpr_e(inst->sid, "%s: Dyn qp is set only when RC is OFF\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
qp.qp_packed = ctrl->val | ctrl->val << 8 | ctrl->val << 16;
|
|
qp.enable = QP_ENABLE_I | QP_ENABLE_P | QP_ENABLE_B;
|
|
qp.layer_id = MSM_VIDC_ALL_LAYER_ID;
|
|
|
|
s_vpr_h(inst->sid, "%s: %#x\n", __func__,
|
|
ctrl->val);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_FRAME_QP, &qp, sizeof(qp));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_aspect_ratio(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl;
|
|
struct hfi_aspect_ratio sar;
|
|
u32 codec;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (!(codec == V4L2_PIX_FMT_H264 || codec == V4L2_PIX_FMT_HEVC))
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH);
|
|
if (!ctrl->val)
|
|
return 0;
|
|
sar.aspect_width = ctrl->val;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT);
|
|
if (!ctrl->val)
|
|
return 0;
|
|
sar.aspect_height = ctrl->val;
|
|
|
|
s_vpr_h(inst->sid, "%s: %d %d\n", __func__,
|
|
sar.aspect_width, sar.aspect_height);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_ASPECT_RATIO, &sar, sizeof(sar));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_blur_resolution(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
struct hfi_frame_size frame_sz;
|
|
struct v4l2_format *f;
|
|
bool disable_blur = false;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_BLUR_DIMENSIONS);
|
|
|
|
frame_sz.buffer_type = HFI_BUFFER_INPUT;
|
|
frame_sz.height = ctrl->val & 0xFFFF;
|
|
frame_sz.width = (ctrl->val & 0x7FFF0000) >> 16;
|
|
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
|
|
/*
|
|
* 0x0 is default value, internal blur enabled, external blur disabled
|
|
* 0x1 means dynamic external blur, blur resolution will be set
|
|
* after start, internal blur disabled
|
|
* 0x2 means disable both internal and external blur
|
|
*/
|
|
if (ctrl->val == MSM_VIDC_BLUR_DISABLE) {
|
|
s_vpr_h(inst->sid,
|
|
"Disable internal/external blur\n");
|
|
disable_blur = true;
|
|
} else if (ctrl->val == MSM_VIDC_BLUR_INTERNAL) {
|
|
if (check_blur_restrictions(inst)) {
|
|
s_vpr_h(inst->sid,
|
|
"Internal blur restrictions not met. Disabling blur..\n");
|
|
disable_blur = true;
|
|
}
|
|
} else {
|
|
if (check_blur_restrictions(inst)) {
|
|
s_vpr_e(inst->sid,
|
|
"External blur is unsupported with rotation/flip/scalar\n");
|
|
disable_blur = true;
|
|
} else if (frame_sz.width > f->fmt.pix_mp.width ||
|
|
frame_sz.height > f->fmt.pix_mp.height) {
|
|
s_vpr_e(inst->sid,
|
|
"external blur wxh[%ux%u] exceeds input wxh[%ux%u]\n",
|
|
frame_sz.width, frame_sz.height,
|
|
f->fmt.pix_mp.width, f->fmt.pix_mp.height);
|
|
disable_blur = true;
|
|
}
|
|
if (inst->state < MSM_VIDC_START_DONE && disable_blur)
|
|
inst->external_blur = false;
|
|
}
|
|
|
|
if (disable_blur) {
|
|
/*
|
|
* Use original input width/height (before VPSS) to inform FW
|
|
* to disable all blur.
|
|
*/
|
|
frame_sz.width = f->fmt.pix_mp.width;
|
|
frame_sz.height = f->fmt.pix_mp.height;
|
|
}
|
|
|
|
s_vpr_h(inst->sid, "%s: type %u, height %u, width %u\n", __func__,
|
|
frame_sz.buffer_type, frame_sz.height, frame_sz.width);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_CONFIG_VENC_BLUR_FRAME_SIZE, &frame_sz,
|
|
sizeof(frame_sz));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_hdr_info(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct v4l2_ctrl *profile = NULL;
|
|
struct hfi_device *hdev;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
hdev = inst->core->device;
|
|
|
|
if (get_v4l2_codec(inst) != V4L2_PIX_FMT_HEVC)
|
|
return 0;
|
|
|
|
profile = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_PROFILE);
|
|
if (profile->val != V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10)
|
|
return 0;
|
|
|
|
/* No conversion to HFI needed as both structures are same */
|
|
s_vpr_h(inst->sid, "%s: setting hdr info\n", __func__);
|
|
rc = call_hfi_op(hdev, session_set_property, inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_HDR10_PQ_SEI, &inst->hdr10_sei_params,
|
|
sizeof(inst->hdr10_sei_params));
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: set property failed\n", __func__);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_extradata(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
u32 codec;
|
|
|
|
codec = get_v4l2_codec(inst);
|
|
if (inst->prop.extradata_ctrls == EXTRADATA_NONE) {
|
|
// Disable all Extradata
|
|
msm_comm_set_extradata(inst,
|
|
HFI_PROPERTY_PARAM_VENC_LTR_INFO, 0x0);
|
|
msm_comm_set_extradata(inst,
|
|
HFI_PROPERTY_PARAM_VENC_ROI_QP_EXTRADATA, 0x0);
|
|
if (codec == V4L2_PIX_FMT_HEVC) {
|
|
msm_comm_set_extradata(inst,
|
|
HFI_PROPERTY_PARAM_VENC_HDR10PLUS_METADATA_EXTRADATA,
|
|
0x0);
|
|
}
|
|
}
|
|
|
|
if (inst->prop.extradata_ctrls & EXTRADATA_ADVANCED)
|
|
// Enable Advanced Extradata - LTR Info
|
|
msm_comm_set_extradata(inst,
|
|
HFI_PROPERTY_PARAM_VENC_LTR_INFO, 0x1);
|
|
|
|
if (inst->prop.extradata_ctrls & EXTRADATA_ENC_INPUT_ROI)
|
|
// Enable ROIQP Extradata
|
|
msm_comm_set_extradata(inst,
|
|
HFI_PROPERTY_PARAM_VENC_ROI_QP_EXTRADATA, 0x1);
|
|
|
|
if (inst->prop.extradata_ctrls & EXTRADATA_ENC_INPUT_HDR10PLUS) {
|
|
// Enable HDR10+ Extradata
|
|
if (codec == V4L2_PIX_FMT_HEVC) {
|
|
msm_comm_set_extradata(inst,
|
|
HFI_PROPERTY_PARAM_VENC_HDR10PLUS_METADATA_EXTRADATA,
|
|
0x1);
|
|
}
|
|
}
|
|
|
|
if(!msm_vidc_cvp_usage)
|
|
inst->prop.extradata_ctrls &= ~EXTRADATA_ENC_INPUT_CVP;
|
|
|
|
/* CVP extradata is common between user space and external CVP kernel to kernel.
|
|
Hence, skipping here and will be set after msm_vidc_prepare_preprocess in start_streaming*/
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_set_lossless(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct hfi_device *hdev;
|
|
struct hfi_enable enable;
|
|
|
|
hdev = inst->core->device;
|
|
|
|
if (inst->rc_type != RATE_CONTROL_LOSSLESS)
|
|
return 0;
|
|
|
|
s_vpr_h(inst->sid, "%s: enable lossless encoding\n", __func__);
|
|
enable.enable = 1;
|
|
rc = call_hfi_op(hdev, session_set_property,
|
|
inst->session,
|
|
HFI_PROPERTY_PARAM_VENC_LOSSLESS_ENCODING,
|
|
&enable, sizeof(enable));
|
|
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "Failed to set lossless mode\n");
|
|
|
|
return rc;
|
|
}
|
|
int msm_venc_set_cvp_skipratio(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
struct v4l2_ctrl *capture_rate_ctrl;
|
|
struct v4l2_ctrl *cvp_rate_ctrl;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!is_cvp_supported(inst)) {
|
|
s_vpr_h(inst->sid, "%s cvp is not supported", __func__);
|
|
return rc;
|
|
}
|
|
|
|
if (!msm_vidc_cvp_usage)
|
|
return 0;
|
|
|
|
capture_rate_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_CAPTURE_FRAME_RATE);
|
|
cvp_rate_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_CVP_FRAME_RATE);
|
|
|
|
rc = msm_comm_set_cvp_skip_ratio(inst,
|
|
capture_rate_ctrl->val, cvp_rate_ctrl->val);
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "Failed to set cvp skip ratio\n");
|
|
|
|
return rc;
|
|
}
|
|
|
|
int msm_venc_update_entropy_mode(struct msm_vidc_inst *inst)
|
|
{
|
|
if (!inst) {
|
|
d_vpr_e("%s: invalid params\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (get_v4l2_codec(inst) == V4L2_PIX_FMT_H264) {
|
|
if ((inst->profile == HFI_H264_PROFILE_BASELINE ||
|
|
inst->profile == HFI_H264_PROFILE_CONSTRAINED_BASE)
|
|
&& inst->entropy_mode == HFI_H264_ENTROPY_CABAC) {
|
|
inst->entropy_mode = HFI_H264_ENTROPY_CAVLC;
|
|
s_vpr_h(inst->sid,
|
|
"%s: profile %d entropy %d\n",
|
|
__func__, inst->profile,
|
|
inst->entropy_mode);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int handle_all_intra_restrictions(struct msm_vidc_inst *inst)
|
|
{
|
|
struct v4l2_ctrl *ctrl = NULL;
|
|
u32 n_fps, fps_max;
|
|
struct msm_vidc_capability *capability;
|
|
struct v4l2_format *f;
|
|
enum hal_video_codec codec;
|
|
struct hfi_intra_period intra_period;
|
|
|
|
if (!inst || !inst->core) {
|
|
d_vpr_e("%s: invalid params %pK\n", __func__, inst);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
|
|
return 0;
|
|
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_GOP_SIZE);
|
|
intra_period.pframes = ctrl->val;
|
|
ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_B_FRAMES);
|
|
intra_period.bframes = ctrl->val;
|
|
|
|
if (!intra_period.pframes && !intra_period.bframes)
|
|
inst->all_intra = true;
|
|
else
|
|
return 0;
|
|
|
|
s_vpr_h(inst->sid, "All Intra(IDRs) Encoding\n");
|
|
/* check codec and profile */
|
|
f = &inst->fmts[OUTPUT_PORT].v4l2_fmt;
|
|
codec = get_hal_codec(f->fmt.pix_mp.pixelformat, inst->sid);
|
|
if (codec != HAL_VIDEO_CODEC_HEVC && codec != HAL_VIDEO_CODEC_H264) {
|
|
s_vpr_e(inst->sid, "Unsupported codec for all intra\n");
|
|
return -ENOTSUPP;
|
|
}
|
|
if (codec == HAL_VIDEO_CODEC_HEVC &&
|
|
inst->profile == HFI_HEVC_PROFILE_MAIN10) {
|
|
s_vpr_e(inst->sid, "Unsupported HEVC profile for all intra\n");
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
/* CBR_CFR is one of the advertised rc mode for HEVC encoding.
|
|
* However, all-intra is intended for quality bitstream. Hence,
|
|
* fallback to VBR RC mode if client needs all-intra encoding.
|
|
*/
|
|
if (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
|
|
inst->rc_type = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
|
|
|
|
/* check supported bit rate mode and frame rate */
|
|
capability = &inst->capability;
|
|
n_fps = inst->clk_data.frame_rate >> 16;
|
|
fps_max = capability->cap[CAP_ALLINTRA_MAX_FPS].max;
|
|
s_vpr_h(inst->sid, "%s: rc_type %u, fps %u, fps_max %u\n",
|
|
__func__, inst->rc_type, n_fps, fps_max);
|
|
if ((inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
|
|
inst->rc_type != RATE_CONTROL_OFF &&
|
|
inst->rc_type != RATE_CONTROL_LOSSLESS) ||
|
|
n_fps > fps_max) {
|
|
s_vpr_e(inst->sid, "Unsupported bitrate mode or frame rate\n");
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
set_all_intra_preconditions(inst);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int check_blur_restrictions(struct msm_vidc_inst *inst)
|
|
{
|
|
struct v4l2_ctrl *cac = NULL;
|
|
struct v4l2_ctrl *profile = NULL;
|
|
struct v4l2_ctrl *blur = NULL;
|
|
struct v4l2_format *f;
|
|
bool scalar_enable = false;
|
|
bool sup_resolution = false;
|
|
bool sup_codec = false;
|
|
bool is_10_bit = false;
|
|
u32 input_height, input_width;
|
|
u32 codec;
|
|
|
|
/* Only need to check static VPSS conditions */
|
|
if (inst->state == MSM_VIDC_START_DONE)
|
|
return 0;
|
|
|
|
scalar_enable = vidc_scalar_enabled(inst);
|
|
blur = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_BLUR_DIMENSIONS);
|
|
/* Minimum restrictions to enable any type of blur */
|
|
if (scalar_enable || inst->static_rotation_flip_enabled) {
|
|
return -ENOTSUPP;
|
|
}
|
|
if (blur->val != MSM_VIDC_BLUR_INTERNAL) {
|
|
/* below restrictions applicable for internal blur only */
|
|
return 0;
|
|
}
|
|
|
|
f = &inst->fmts[INPUT_PORT].v4l2_fmt;
|
|
input_height = f->fmt.pix_mp.height;
|
|
input_width = f->fmt.pix_mp.width;
|
|
|
|
/* Adaptive blur restrictions */
|
|
cac = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VENC_BITRATE_SAVINGS);
|
|
codec = get_v4l2_codec(inst);
|
|
profile = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_PROFILE);
|
|
|
|
if (codec == V4L2_PIX_FMT_HEVC &&
|
|
profile->val == V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10) {
|
|
is_10_bit = true;
|
|
}
|
|
if (res_is_greater_than(input_width, input_height, 352, 240) &&
|
|
res_is_less_than_or_equal_to(input_width, input_height,
|
|
3840, 2160)) {
|
|
sup_resolution = true;
|
|
}
|
|
|
|
if (codec == V4L2_PIX_FMT_HEVC || codec == V4L2_PIX_FMT_H264)
|
|
sup_codec = true;
|
|
|
|
if (inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR ||
|
|
!cac->val || is_10_bit || !sup_codec || inst->all_intra ||
|
|
!sup_resolution) {
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int msm_venc_set_properties(struct msm_vidc_inst *inst)
|
|
{
|
|
int rc = 0;
|
|
|
|
rc = msm_venc_update_entropy_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_update_bitrate(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = handle_all_intra_restrictions(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_frame_size(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_frame_rate(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_secure_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_priority(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_color_format(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_sequence_header_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_profile_level(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_8x8_transform(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_entropy_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_rate_control(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_vbv_delay(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_bitrate_savings_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_input_timestamp_rc(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_frame_qp(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_qp_range(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_image_properties(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_au_delimiter_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_vui_timing_info(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_hdr_info(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_nal_stream_format(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_slice_control_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_loop_filter_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_intra_refresh_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_ltr_mode(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_hb_max_layer(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_hp_max_layer(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_hp_layer(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_base_layer_priority_id(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_idr_period(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_intra_period(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_aspect_ratio(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_video_signal_info(inst);
|
|
if (rc)
|
|
goto exit;
|
|
/*
|
|
* Layer bitrate is preferred over cumulative bitrate.
|
|
* Cumulative bitrate is set only when we fall back.
|
|
*/
|
|
rc = msm_venc_set_layer_bitrate(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_bitrate(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_video_csc(inst);
|
|
if (rc)
|
|
goto exit;
|
|
/*
|
|
* Downscalar and Static rotation/flip has higher priority
|
|
* than blur.
|
|
*/
|
|
rc = msm_venc_set_rotation(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_chroma_qp_offset(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_blur_resolution(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_extradata(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_operating_rate(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_buffer_counts(inst);
|
|
if (rc)
|
|
goto exit;
|
|
rc = msm_venc_set_lossless(inst);
|
|
if (rc)
|
|
goto exit;
|
|
|
|
exit:
|
|
if (rc)
|
|
s_vpr_e(inst->sid, "%s: failed with %d\n", __func__, rc);
|
|
else
|
|
s_vpr_h(inst->sid, "%s: set properties successful\n", __func__);
|
|
|
|
return rc;
|
|
}
|