18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) STMicroelectronics SA 2015 48c2ecf20Sopenharmony_ci * Authors: Yannick Fertre <yannick.fertre@st.com> 58c2ecf20Sopenharmony_ci * Hugues Fruchet <hugues.fruchet@st.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "hva.h" 98c2ecf20Sopenharmony_ci#include "hva-hw.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#define MAX_SPS_PPS_SIZE 128 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define BITSTREAM_OFFSET_MASK 0x7F 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* video max size*/ 168c2ecf20Sopenharmony_ci#define H264_MAX_SIZE_W 1920 178c2ecf20Sopenharmony_ci#define H264_MAX_SIZE_H 1920 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* macroBlocs number (width & height) */ 208c2ecf20Sopenharmony_ci#define MB_W(w) ((w + 0xF) / 0x10) 218c2ecf20Sopenharmony_ci#define MB_H(h) ((h + 0xF) / 0x10) 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* formula to get temporal or spatial data size */ 248c2ecf20Sopenharmony_ci#define DATA_SIZE(w, h) (MB_W(w) * MB_H(h) * 16) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define SEARCH_WINDOW_BUFFER_MAX_SIZE(w) ((4 * MB_W(w) + 42) * 256 * 3 / 2) 278c2ecf20Sopenharmony_ci#define CABAC_CONTEXT_BUFFER_MAX_SIZE(w) (MB_W(w) * 16) 288c2ecf20Sopenharmony_ci#define CTX_MB_BUFFER_MAX_SIZE(w) (MB_W(w) * 16 * 8) 298c2ecf20Sopenharmony_ci#define SLICE_HEADER_SIZE (4 * 16) 308c2ecf20Sopenharmony_ci#define BRC_DATA_SIZE (5 * 16) 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* source buffer copy in YUV 420 MB-tiled format with size=16*256*3/2 */ 338c2ecf20Sopenharmony_ci#define CURRENT_WINDOW_BUFFER_MAX_SIZE (16 * 256 * 3 / 2) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* 368c2ecf20Sopenharmony_ci * 4 lines of pixels (in Luma, Chroma blue and Chroma red) of top MB 378c2ecf20Sopenharmony_ci * for deblocking with size=4*16*MBx*2 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_ci#define LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(w) (4 * 16 * MB_W(w) * 2) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* factor for bitrate and cpb buffer size max values if profile >= high */ 428c2ecf20Sopenharmony_ci#define H264_FACTOR_HIGH 1200 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* factor for bitrate and cpb buffer size max values if profile < high */ 458c2ecf20Sopenharmony_ci#define H264_FACTOR_BASELINE 1000 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* number of bytes for NALU_TYPE_FILLER_DATA header and footer */ 488c2ecf20Sopenharmony_ci#define H264_FILLER_DATA_SIZE 6 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistruct h264_profile { 518c2ecf20Sopenharmony_ci enum v4l2_mpeg_video_h264_level level; 528c2ecf20Sopenharmony_ci u32 max_mb_per_seconds; 538c2ecf20Sopenharmony_ci u32 max_frame_size; 548c2ecf20Sopenharmony_ci u32 max_bitrate; 558c2ecf20Sopenharmony_ci u32 max_cpb_size; 568c2ecf20Sopenharmony_ci u32 min_comp_ratio; 578c2ecf20Sopenharmony_ci}; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic const struct h264_profile h264_infos_list[] = { 608c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_1_0, 1485, 99, 64, 175, 2}, 618c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_1B, 1485, 99, 128, 350, 2}, 628c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_1_1, 3000, 396, 192, 500, 2}, 638c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_1_2, 6000, 396, 384, 1000, 2}, 648c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_1_3, 11880, 396, 768, 2000, 2}, 658c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_2_0, 11880, 396, 2000, 2000, 2}, 668c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_2_1, 19800, 792, 4000, 4000, 2}, 678c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_2_2, 20250, 1620, 4000, 4000, 2}, 688c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_3_0, 40500, 1620, 10000, 10000, 2}, 698c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_3_1, 108000, 3600, 14000, 14000, 4}, 708c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_3_2, 216000, 5120, 20000, 20000, 4}, 718c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 245760, 8192, 20000, 25000, 4}, 728c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_4_1, 245760, 8192, 50000, 62500, 2}, 738c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_4_2, 522240, 8704, 50000, 62500, 2}, 748c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_5_0, 589824, 22080, 135000, 135000, 2}, 758c2ecf20Sopenharmony_ci {V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 983040, 36864, 240000, 240000, 2} 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cienum hva_brc_type { 798c2ecf20Sopenharmony_ci BRC_TYPE_NONE = 0, 808c2ecf20Sopenharmony_ci BRC_TYPE_CBR = 1, 818c2ecf20Sopenharmony_ci BRC_TYPE_VBR = 2, 828c2ecf20Sopenharmony_ci BRC_TYPE_VBR_LOW_DELAY = 3 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cienum hva_entropy_coding_mode { 868c2ecf20Sopenharmony_ci CAVLC = 0, 878c2ecf20Sopenharmony_ci CABAC = 1 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cienum hva_picture_coding_type { 918c2ecf20Sopenharmony_ci PICTURE_CODING_TYPE_I = 0, 928c2ecf20Sopenharmony_ci PICTURE_CODING_TYPE_P = 1, 938c2ecf20Sopenharmony_ci PICTURE_CODING_TYPE_B = 2 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cienum hva_h264_sampling_mode { 978c2ecf20Sopenharmony_ci SAMPLING_MODE_NV12 = 0, 988c2ecf20Sopenharmony_ci SAMPLING_MODE_UYVY = 1, 998c2ecf20Sopenharmony_ci SAMPLING_MODE_RGB3 = 3, 1008c2ecf20Sopenharmony_ci SAMPLING_MODE_XRGB4 = 4, 1018c2ecf20Sopenharmony_ci SAMPLING_MODE_NV21 = 8, 1028c2ecf20Sopenharmony_ci SAMPLING_MODE_VYUY = 9, 1038c2ecf20Sopenharmony_ci SAMPLING_MODE_BGR3 = 11, 1048c2ecf20Sopenharmony_ci SAMPLING_MODE_XBGR4 = 12, 1058c2ecf20Sopenharmony_ci SAMPLING_MODE_RGBX4 = 20, 1068c2ecf20Sopenharmony_ci SAMPLING_MODE_BGRX4 = 28 1078c2ecf20Sopenharmony_ci}; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cienum hva_h264_nalu_type { 1108c2ecf20Sopenharmony_ci NALU_TYPE_UNKNOWN = 0, 1118c2ecf20Sopenharmony_ci NALU_TYPE_SLICE = 1, 1128c2ecf20Sopenharmony_ci NALU_TYPE_SLICE_DPA = 2, 1138c2ecf20Sopenharmony_ci NALU_TYPE_SLICE_DPB = 3, 1148c2ecf20Sopenharmony_ci NALU_TYPE_SLICE_DPC = 4, 1158c2ecf20Sopenharmony_ci NALU_TYPE_SLICE_IDR = 5, 1168c2ecf20Sopenharmony_ci NALU_TYPE_SEI = 6, 1178c2ecf20Sopenharmony_ci NALU_TYPE_SPS = 7, 1188c2ecf20Sopenharmony_ci NALU_TYPE_PPS = 8, 1198c2ecf20Sopenharmony_ci NALU_TYPE_AU_DELIMITER = 9, 1208c2ecf20Sopenharmony_ci NALU_TYPE_SEQ_END = 10, 1218c2ecf20Sopenharmony_ci NALU_TYPE_STREAM_END = 11, 1228c2ecf20Sopenharmony_ci NALU_TYPE_FILLER_DATA = 12, 1238c2ecf20Sopenharmony_ci NALU_TYPE_SPS_EXT = 13, 1248c2ecf20Sopenharmony_ci NALU_TYPE_PREFIX_UNIT = 14, 1258c2ecf20Sopenharmony_ci NALU_TYPE_SUBSET_SPS = 15, 1268c2ecf20Sopenharmony_ci NALU_TYPE_SLICE_AUX = 19, 1278c2ecf20Sopenharmony_ci NALU_TYPE_SLICE_EXT = 20 1288c2ecf20Sopenharmony_ci}; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cienum hva_h264_sei_payload_type { 1318c2ecf20Sopenharmony_ci SEI_BUFFERING_PERIOD = 0, 1328c2ecf20Sopenharmony_ci SEI_PICTURE_TIMING = 1, 1338c2ecf20Sopenharmony_ci SEI_STEREO_VIDEO_INFO = 21, 1348c2ecf20Sopenharmony_ci SEI_FRAME_PACKING_ARRANGEMENT = 45 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* 1388c2ecf20Sopenharmony_ci * stereo Video Info struct 1398c2ecf20Sopenharmony_ci */ 1408c2ecf20Sopenharmony_cistruct hva_h264_stereo_video_sei { 1418c2ecf20Sopenharmony_ci u8 field_views_flag; 1428c2ecf20Sopenharmony_ci u8 top_field_is_left_view_flag; 1438c2ecf20Sopenharmony_ci u8 current_frame_is_left_view_flag; 1448c2ecf20Sopenharmony_ci u8 next_frame_is_second_view_flag; 1458c2ecf20Sopenharmony_ci u8 left_view_self_contained_flag; 1468c2ecf20Sopenharmony_ci u8 right_view_self_contained_flag; 1478c2ecf20Sopenharmony_ci}; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* 1508c2ecf20Sopenharmony_ci * struct hva_h264_td 1518c2ecf20Sopenharmony_ci * 1528c2ecf20Sopenharmony_ci * @frame_width: width in pixels of the buffer containing the input frame 1538c2ecf20Sopenharmony_ci * @frame_height: height in pixels of the buffer containing the input frame 1548c2ecf20Sopenharmony_ci * @frame_num: the parameter to be written in the slice header 1558c2ecf20Sopenharmony_ci * @picture_coding_type: type I, P or B 1568c2ecf20Sopenharmony_ci * @pic_order_cnt_type: POC mode, as defined in H264 std : can be 0,1,2 1578c2ecf20Sopenharmony_ci * @first_picture_in_sequence: flag telling to encoder that this is the 1588c2ecf20Sopenharmony_ci * first picture in a video sequence. 1598c2ecf20Sopenharmony_ci * Used for VBR 1608c2ecf20Sopenharmony_ci * @slice_size_type: 0 = no constraint to close the slice 1618c2ecf20Sopenharmony_ci * 1= a slice is closed as soon as the slice_mb_size limit 1628c2ecf20Sopenharmony_ci * is reached 1638c2ecf20Sopenharmony_ci * 2= a slice is closed as soon as the slice_byte_size limit 1648c2ecf20Sopenharmony_ci * is reached 1658c2ecf20Sopenharmony_ci * 3= a slice is closed as soon as either the slice_byte_size 1668c2ecf20Sopenharmony_ci * limit or the slice_mb_size limit is reached 1678c2ecf20Sopenharmony_ci * @slice_mb_size: defines the slice size in number of macroblocks 1688c2ecf20Sopenharmony_ci * (used when slice_size_type=1 or slice_size_type=3) 1698c2ecf20Sopenharmony_ci * @ir_param_option: defines the number of macroblocks per frame to be 1708c2ecf20Sopenharmony_ci * refreshed by AIR algorithm OR the refresh period 1718c2ecf20Sopenharmony_ci * by CIR algorithm 1728c2ecf20Sopenharmony_ci * @intra_refresh_type: enables the adaptive intra refresh algorithm. 1738c2ecf20Sopenharmony_ci * Disable=0 / Adaptative=1 and Cycle=2 as intra refresh 1748c2ecf20Sopenharmony_ci * @use_constrained_intra_flag: constrained_intra_pred_flag from PPS 1758c2ecf20Sopenharmony_ci * @transform_mode: controls the use of 4x4/8x8 transform mode 1768c2ecf20Sopenharmony_ci * @disable_deblocking_filter_idc: 1778c2ecf20Sopenharmony_ci * 0: specifies that all luma and chroma block edges of 1788c2ecf20Sopenharmony_ci * the slice are filtered. 1798c2ecf20Sopenharmony_ci * 1: specifies that deblocking is disabled for all block 1808c2ecf20Sopenharmony_ci * edges of the slice. 1818c2ecf20Sopenharmony_ci * 2: specifies that all luma and chroma block edges of 1828c2ecf20Sopenharmony_ci * the slice are filtered with exception of the block edges 1838c2ecf20Sopenharmony_ci * that coincide with slice boundaries 1848c2ecf20Sopenharmony_ci * @slice_alpha_c0_offset_div2: to be written in slice header, 1858c2ecf20Sopenharmony_ci * controls deblocking 1868c2ecf20Sopenharmony_ci * @slice_beta_offset_div2: to be written in slice header, 1878c2ecf20Sopenharmony_ci * controls deblocking 1888c2ecf20Sopenharmony_ci * @encoder_complexity: encoder complexity control (IME). 1898c2ecf20Sopenharmony_ci * 0 = I_16x16, P_16x16, Full ME Complexity 1908c2ecf20Sopenharmony_ci * 1 = I_16x16, I_NxN, P_16x16, Full ME Complexity 1918c2ecf20Sopenharmony_ci * 2 = I_16x16, I_NXN, P_16x16, P_WxH, Full ME Complexity 1928c2ecf20Sopenharmony_ci * 4 = I_16x16, P_16x16, Reduced ME Complexity 1938c2ecf20Sopenharmony_ci * 5 = I_16x16, I_NxN, P_16x16, Reduced ME Complexity 1948c2ecf20Sopenharmony_ci * 6 = I_16x16, I_NXN, P_16x16, P_WxH, Reduced ME Complexity 1958c2ecf20Sopenharmony_ci * @chroma_qp_index_offset: coming from picture parameter set 1968c2ecf20Sopenharmony_ci * (PPS see [H.264 STD] 7.4.2.2) 1978c2ecf20Sopenharmony_ci * @entropy_coding_mode: entropy coding mode. 1988c2ecf20Sopenharmony_ci * 0 = CAVLC 1998c2ecf20Sopenharmony_ci * 1 = CABAC 2008c2ecf20Sopenharmony_ci * @brc_type: selects the bit-rate control algorithm 2018c2ecf20Sopenharmony_ci * 0 = constant Qp, (no BRC) 2028c2ecf20Sopenharmony_ci * 1 = CBR 2038c2ecf20Sopenharmony_ci * 2 = VBR 2048c2ecf20Sopenharmony_ci * @quant: Quantization param used in case of fix QP encoding (no BRC) 2058c2ecf20Sopenharmony_ci * @non_VCL_NALU_Size: size of non-VCL NALUs (SPS, PPS, filler), 2068c2ecf20Sopenharmony_ci * used by BRC 2078c2ecf20Sopenharmony_ci * @cpb_buffer_size: size of Coded Picture Buffer, used by BRC 2088c2ecf20Sopenharmony_ci * @bit_rate: target bitrate, for BRC 2098c2ecf20Sopenharmony_ci * @qp_min: min QP threshold 2108c2ecf20Sopenharmony_ci * @qp_max: max QP threshold 2118c2ecf20Sopenharmony_ci * @framerate_num: target framerate numerator , used by BRC 2128c2ecf20Sopenharmony_ci * @framerate_den: target framerate denomurator , used by BRC 2138c2ecf20Sopenharmony_ci * @delay: End-to-End Initial Delay 2148c2ecf20Sopenharmony_ci * @strict_HRD_compliancy: flag for HDR compliancy (1) 2158c2ecf20Sopenharmony_ci * May impact quality encoding 2168c2ecf20Sopenharmony_ci * @addr_source_buffer: address of input frame buffer for current frame 2178c2ecf20Sopenharmony_ci * @addr_fwd_Ref_Buffer: address of reference frame buffer 2188c2ecf20Sopenharmony_ci * @addr_rec_buffer: address of reconstructed frame buffer 2198c2ecf20Sopenharmony_ci * @addr_output_bitstream_start: output bitstream start address 2208c2ecf20Sopenharmony_ci * @addr_output_bitstream_end: output bitstream end address 2218c2ecf20Sopenharmony_ci * @addr_external_sw : address of external search window 2228c2ecf20Sopenharmony_ci * @addr_lctx : address of context picture buffer 2238c2ecf20Sopenharmony_ci * @addr_local_rec_buffer: address of local reconstructed buffer 2248c2ecf20Sopenharmony_ci * @addr_spatial_context: address of spatial context buffer 2258c2ecf20Sopenharmony_ci * @bitstream_offset: offset in bits between aligned bitstream start 2268c2ecf20Sopenharmony_ci * address and first bit to be written by HVA. 2278c2ecf20Sopenharmony_ci * Range value is [0..63] 2288c2ecf20Sopenharmony_ci * @sampling_mode: Input picture format . 2298c2ecf20Sopenharmony_ci * 0: YUV420 semi_planar Interleaved 2308c2ecf20Sopenharmony_ci * 1: YUV422 raster Interleaved 2318c2ecf20Sopenharmony_ci * @addr_param_out: address of output parameters structure 2328c2ecf20Sopenharmony_ci * @addr_scaling_matrix: address to the coefficient of 2338c2ecf20Sopenharmony_ci * the inverse scaling matrix 2348c2ecf20Sopenharmony_ci * @addr_scaling_matrix_dir: address to the coefficient of 2358c2ecf20Sopenharmony_ci * the direct scaling matrix 2368c2ecf20Sopenharmony_ci * @addr_cabac_context_buffer: address of cabac context buffer 2378c2ecf20Sopenharmony_ci * @GmvX: Input information about the horizontal global displacement of 2388c2ecf20Sopenharmony_ci * the encoded frame versus the previous one 2398c2ecf20Sopenharmony_ci * @GmvY: Input information about the vertical global displacement of 2408c2ecf20Sopenharmony_ci * the encoded frame versus the previous one 2418c2ecf20Sopenharmony_ci * @window_width: width in pixels of the window to be encoded inside 2428c2ecf20Sopenharmony_ci * the input frame 2438c2ecf20Sopenharmony_ci * @window_height: width in pixels of the window to be encoded inside 2448c2ecf20Sopenharmony_ci * the input frame 2458c2ecf20Sopenharmony_ci * @window_horizontal_offset: horizontal offset in pels for input window 2468c2ecf20Sopenharmony_ci * within input frame 2478c2ecf20Sopenharmony_ci * @window_vertical_offset: vertical offset in pels for input window 2488c2ecf20Sopenharmony_ci * within input frame 2498c2ecf20Sopenharmony_ci * @addr_roi: Map of QP offset for the Region of Interest algorithm and 2508c2ecf20Sopenharmony_ci * also used for Error map. 2518c2ecf20Sopenharmony_ci * Bit 0-6 used for qp offset (value -64 to 63). 2528c2ecf20Sopenharmony_ci * Bit 7 used to force intra 2538c2ecf20Sopenharmony_ci * @addr_slice_header: address to slice header 2548c2ecf20Sopenharmony_ci * @slice_header_size_in_bits: size in bits of the Slice header 2558c2ecf20Sopenharmony_ci * @slice_header_offset0: Slice header offset where to insert 2568c2ecf20Sopenharmony_ci * first_Mb_in_slice 2578c2ecf20Sopenharmony_ci * @slice_header_offset1: Slice header offset where to insert 2588c2ecf20Sopenharmony_ci * slice_qp_delta 2598c2ecf20Sopenharmony_ci * @slice_header_offset2: Slice header offset where to insert 2608c2ecf20Sopenharmony_ci * num_MBs_in_slice 2618c2ecf20Sopenharmony_ci * @slice_synchro_enable: enable "slice ready" interrupt after each slice 2628c2ecf20Sopenharmony_ci * @max_slice_number: Maximum number of slice in a frame 2638c2ecf20Sopenharmony_ci * (0 is strictly forbidden) 2648c2ecf20Sopenharmony_ci * @rgb2_yuv_y_coeff: Four coefficients (C0C1C2C3) to convert from RGB to 2658c2ecf20Sopenharmony_ci * YUV for the Y component. 2668c2ecf20Sopenharmony_ci * Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) 2678c2ecf20Sopenharmony_ci * @rgb2_yuv_u_coeff: four coefficients (C0C1C2C3) to convert from RGB to 2688c2ecf20Sopenharmony_ci * YUV for the Y component. 2698c2ecf20Sopenharmony_ci * Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) 2708c2ecf20Sopenharmony_ci * @rgb2_yuv_v_coeff: Four coefficients (C0C1C2C3) to convert from RGB to 2718c2ecf20Sopenharmony_ci * YUV for the U (Cb) component. 2728c2ecf20Sopenharmony_ci * U = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) 2738c2ecf20Sopenharmony_ci * @slice_byte_size: maximum slice size in bytes 2748c2ecf20Sopenharmony_ci * (used when slice_size_type=2 or slice_size_type=3) 2758c2ecf20Sopenharmony_ci * @max_air_intra_mb_nb: Maximum number of intra macroblock in a frame 2768c2ecf20Sopenharmony_ci * for the AIR algorithm 2778c2ecf20Sopenharmony_ci * @brc_no_skip: Disable skipping in the Bitrate Controller 2788c2ecf20Sopenharmony_ci * @addr_brc_in_out_parameter: address of static buffer for BRC parameters 2798c2ecf20Sopenharmony_ci */ 2808c2ecf20Sopenharmony_cistruct hva_h264_td { 2818c2ecf20Sopenharmony_ci u16 frame_width; 2828c2ecf20Sopenharmony_ci u16 frame_height; 2838c2ecf20Sopenharmony_ci u32 frame_num; 2848c2ecf20Sopenharmony_ci u16 picture_coding_type; 2858c2ecf20Sopenharmony_ci u16 reserved1; 2868c2ecf20Sopenharmony_ci u16 pic_order_cnt_type; 2878c2ecf20Sopenharmony_ci u16 first_picture_in_sequence; 2888c2ecf20Sopenharmony_ci u16 slice_size_type; 2898c2ecf20Sopenharmony_ci u16 reserved2; 2908c2ecf20Sopenharmony_ci u32 slice_mb_size; 2918c2ecf20Sopenharmony_ci u16 ir_param_option; 2928c2ecf20Sopenharmony_ci u16 intra_refresh_type; 2938c2ecf20Sopenharmony_ci u16 use_constrained_intra_flag; 2948c2ecf20Sopenharmony_ci u16 transform_mode; 2958c2ecf20Sopenharmony_ci u16 disable_deblocking_filter_idc; 2968c2ecf20Sopenharmony_ci s16 slice_alpha_c0_offset_div2; 2978c2ecf20Sopenharmony_ci s16 slice_beta_offset_div2; 2988c2ecf20Sopenharmony_ci u16 encoder_complexity; 2998c2ecf20Sopenharmony_ci s16 chroma_qp_index_offset; 3008c2ecf20Sopenharmony_ci u16 entropy_coding_mode; 3018c2ecf20Sopenharmony_ci u16 brc_type; 3028c2ecf20Sopenharmony_ci u16 quant; 3038c2ecf20Sopenharmony_ci u32 non_vcl_nalu_size; 3048c2ecf20Sopenharmony_ci u32 cpb_buffer_size; 3058c2ecf20Sopenharmony_ci u32 bit_rate; 3068c2ecf20Sopenharmony_ci u16 qp_min; 3078c2ecf20Sopenharmony_ci u16 qp_max; 3088c2ecf20Sopenharmony_ci u16 framerate_num; 3098c2ecf20Sopenharmony_ci u16 framerate_den; 3108c2ecf20Sopenharmony_ci u16 delay; 3118c2ecf20Sopenharmony_ci u16 strict_hrd_compliancy; 3128c2ecf20Sopenharmony_ci u32 addr_source_buffer; 3138c2ecf20Sopenharmony_ci u32 addr_fwd_ref_buffer; 3148c2ecf20Sopenharmony_ci u32 addr_rec_buffer; 3158c2ecf20Sopenharmony_ci u32 addr_output_bitstream_start; 3168c2ecf20Sopenharmony_ci u32 addr_output_bitstream_end; 3178c2ecf20Sopenharmony_ci u32 addr_external_sw; 3188c2ecf20Sopenharmony_ci u32 addr_lctx; 3198c2ecf20Sopenharmony_ci u32 addr_local_rec_buffer; 3208c2ecf20Sopenharmony_ci u32 addr_spatial_context; 3218c2ecf20Sopenharmony_ci u16 bitstream_offset; 3228c2ecf20Sopenharmony_ci u16 sampling_mode; 3238c2ecf20Sopenharmony_ci u32 addr_param_out; 3248c2ecf20Sopenharmony_ci u32 addr_scaling_matrix; 3258c2ecf20Sopenharmony_ci u32 addr_scaling_matrix_dir; 3268c2ecf20Sopenharmony_ci u32 addr_cabac_context_buffer; 3278c2ecf20Sopenharmony_ci u32 reserved3; 3288c2ecf20Sopenharmony_ci u32 reserved4; 3298c2ecf20Sopenharmony_ci s16 gmv_x; 3308c2ecf20Sopenharmony_ci s16 gmv_y; 3318c2ecf20Sopenharmony_ci u16 window_width; 3328c2ecf20Sopenharmony_ci u16 window_height; 3338c2ecf20Sopenharmony_ci u16 window_horizontal_offset; 3348c2ecf20Sopenharmony_ci u16 window_vertical_offset; 3358c2ecf20Sopenharmony_ci u32 addr_roi; 3368c2ecf20Sopenharmony_ci u32 addr_slice_header; 3378c2ecf20Sopenharmony_ci u16 slice_header_size_in_bits; 3388c2ecf20Sopenharmony_ci u16 slice_header_offset0; 3398c2ecf20Sopenharmony_ci u16 slice_header_offset1; 3408c2ecf20Sopenharmony_ci u16 slice_header_offset2; 3418c2ecf20Sopenharmony_ci u32 reserved5; 3428c2ecf20Sopenharmony_ci u32 reserved6; 3438c2ecf20Sopenharmony_ci u16 reserved7; 3448c2ecf20Sopenharmony_ci u16 reserved8; 3458c2ecf20Sopenharmony_ci u16 slice_synchro_enable; 3468c2ecf20Sopenharmony_ci u16 max_slice_number; 3478c2ecf20Sopenharmony_ci u32 rgb2_yuv_y_coeff; 3488c2ecf20Sopenharmony_ci u32 rgb2_yuv_u_coeff; 3498c2ecf20Sopenharmony_ci u32 rgb2_yuv_v_coeff; 3508c2ecf20Sopenharmony_ci u32 slice_byte_size; 3518c2ecf20Sopenharmony_ci u16 max_air_intra_mb_nb; 3528c2ecf20Sopenharmony_ci u16 brc_no_skip; 3538c2ecf20Sopenharmony_ci u32 addr_temporal_context; 3548c2ecf20Sopenharmony_ci u32 addr_brc_in_out_parameter; 3558c2ecf20Sopenharmony_ci}; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci/* 3588c2ecf20Sopenharmony_ci * struct hva_h264_slice_po 3598c2ecf20Sopenharmony_ci * 3608c2ecf20Sopenharmony_ci * @ slice_size: slice size 3618c2ecf20Sopenharmony_ci * @ slice_start_time: start time 3628c2ecf20Sopenharmony_ci * @ slice_stop_time: stop time 3638c2ecf20Sopenharmony_ci * @ slice_num: slice number 3648c2ecf20Sopenharmony_ci */ 3658c2ecf20Sopenharmony_cistruct hva_h264_slice_po { 3668c2ecf20Sopenharmony_ci u32 slice_size; 3678c2ecf20Sopenharmony_ci u32 slice_start_time; 3688c2ecf20Sopenharmony_ci u32 slice_end_time; 3698c2ecf20Sopenharmony_ci u32 slice_num; 3708c2ecf20Sopenharmony_ci}; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci/* 3738c2ecf20Sopenharmony_ci * struct hva_h264_po 3748c2ecf20Sopenharmony_ci * 3758c2ecf20Sopenharmony_ci * @ bitstream_size: bitstream size 3768c2ecf20Sopenharmony_ci * @ dct_bitstream_size: dtc bitstream size 3778c2ecf20Sopenharmony_ci * @ stuffing_bits: number of stuffing bits inserted by the encoder 3788c2ecf20Sopenharmony_ci * @ removal_time: removal time of current frame (nb of ticks 1/framerate) 3798c2ecf20Sopenharmony_ci * @ hvc_start_time: hvc start time 3808c2ecf20Sopenharmony_ci * @ hvc_stop_time: hvc stop time 3818c2ecf20Sopenharmony_ci * @ slice_count: slice count 3828c2ecf20Sopenharmony_ci */ 3838c2ecf20Sopenharmony_cistruct hva_h264_po { 3848c2ecf20Sopenharmony_ci u32 bitstream_size; 3858c2ecf20Sopenharmony_ci u32 dct_bitstream_size; 3868c2ecf20Sopenharmony_ci u32 stuffing_bits; 3878c2ecf20Sopenharmony_ci u32 removal_time; 3888c2ecf20Sopenharmony_ci u32 hvc_start_time; 3898c2ecf20Sopenharmony_ci u32 hvc_stop_time; 3908c2ecf20Sopenharmony_ci u32 slice_count; 3918c2ecf20Sopenharmony_ci u32 reserved0; 3928c2ecf20Sopenharmony_ci struct hva_h264_slice_po slice_params[16]; 3938c2ecf20Sopenharmony_ci}; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistruct hva_h264_task { 3968c2ecf20Sopenharmony_ci struct hva_h264_td td; 3978c2ecf20Sopenharmony_ci struct hva_h264_po po; 3988c2ecf20Sopenharmony_ci}; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci/* 4018c2ecf20Sopenharmony_ci * struct hva_h264_ctx 4028c2ecf20Sopenharmony_ci * 4038c2ecf20Sopenharmony_ci * @seq_info: sequence information buffer 4048c2ecf20Sopenharmony_ci * @ref_frame: reference frame buffer 4058c2ecf20Sopenharmony_ci * @rec_frame: reconstructed frame buffer 4068c2ecf20Sopenharmony_ci * @task: task descriptor 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_cistruct hva_h264_ctx { 4098c2ecf20Sopenharmony_ci struct hva_buffer *seq_info; 4108c2ecf20Sopenharmony_ci struct hva_buffer *ref_frame; 4118c2ecf20Sopenharmony_ci struct hva_buffer *rec_frame; 4128c2ecf20Sopenharmony_ci struct hva_buffer *task; 4138c2ecf20Sopenharmony_ci}; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic int hva_h264_fill_slice_header(struct hva_ctx *pctx, 4168c2ecf20Sopenharmony_ci u8 *slice_header_addr, 4178c2ecf20Sopenharmony_ci struct hva_controls *ctrls, 4188c2ecf20Sopenharmony_ci int frame_num, 4198c2ecf20Sopenharmony_ci u16 *header_size, 4208c2ecf20Sopenharmony_ci u16 *header_offset0, 4218c2ecf20Sopenharmony_ci u16 *header_offset1, 4228c2ecf20Sopenharmony_ci u16 *header_offset2) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci /* 4258c2ecf20Sopenharmony_ci * with this HVA hardware version, part of the slice header is computed 4268c2ecf20Sopenharmony_ci * on host and part by hardware. 4278c2ecf20Sopenharmony_ci * The part of host is precomputed and available through this array. 4288c2ecf20Sopenharmony_ci */ 4298c2ecf20Sopenharmony_ci struct device *dev = ctx_to_dev(pctx); 4308c2ecf20Sopenharmony_ci int cabac = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC; 4318c2ecf20Sopenharmony_ci const unsigned char slice_header[] = { 0x00, 0x00, 0x00, 0x01, 4328c2ecf20Sopenharmony_ci 0x41, 0x34, 0x07, 0x00}; 4338c2ecf20Sopenharmony_ci int idr_pic_id = frame_num % 2; 4348c2ecf20Sopenharmony_ci enum hva_picture_coding_type type; 4358c2ecf20Sopenharmony_ci u32 frame_order = frame_num % ctrls->gop_size; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci if (!(frame_num % ctrls->gop_size)) 4388c2ecf20Sopenharmony_ci type = PICTURE_CODING_TYPE_I; 4398c2ecf20Sopenharmony_ci else 4408c2ecf20Sopenharmony_ci type = PICTURE_CODING_TYPE_P; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci memcpy(slice_header_addr, slice_header, sizeof(slice_header)); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci *header_size = 56; 4458c2ecf20Sopenharmony_ci *header_offset0 = 40; 4468c2ecf20Sopenharmony_ci *header_offset1 = 13; 4478c2ecf20Sopenharmony_ci *header_offset2 = 0; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if (type == PICTURE_CODING_TYPE_I) { 4508c2ecf20Sopenharmony_ci slice_header_addr[4] = 0x65; 4518c2ecf20Sopenharmony_ci slice_header_addr[5] = 0x11; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* toggle the I frame */ 4548c2ecf20Sopenharmony_ci if ((frame_num / ctrls->gop_size) % 2) { 4558c2ecf20Sopenharmony_ci *header_size += 4; 4568c2ecf20Sopenharmony_ci *header_offset1 += 4; 4578c2ecf20Sopenharmony_ci slice_header_addr[6] = 0x04; 4588c2ecf20Sopenharmony_ci slice_header_addr[7] = 0x70; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci } else { 4618c2ecf20Sopenharmony_ci *header_size += 2; 4628c2ecf20Sopenharmony_ci *header_offset1 += 2; 4638c2ecf20Sopenharmony_ci slice_header_addr[6] = 0x09; 4648c2ecf20Sopenharmony_ci slice_header_addr[7] = 0xC0; 4658c2ecf20Sopenharmony_ci } 4668c2ecf20Sopenharmony_ci } else { 4678c2ecf20Sopenharmony_ci if (ctrls->entropy_mode == cabac) { 4688c2ecf20Sopenharmony_ci *header_size += 1; 4698c2ecf20Sopenharmony_ci *header_offset1 += 1; 4708c2ecf20Sopenharmony_ci slice_header_addr[7] = 0x80; 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci /* 4738c2ecf20Sopenharmony_ci * update slice header with P frame order 4748c2ecf20Sopenharmony_ci * frame order is limited to 16 (coded on 4bits only) 4758c2ecf20Sopenharmony_ci */ 4768c2ecf20Sopenharmony_ci slice_header_addr[5] += ((frame_order & 0x0C) >> 2); 4778c2ecf20Sopenharmony_ci slice_header_addr[6] += ((frame_order & 0x03) << 6); 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci dev_dbg(dev, 4818c2ecf20Sopenharmony_ci "%s %s slice header order %d idrPicId %d header size %d\n", 4828c2ecf20Sopenharmony_ci pctx->name, __func__, frame_order, idr_pic_id, *header_size); 4838c2ecf20Sopenharmony_ci return 0; 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic int hva_h264_fill_data_nal(struct hva_ctx *pctx, 4878c2ecf20Sopenharmony_ci unsigned int stuffing_bytes, u8 *addr, 4888c2ecf20Sopenharmony_ci unsigned int stream_size, unsigned int *size) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci struct device *dev = ctx_to_dev(pctx); 4918c2ecf20Sopenharmony_ci const u8 start[] = { 0x00, 0x00, 0x00, 0x01 }; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci dev_dbg(dev, "%s %s stuffing bytes %d\n", pctx->name, __func__, 4948c2ecf20Sopenharmony_ci stuffing_bytes); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if ((*size + stuffing_bytes + H264_FILLER_DATA_SIZE) > stream_size) { 4978c2ecf20Sopenharmony_ci dev_dbg(dev, "%s %s too many stuffing bytes %d\n", 4988c2ecf20Sopenharmony_ci pctx->name, __func__, stuffing_bytes); 4998c2ecf20Sopenharmony_ci return 0; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci /* start code */ 5038c2ecf20Sopenharmony_ci memcpy(addr + *size, start, sizeof(start)); 5048c2ecf20Sopenharmony_ci *size += sizeof(start); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci /* nal_unit_type */ 5078c2ecf20Sopenharmony_ci addr[*size] = NALU_TYPE_FILLER_DATA; 5088c2ecf20Sopenharmony_ci *size += 1; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci memset(addr + *size, 0xff, stuffing_bytes); 5118c2ecf20Sopenharmony_ci *size += stuffing_bytes; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci addr[*size] = 0x80; 5148c2ecf20Sopenharmony_ci *size += 1; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci return 0; 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cistatic int hva_h264_fill_sei_nal(struct hva_ctx *pctx, 5208c2ecf20Sopenharmony_ci enum hva_h264_sei_payload_type type, 5218c2ecf20Sopenharmony_ci u8 *addr, u32 *size) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci struct device *dev = ctx_to_dev(pctx); 5248c2ecf20Sopenharmony_ci const u8 start[] = { 0x00, 0x00, 0x00, 0x01 }; 5258c2ecf20Sopenharmony_ci struct hva_h264_stereo_video_sei info; 5268c2ecf20Sopenharmony_ci u8 offset = 7; 5278c2ecf20Sopenharmony_ci u8 msg = 0; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci /* start code */ 5308c2ecf20Sopenharmony_ci memcpy(addr + *size, start, sizeof(start)); 5318c2ecf20Sopenharmony_ci *size += sizeof(start); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci /* nal_unit_type */ 5348c2ecf20Sopenharmony_ci addr[*size] = NALU_TYPE_SEI; 5358c2ecf20Sopenharmony_ci *size += 1; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* payload type */ 5388c2ecf20Sopenharmony_ci addr[*size] = type; 5398c2ecf20Sopenharmony_ci *size += 1; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci switch (type) { 5428c2ecf20Sopenharmony_ci case SEI_STEREO_VIDEO_INFO: 5438c2ecf20Sopenharmony_ci memset(&info, 0, sizeof(info)); 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci /* set to top/bottom frame packing arrangement */ 5468c2ecf20Sopenharmony_ci info.field_views_flag = 1; 5478c2ecf20Sopenharmony_ci info.top_field_is_left_view_flag = 1; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci /* payload size */ 5508c2ecf20Sopenharmony_ci addr[*size] = 1; 5518c2ecf20Sopenharmony_ci *size += 1; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci /* payload */ 5548c2ecf20Sopenharmony_ci msg = info.field_views_flag << offset--; 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci if (info.field_views_flag) { 5578c2ecf20Sopenharmony_ci msg |= info.top_field_is_left_view_flag << 5588c2ecf20Sopenharmony_ci offset--; 5598c2ecf20Sopenharmony_ci } else { 5608c2ecf20Sopenharmony_ci msg |= info.current_frame_is_left_view_flag << 5618c2ecf20Sopenharmony_ci offset--; 5628c2ecf20Sopenharmony_ci msg |= info.next_frame_is_second_view_flag << 5638c2ecf20Sopenharmony_ci offset--; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci msg |= info.left_view_self_contained_flag << offset--; 5668c2ecf20Sopenharmony_ci msg |= info.right_view_self_contained_flag << offset--; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci addr[*size] = msg; 5698c2ecf20Sopenharmony_ci *size += 1; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci addr[*size] = 0x80; 5728c2ecf20Sopenharmony_ci *size += 1; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci return 0; 5758c2ecf20Sopenharmony_ci case SEI_BUFFERING_PERIOD: 5768c2ecf20Sopenharmony_ci case SEI_PICTURE_TIMING: 5778c2ecf20Sopenharmony_ci case SEI_FRAME_PACKING_ARRANGEMENT: 5788c2ecf20Sopenharmony_ci default: 5798c2ecf20Sopenharmony_ci dev_err(dev, "%s sei nal type not supported %d\n", 5808c2ecf20Sopenharmony_ci pctx->name, type); 5818c2ecf20Sopenharmony_ci return -EINVAL; 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic int hva_h264_prepare_task(struct hva_ctx *pctx, 5868c2ecf20Sopenharmony_ci struct hva_h264_task *task, 5878c2ecf20Sopenharmony_ci struct hva_frame *frame, 5888c2ecf20Sopenharmony_ci struct hva_stream *stream) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci struct hva_dev *hva = ctx_to_hdev(pctx); 5918c2ecf20Sopenharmony_ci struct device *dev = ctx_to_dev(pctx); 5928c2ecf20Sopenharmony_ci struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; 5938c2ecf20Sopenharmony_ci struct hva_buffer *seq_info = ctx->seq_info; 5948c2ecf20Sopenharmony_ci struct hva_buffer *fwd_ref_frame = ctx->ref_frame; 5958c2ecf20Sopenharmony_ci struct hva_buffer *loc_rec_frame = ctx->rec_frame; 5968c2ecf20Sopenharmony_ci struct hva_h264_td *td = &task->td; 5978c2ecf20Sopenharmony_ci struct hva_controls *ctrls = &pctx->ctrls; 5988c2ecf20Sopenharmony_ci struct v4l2_fract *time_per_frame = &pctx->ctrls.time_per_frame; 5998c2ecf20Sopenharmony_ci int cavlc = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; 6008c2ecf20Sopenharmony_ci u32 frame_num = pctx->stream_num; 6018c2ecf20Sopenharmony_ci u32 addr_esram = hva->esram_addr; 6028c2ecf20Sopenharmony_ci enum v4l2_mpeg_video_h264_level level; 6038c2ecf20Sopenharmony_ci dma_addr_t paddr = 0; 6048c2ecf20Sopenharmony_ci u8 *slice_header_vaddr; 6058c2ecf20Sopenharmony_ci u32 frame_width = frame->info.aligned_width; 6068c2ecf20Sopenharmony_ci u32 frame_height = frame->info.aligned_height; 6078c2ecf20Sopenharmony_ci u32 max_cpb_buffer_size; 6088c2ecf20Sopenharmony_ci unsigned int payload = stream->bytesused; 6098c2ecf20Sopenharmony_ci u32 max_bitrate; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci /* check width and height parameters */ 6128c2ecf20Sopenharmony_ci if ((frame_width > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H)) || 6138c2ecf20Sopenharmony_ci (frame_height > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H))) { 6148c2ecf20Sopenharmony_ci dev_err(dev, 6158c2ecf20Sopenharmony_ci "%s width(%d) or height(%d) exceeds limits (%dx%d)\n", 6168c2ecf20Sopenharmony_ci pctx->name, frame_width, frame_height, 6178c2ecf20Sopenharmony_ci H264_MAX_SIZE_W, H264_MAX_SIZE_H); 6188c2ecf20Sopenharmony_ci pctx->frame_errors++; 6198c2ecf20Sopenharmony_ci return -EINVAL; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci level = ctrls->level; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci memset(td, 0, sizeof(struct hva_h264_td)); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci td->frame_width = frame_width; 6278c2ecf20Sopenharmony_ci td->frame_height = frame_height; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci /* set frame alignment */ 6308c2ecf20Sopenharmony_ci td->window_width = frame_width; 6318c2ecf20Sopenharmony_ci td->window_height = frame_height; 6328c2ecf20Sopenharmony_ci td->window_horizontal_offset = 0; 6338c2ecf20Sopenharmony_ci td->window_vertical_offset = 0; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci td->first_picture_in_sequence = (!frame_num) ? 1 : 0; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci /* pic_order_cnt_type hard coded to '2' as only I & P frames */ 6388c2ecf20Sopenharmony_ci td->pic_order_cnt_type = 2; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci /* useConstrainedIntraFlag set to false for better coding efficiency */ 6418c2ecf20Sopenharmony_ci td->use_constrained_intra_flag = false; 6428c2ecf20Sopenharmony_ci td->brc_type = (ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) 6438c2ecf20Sopenharmony_ci ? BRC_TYPE_CBR : BRC_TYPE_VBR; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci td->entropy_coding_mode = (ctrls->entropy_mode == cavlc) ? CAVLC : 6468c2ecf20Sopenharmony_ci CABAC; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci td->bit_rate = ctrls->bitrate; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci /* set framerate, framerate = 1 n/ time per frame */ 6518c2ecf20Sopenharmony_ci if (time_per_frame->numerator >= 536) { 6528c2ecf20Sopenharmony_ci /* 6538c2ecf20Sopenharmony_ci * due to a hardware bug, framerate denominator can't exceed 6548c2ecf20Sopenharmony_ci * 536 (BRC overflow). Compute nearest framerate 6558c2ecf20Sopenharmony_ci */ 6568c2ecf20Sopenharmony_ci td->framerate_den = 1; 6578c2ecf20Sopenharmony_ci td->framerate_num = (time_per_frame->denominator + 6588c2ecf20Sopenharmony_ci (time_per_frame->numerator >> 1) - 1) / 6598c2ecf20Sopenharmony_ci time_per_frame->numerator; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci /* 6628c2ecf20Sopenharmony_ci * update bitrate to introduce a correction due to 6638c2ecf20Sopenharmony_ci * the new framerate 6648c2ecf20Sopenharmony_ci * new bitrate = (old bitrate * new framerate) / old framerate 6658c2ecf20Sopenharmony_ci */ 6668c2ecf20Sopenharmony_ci td->bit_rate /= time_per_frame->numerator; 6678c2ecf20Sopenharmony_ci td->bit_rate *= time_per_frame->denominator; 6688c2ecf20Sopenharmony_ci td->bit_rate /= td->framerate_num; 6698c2ecf20Sopenharmony_ci } else { 6708c2ecf20Sopenharmony_ci td->framerate_den = time_per_frame->numerator; 6718c2ecf20Sopenharmony_ci td->framerate_num = time_per_frame->denominator; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci /* compute maximum bitrate depending on profile */ 6758c2ecf20Sopenharmony_ci if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) 6768c2ecf20Sopenharmony_ci max_bitrate = h264_infos_list[level].max_bitrate * 6778c2ecf20Sopenharmony_ci H264_FACTOR_HIGH; 6788c2ecf20Sopenharmony_ci else 6798c2ecf20Sopenharmony_ci max_bitrate = h264_infos_list[level].max_bitrate * 6808c2ecf20Sopenharmony_ci H264_FACTOR_BASELINE; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci /* check if bitrate doesn't exceed max size */ 6838c2ecf20Sopenharmony_ci if (td->bit_rate > max_bitrate) { 6848c2ecf20Sopenharmony_ci dev_dbg(dev, 6858c2ecf20Sopenharmony_ci "%s bitrate (%d) larger than level and profile allow, clip to %d\n", 6868c2ecf20Sopenharmony_ci pctx->name, td->bit_rate, max_bitrate); 6878c2ecf20Sopenharmony_ci td->bit_rate = max_bitrate; 6888c2ecf20Sopenharmony_ci } 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci /* convert cpb_buffer_size in bits */ 6918c2ecf20Sopenharmony_ci td->cpb_buffer_size = ctrls->cpb_size * 8000; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* compute maximum cpb buffer size depending on profile */ 6948c2ecf20Sopenharmony_ci if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) 6958c2ecf20Sopenharmony_ci max_cpb_buffer_size = 6968c2ecf20Sopenharmony_ci h264_infos_list[level].max_cpb_size * H264_FACTOR_HIGH; 6978c2ecf20Sopenharmony_ci else 6988c2ecf20Sopenharmony_ci max_cpb_buffer_size = 6998c2ecf20Sopenharmony_ci h264_infos_list[level].max_cpb_size * H264_FACTOR_BASELINE; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci /* check if cpb buffer size doesn't exceed max size */ 7028c2ecf20Sopenharmony_ci if (td->cpb_buffer_size > max_cpb_buffer_size) { 7038c2ecf20Sopenharmony_ci dev_dbg(dev, 7048c2ecf20Sopenharmony_ci "%s cpb size larger than level %d allows, clip to %d\n", 7058c2ecf20Sopenharmony_ci pctx->name, td->cpb_buffer_size, max_cpb_buffer_size); 7068c2ecf20Sopenharmony_ci td->cpb_buffer_size = max_cpb_buffer_size; 7078c2ecf20Sopenharmony_ci } 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci /* enable skipping in the Bitrate Controller */ 7108c2ecf20Sopenharmony_ci td->brc_no_skip = 0; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci /* initial delay */ 7138c2ecf20Sopenharmony_ci if ((ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) && 7148c2ecf20Sopenharmony_ci td->bit_rate) 7158c2ecf20Sopenharmony_ci td->delay = 1000 * (td->cpb_buffer_size / td->bit_rate); 7168c2ecf20Sopenharmony_ci else 7178c2ecf20Sopenharmony_ci td->delay = 0; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci switch (frame->info.pixelformat) { 7208c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_NV12: 7218c2ecf20Sopenharmony_ci td->sampling_mode = SAMPLING_MODE_NV12; 7228c2ecf20Sopenharmony_ci break; 7238c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_NV21: 7248c2ecf20Sopenharmony_ci td->sampling_mode = SAMPLING_MODE_NV21; 7258c2ecf20Sopenharmony_ci break; 7268c2ecf20Sopenharmony_ci default: 7278c2ecf20Sopenharmony_ci dev_err(dev, "%s invalid source pixel format\n", 7288c2ecf20Sopenharmony_ci pctx->name); 7298c2ecf20Sopenharmony_ci pctx->frame_errors++; 7308c2ecf20Sopenharmony_ci return -EINVAL; 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci /* 7348c2ecf20Sopenharmony_ci * fill matrix color converter (RGB to YUV) 7358c2ecf20Sopenharmony_ci * Y = 0,299 R + 0,587 G + 0,114 B 7368c2ecf20Sopenharmony_ci * Cb = -0,1687 R -0,3313 G + 0,5 B + 128 7378c2ecf20Sopenharmony_ci * Cr = 0,5 R - 0,4187 G - 0,0813 B + 128 7388c2ecf20Sopenharmony_ci */ 7398c2ecf20Sopenharmony_ci td->rgb2_yuv_y_coeff = 0x12031008; 7408c2ecf20Sopenharmony_ci td->rgb2_yuv_u_coeff = 0x800EF7FB; 7418c2ecf20Sopenharmony_ci td->rgb2_yuv_v_coeff = 0x80FEF40E; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci /* enable/disable transform mode */ 7448c2ecf20Sopenharmony_ci td->transform_mode = ctrls->dct8x8; 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* encoder complexity fix to 2, ENCODE_I_16x16_I_NxN_P_16x16_P_WxH */ 7478c2ecf20Sopenharmony_ci td->encoder_complexity = 2; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci /* quant fix to 28, default VBR value */ 7508c2ecf20Sopenharmony_ci td->quant = 28; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci if (td->framerate_den == 0) { 7538c2ecf20Sopenharmony_ci dev_err(dev, "%s invalid framerate\n", pctx->name); 7548c2ecf20Sopenharmony_ci pctx->frame_errors++; 7558c2ecf20Sopenharmony_ci return -EINVAL; 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci /* if automatic framerate, deactivate bitrate controller */ 7598c2ecf20Sopenharmony_ci if (td->framerate_num == 0) 7608c2ecf20Sopenharmony_ci td->brc_type = 0; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci /* compliancy fix to true */ 7638c2ecf20Sopenharmony_ci td->strict_hrd_compliancy = 1; 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci /* set minimum & maximum quantizers */ 7668c2ecf20Sopenharmony_ci td->qp_min = clamp_val(ctrls->qpmin, 0, 51); 7678c2ecf20Sopenharmony_ci td->qp_max = clamp_val(ctrls->qpmax, 0, 51); 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci td->addr_source_buffer = frame->paddr; 7708c2ecf20Sopenharmony_ci td->addr_fwd_ref_buffer = fwd_ref_frame->paddr; 7718c2ecf20Sopenharmony_ci td->addr_rec_buffer = loc_rec_frame->paddr; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci td->addr_output_bitstream_end = (u32)stream->paddr + stream->size; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci td->addr_output_bitstream_start = (u32)stream->paddr; 7768c2ecf20Sopenharmony_ci td->bitstream_offset = (((u32)stream->paddr & 0xF) << 3) & 7778c2ecf20Sopenharmony_ci BITSTREAM_OFFSET_MASK; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci td->addr_param_out = (u32)ctx->task->paddr + 7808c2ecf20Sopenharmony_ci offsetof(struct hva_h264_task, po); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci /* swap spatial and temporal context */ 7838c2ecf20Sopenharmony_ci if (frame_num % 2) { 7848c2ecf20Sopenharmony_ci paddr = seq_info->paddr; 7858c2ecf20Sopenharmony_ci td->addr_spatial_context = ALIGN(paddr, 0x100); 7868c2ecf20Sopenharmony_ci paddr = seq_info->paddr + DATA_SIZE(frame_width, 7878c2ecf20Sopenharmony_ci frame_height); 7888c2ecf20Sopenharmony_ci td->addr_temporal_context = ALIGN(paddr, 0x100); 7898c2ecf20Sopenharmony_ci } else { 7908c2ecf20Sopenharmony_ci paddr = seq_info->paddr; 7918c2ecf20Sopenharmony_ci td->addr_temporal_context = ALIGN(paddr, 0x100); 7928c2ecf20Sopenharmony_ci paddr = seq_info->paddr + DATA_SIZE(frame_width, 7938c2ecf20Sopenharmony_ci frame_height); 7948c2ecf20Sopenharmony_ci td->addr_spatial_context = ALIGN(paddr, 0x100); 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci paddr = seq_info->paddr + 2 * DATA_SIZE(frame_width, frame_height); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci td->addr_brc_in_out_parameter = ALIGN(paddr, 0x100); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci paddr = td->addr_brc_in_out_parameter + BRC_DATA_SIZE; 8028c2ecf20Sopenharmony_ci td->addr_slice_header = ALIGN(paddr, 0x100); 8038c2ecf20Sopenharmony_ci td->addr_external_sw = ALIGN(addr_esram, 0x100); 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci addr_esram += SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width); 8068c2ecf20Sopenharmony_ci td->addr_local_rec_buffer = ALIGN(addr_esram, 0x100); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci addr_esram += LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width); 8098c2ecf20Sopenharmony_ci td->addr_lctx = ALIGN(addr_esram, 0x100); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci addr_esram += CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height)); 8128c2ecf20Sopenharmony_ci td->addr_cabac_context_buffer = ALIGN(addr_esram, 0x100); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci if (!(frame_num % ctrls->gop_size)) { 8158c2ecf20Sopenharmony_ci td->picture_coding_type = PICTURE_CODING_TYPE_I; 8168c2ecf20Sopenharmony_ci stream->vbuf.flags |= V4L2_BUF_FLAG_KEYFRAME; 8178c2ecf20Sopenharmony_ci } else { 8188c2ecf20Sopenharmony_ci td->picture_coding_type = PICTURE_CODING_TYPE_P; 8198c2ecf20Sopenharmony_ci stream->vbuf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci /* fill the slice header part */ 8238c2ecf20Sopenharmony_ci slice_header_vaddr = seq_info->vaddr + (td->addr_slice_header - 8248c2ecf20Sopenharmony_ci seq_info->paddr); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci hva_h264_fill_slice_header(pctx, slice_header_vaddr, ctrls, frame_num, 8278c2ecf20Sopenharmony_ci &td->slice_header_size_in_bits, 8288c2ecf20Sopenharmony_ci &td->slice_header_offset0, 8298c2ecf20Sopenharmony_ci &td->slice_header_offset1, 8308c2ecf20Sopenharmony_ci &td->slice_header_offset2); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci td->chroma_qp_index_offset = 2; 8338c2ecf20Sopenharmony_ci td->slice_synchro_enable = 0; 8348c2ecf20Sopenharmony_ci td->max_slice_number = 1; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci /* 8378c2ecf20Sopenharmony_ci * check the sps/pps header size for key frame only 8388c2ecf20Sopenharmony_ci * sps/pps header was previously fill by libv4l 8398c2ecf20Sopenharmony_ci * during qbuf of stream buffer 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_ci if ((stream->vbuf.flags == V4L2_BUF_FLAG_KEYFRAME) && 8428c2ecf20Sopenharmony_ci (payload > MAX_SPS_PPS_SIZE)) { 8438c2ecf20Sopenharmony_ci dev_err(dev, "%s invalid sps/pps size %d\n", pctx->name, 8448c2ecf20Sopenharmony_ci payload); 8458c2ecf20Sopenharmony_ci pctx->frame_errors++; 8468c2ecf20Sopenharmony_ci return -EINVAL; 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci if (stream->vbuf.flags != V4L2_BUF_FLAG_KEYFRAME) 8508c2ecf20Sopenharmony_ci payload = 0; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci /* add SEI nal (video stereo info) */ 8538c2ecf20Sopenharmony_ci if (ctrls->sei_fp && hva_h264_fill_sei_nal(pctx, SEI_STEREO_VIDEO_INFO, 8548c2ecf20Sopenharmony_ci (u8 *)stream->vaddr, 8558c2ecf20Sopenharmony_ci &payload)) { 8568c2ecf20Sopenharmony_ci dev_err(dev, "%s fail to get SEI nal\n", pctx->name); 8578c2ecf20Sopenharmony_ci pctx->frame_errors++; 8588c2ecf20Sopenharmony_ci return -EINVAL; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci /* fill size of non-VCL NAL units (SPS, PPS, filler and SEI) */ 8628c2ecf20Sopenharmony_ci td->non_vcl_nalu_size = payload * 8; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci /* compute bitstream offset & new start address of bitstream */ 8658c2ecf20Sopenharmony_ci td->addr_output_bitstream_start += ((payload >> 4) << 4); 8668c2ecf20Sopenharmony_ci td->bitstream_offset += (payload - ((payload >> 4) << 4)) * 8; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci stream->bytesused = payload; 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci return 0; 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_cistatic unsigned int hva_h264_get_stream_size(struct hva_h264_task *task) 8748c2ecf20Sopenharmony_ci{ 8758c2ecf20Sopenharmony_ci struct hva_h264_po *po = &task->po; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci return po->bitstream_size; 8788c2ecf20Sopenharmony_ci} 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_cistatic u32 hva_h264_get_stuffing_bytes(struct hva_h264_task *task) 8818c2ecf20Sopenharmony_ci{ 8828c2ecf20Sopenharmony_ci struct hva_h264_po *po = &task->po; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci return po->stuffing_bits >> 3; 8858c2ecf20Sopenharmony_ci} 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_cistatic int hva_h264_open(struct hva_ctx *pctx) 8888c2ecf20Sopenharmony_ci{ 8898c2ecf20Sopenharmony_ci struct device *dev = ctx_to_dev(pctx); 8908c2ecf20Sopenharmony_ci struct hva_h264_ctx *ctx; 8918c2ecf20Sopenharmony_ci struct hva_dev *hva = ctx_to_hdev(pctx); 8928c2ecf20Sopenharmony_ci u32 frame_width = pctx->frameinfo.aligned_width; 8938c2ecf20Sopenharmony_ci u32 frame_height = pctx->frameinfo.aligned_height; 8948c2ecf20Sopenharmony_ci u32 size; 8958c2ecf20Sopenharmony_ci int ret; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* check esram size necessary to encode a frame */ 8988c2ecf20Sopenharmony_ci size = SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width) + 8998c2ecf20Sopenharmony_ci LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width) + 9008c2ecf20Sopenharmony_ci CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height)) + 9018c2ecf20Sopenharmony_ci CABAC_CONTEXT_BUFFER_MAX_SIZE(frame_width); 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci if (hva->esram_size < size) { 9048c2ecf20Sopenharmony_ci dev_err(dev, "%s not enough esram (max:%d request:%d)\n", 9058c2ecf20Sopenharmony_ci pctx->name, hva->esram_size, size); 9068c2ecf20Sopenharmony_ci ret = -EINVAL; 9078c2ecf20Sopenharmony_ci goto err; 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci /* allocate context for codec */ 9118c2ecf20Sopenharmony_ci ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 9128c2ecf20Sopenharmony_ci if (!ctx) { 9138c2ecf20Sopenharmony_ci ret = -ENOMEM; 9148c2ecf20Sopenharmony_ci goto err; 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci /* allocate sequence info buffer */ 9188c2ecf20Sopenharmony_ci ret = hva_mem_alloc(pctx, 9198c2ecf20Sopenharmony_ci 2 * DATA_SIZE(frame_width, frame_height) + 9208c2ecf20Sopenharmony_ci SLICE_HEADER_SIZE + 9218c2ecf20Sopenharmony_ci BRC_DATA_SIZE, 9228c2ecf20Sopenharmony_ci "hva sequence info", 9238c2ecf20Sopenharmony_ci &ctx->seq_info); 9248c2ecf20Sopenharmony_ci if (ret) { 9258c2ecf20Sopenharmony_ci dev_err(dev, 9268c2ecf20Sopenharmony_ci "%s failed to allocate sequence info buffer\n", 9278c2ecf20Sopenharmony_ci pctx->name); 9288c2ecf20Sopenharmony_ci goto err_ctx; 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci /* allocate reference frame buffer */ 9328c2ecf20Sopenharmony_ci ret = hva_mem_alloc(pctx, 9338c2ecf20Sopenharmony_ci frame_width * frame_height * 3 / 2, 9348c2ecf20Sopenharmony_ci "hva reference frame", 9358c2ecf20Sopenharmony_ci &ctx->ref_frame); 9368c2ecf20Sopenharmony_ci if (ret) { 9378c2ecf20Sopenharmony_ci dev_err(dev, "%s failed to allocate reference frame buffer\n", 9388c2ecf20Sopenharmony_ci pctx->name); 9398c2ecf20Sopenharmony_ci goto err_seq_info; 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci /* allocate reconstructed frame buffer */ 9438c2ecf20Sopenharmony_ci ret = hva_mem_alloc(pctx, 9448c2ecf20Sopenharmony_ci frame_width * frame_height * 3 / 2, 9458c2ecf20Sopenharmony_ci "hva reconstructed frame", 9468c2ecf20Sopenharmony_ci &ctx->rec_frame); 9478c2ecf20Sopenharmony_ci if (ret) { 9488c2ecf20Sopenharmony_ci dev_err(dev, 9498c2ecf20Sopenharmony_ci "%s failed to allocate reconstructed frame buffer\n", 9508c2ecf20Sopenharmony_ci pctx->name); 9518c2ecf20Sopenharmony_ci goto err_ref_frame; 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci /* allocate task descriptor */ 9558c2ecf20Sopenharmony_ci ret = hva_mem_alloc(pctx, 9568c2ecf20Sopenharmony_ci sizeof(struct hva_h264_task), 9578c2ecf20Sopenharmony_ci "hva task descriptor", 9588c2ecf20Sopenharmony_ci &ctx->task); 9598c2ecf20Sopenharmony_ci if (ret) { 9608c2ecf20Sopenharmony_ci dev_err(dev, 9618c2ecf20Sopenharmony_ci "%s failed to allocate task descriptor\n", 9628c2ecf20Sopenharmony_ci pctx->name); 9638c2ecf20Sopenharmony_ci goto err_rec_frame; 9648c2ecf20Sopenharmony_ci } 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci pctx->priv = (void *)ctx; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci return 0; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_cierr_rec_frame: 9718c2ecf20Sopenharmony_ci hva_mem_free(pctx, ctx->rec_frame); 9728c2ecf20Sopenharmony_cierr_ref_frame: 9738c2ecf20Sopenharmony_ci hva_mem_free(pctx, ctx->ref_frame); 9748c2ecf20Sopenharmony_cierr_seq_info: 9758c2ecf20Sopenharmony_ci hva_mem_free(pctx, ctx->seq_info); 9768c2ecf20Sopenharmony_cierr_ctx: 9778c2ecf20Sopenharmony_ci devm_kfree(dev, ctx); 9788c2ecf20Sopenharmony_cierr: 9798c2ecf20Sopenharmony_ci pctx->sys_errors++; 9808c2ecf20Sopenharmony_ci return ret; 9818c2ecf20Sopenharmony_ci} 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_cistatic int hva_h264_close(struct hva_ctx *pctx) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; 9868c2ecf20Sopenharmony_ci struct device *dev = ctx_to_dev(pctx); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci if (ctx->seq_info) 9898c2ecf20Sopenharmony_ci hva_mem_free(pctx, ctx->seq_info); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (ctx->ref_frame) 9928c2ecf20Sopenharmony_ci hva_mem_free(pctx, ctx->ref_frame); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci if (ctx->rec_frame) 9958c2ecf20Sopenharmony_ci hva_mem_free(pctx, ctx->rec_frame); 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci if (ctx->task) 9988c2ecf20Sopenharmony_ci hva_mem_free(pctx, ctx->task); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci devm_kfree(dev, ctx); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci return 0; 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_cistatic int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame, 10068c2ecf20Sopenharmony_ci struct hva_stream *stream) 10078c2ecf20Sopenharmony_ci{ 10088c2ecf20Sopenharmony_ci struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; 10098c2ecf20Sopenharmony_ci struct hva_h264_task *task = (struct hva_h264_task *)ctx->task->vaddr; 10108c2ecf20Sopenharmony_ci u32 stuffing_bytes = 0; 10118c2ecf20Sopenharmony_ci int ret = 0; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci ret = hva_h264_prepare_task(pctx, task, frame, stream); 10148c2ecf20Sopenharmony_ci if (ret) 10158c2ecf20Sopenharmony_ci goto err; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci ret = hva_hw_execute_task(pctx, H264_ENC, ctx->task); 10188c2ecf20Sopenharmony_ci if (ret) 10198c2ecf20Sopenharmony_ci goto err; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci pctx->stream_num++; 10228c2ecf20Sopenharmony_ci stream->bytesused += hva_h264_get_stream_size(task); 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci stuffing_bytes = hva_h264_get_stuffing_bytes(task); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci if (stuffing_bytes) 10278c2ecf20Sopenharmony_ci hva_h264_fill_data_nal(pctx, stuffing_bytes, 10288c2ecf20Sopenharmony_ci (u8 *)stream->vaddr, 10298c2ecf20Sopenharmony_ci stream->size, 10308c2ecf20Sopenharmony_ci &stream->bytesused); 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci /* switch reference & reconstructed frame */ 10338c2ecf20Sopenharmony_ci swap(ctx->ref_frame, ctx->rec_frame); 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci return 0; 10368c2ecf20Sopenharmony_cierr: 10378c2ecf20Sopenharmony_ci stream->bytesused = 0; 10388c2ecf20Sopenharmony_ci return ret; 10398c2ecf20Sopenharmony_ci} 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ciconst struct hva_enc nv12h264enc = { 10428c2ecf20Sopenharmony_ci .name = "H264(NV12)", 10438c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_NV12, 10448c2ecf20Sopenharmony_ci .streamformat = V4L2_PIX_FMT_H264, 10458c2ecf20Sopenharmony_ci .max_width = H264_MAX_SIZE_W, 10468c2ecf20Sopenharmony_ci .max_height = H264_MAX_SIZE_H, 10478c2ecf20Sopenharmony_ci .open = hva_h264_open, 10488c2ecf20Sopenharmony_ci .close = hva_h264_close, 10498c2ecf20Sopenharmony_ci .encode = hva_h264_encode, 10508c2ecf20Sopenharmony_ci}; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ciconst struct hva_enc nv21h264enc = { 10538c2ecf20Sopenharmony_ci .name = "H264(NV21)", 10548c2ecf20Sopenharmony_ci .pixelformat = V4L2_PIX_FMT_NV21, 10558c2ecf20Sopenharmony_ci .streamformat = V4L2_PIX_FMT_H264, 10568c2ecf20Sopenharmony_ci .max_width = H264_MAX_SIZE_W, 10578c2ecf20Sopenharmony_ci .max_height = H264_MAX_SIZE_H, 10588c2ecf20Sopenharmony_ci .open = hva_h264_open, 10598c2ecf20Sopenharmony_ci .close = hva_h264_close, 10608c2ecf20Sopenharmony_ci .encode = hva_h264_encode, 10618c2ecf20Sopenharmony_ci}; 1062