diff options
author | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-03-14 12:43:10 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@kernel.org> | 2022-03-18 05:58:34 +0100 |
commit | e7b8153e2a4f0c9c8d1450aa7328d54ea64fe8b2 (patch) | |
tree | 66b31cbad2bcee3f115a8c910cfebefcb9f4e048 /drivers/media/platform/sti/hva/hva-h264.c | |
parent | media: platform: rename s5p-mfc/ to samsung/s5p-mfc/ (diff) | |
download | linux-dev-e7b8153e2a4f0c9c8d1450aa7328d54ea64fe8b2.tar.xz linux-dev-e7b8153e2a4f0c9c8d1450aa7328d54ea64fe8b2.zip |
media: platform: place stm32/ and sti/ under st/ dir
As the end goal is to have platform drivers split by vendor,
move both stm32/ and sti/ for them to be inside st/ directory.
Acked-by: Hugues Fruchet <hugues.fruchet@st.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers/media/platform/sti/hva/hva-h264.c')
-rw-r--r-- | drivers/media/platform/sti/hva/hva-h264.c | 1063 |
1 files changed, 0 insertions, 1063 deletions
diff --git a/drivers/media/platform/sti/hva/hva-h264.c b/drivers/media/platform/sti/hva/hva-h264.c deleted file mode 100644 index 98cb00d2d868..000000000000 --- a/drivers/media/platform/sti/hva/hva-h264.c +++ /dev/null @@ -1,1063 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) STMicroelectronics SA 2015 - * Authors: Yannick Fertre <yannick.fertre@st.com> - * Hugues Fruchet <hugues.fruchet@st.com> - */ - -#include "hva.h" -#include "hva-hw.h" - -#define MAX_SPS_PPS_SIZE 128 - -#define BITSTREAM_OFFSET_MASK 0x7F - -/* video max size*/ -#define H264_MAX_SIZE_W 1920 -#define H264_MAX_SIZE_H 1920 - -/* macroBlocs number (width & height) */ -#define MB_W(w) ((w + 0xF) / 0x10) -#define MB_H(h) ((h + 0xF) / 0x10) - -/* formula to get temporal or spatial data size */ -#define DATA_SIZE(w, h) (MB_W(w) * MB_H(h) * 16) - -#define SEARCH_WINDOW_BUFFER_MAX_SIZE(w) ((4 * MB_W(w) + 42) * 256 * 3 / 2) -#define CABAC_CONTEXT_BUFFER_MAX_SIZE(w) (MB_W(w) * 16) -#define CTX_MB_BUFFER_MAX_SIZE(w) (MB_W(w) * 16 * 8) -#define SLICE_HEADER_SIZE (4 * 16) -#define BRC_DATA_SIZE (5 * 16) - -/* source buffer copy in YUV 420 MB-tiled format with size=16*256*3/2 */ -#define CURRENT_WINDOW_BUFFER_MAX_SIZE (16 * 256 * 3 / 2) - -/* - * 4 lines of pixels (in Luma, Chroma blue and Chroma red) of top MB - * for deblocking with size=4*16*MBx*2 - */ -#define LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(w) (4 * 16 * MB_W(w) * 2) - -/* factor for bitrate and cpb buffer size max values if profile >= high */ -#define H264_FACTOR_HIGH 1200 - -/* factor for bitrate and cpb buffer size max values if profile < high */ -#define H264_FACTOR_BASELINE 1000 - -/* number of bytes for NALU_TYPE_FILLER_DATA header and footer */ -#define H264_FILLER_DATA_SIZE 6 - -struct h264_profile { - enum v4l2_mpeg_video_h264_level level; - u32 max_mb_per_seconds; - u32 max_frame_size; - u32 max_bitrate; - u32 max_cpb_size; - u32 min_comp_ratio; -}; - -static const struct h264_profile h264_infos_list[] = { - {V4L2_MPEG_VIDEO_H264_LEVEL_1_0, 1485, 99, 64, 175, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_1B, 1485, 99, 128, 350, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_1_1, 3000, 396, 192, 500, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_1_2, 6000, 396, 384, 1000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_1_3, 11880, 396, 768, 2000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_2_0, 11880, 396, 2000, 2000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_2_1, 19800, 792, 4000, 4000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_2_2, 20250, 1620, 4000, 4000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_3_0, 40500, 1620, 10000, 10000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_3_1, 108000, 3600, 14000, 14000, 4}, - {V4L2_MPEG_VIDEO_H264_LEVEL_3_2, 216000, 5120, 20000, 20000, 4}, - {V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 245760, 8192, 20000, 25000, 4}, - {V4L2_MPEG_VIDEO_H264_LEVEL_4_1, 245760, 8192, 50000, 62500, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_4_2, 522240, 8704, 50000, 62500, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_5_0, 589824, 22080, 135000, 135000, 2}, - {V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 983040, 36864, 240000, 240000, 2} -}; - -enum hva_brc_type { - BRC_TYPE_NONE = 0, - BRC_TYPE_CBR = 1, - BRC_TYPE_VBR = 2, - BRC_TYPE_VBR_LOW_DELAY = 3 -}; - -enum hva_entropy_coding_mode { - CAVLC = 0, - CABAC = 1 -}; - -enum hva_picture_coding_type { - PICTURE_CODING_TYPE_I = 0, - PICTURE_CODING_TYPE_P = 1, - PICTURE_CODING_TYPE_B = 2 -}; - -enum hva_h264_sampling_mode { - SAMPLING_MODE_NV12 = 0, - SAMPLING_MODE_UYVY = 1, - SAMPLING_MODE_RGB3 = 3, - SAMPLING_MODE_XRGB4 = 4, - SAMPLING_MODE_NV21 = 8, - SAMPLING_MODE_VYUY = 9, - SAMPLING_MODE_BGR3 = 11, - SAMPLING_MODE_XBGR4 = 12, - SAMPLING_MODE_RGBX4 = 20, - SAMPLING_MODE_BGRX4 = 28 -}; - -enum hva_h264_nalu_type { - NALU_TYPE_UNKNOWN = 0, - NALU_TYPE_SLICE = 1, - NALU_TYPE_SLICE_DPA = 2, - NALU_TYPE_SLICE_DPB = 3, - NALU_TYPE_SLICE_DPC = 4, - NALU_TYPE_SLICE_IDR = 5, - NALU_TYPE_SEI = 6, - NALU_TYPE_SPS = 7, - NALU_TYPE_PPS = 8, - NALU_TYPE_AU_DELIMITER = 9, - NALU_TYPE_SEQ_END = 10, - NALU_TYPE_STREAM_END = 11, - NALU_TYPE_FILLER_DATA = 12, - NALU_TYPE_SPS_EXT = 13, - NALU_TYPE_PREFIX_UNIT = 14, - NALU_TYPE_SUBSET_SPS = 15, - NALU_TYPE_SLICE_AUX = 19, - NALU_TYPE_SLICE_EXT = 20 -}; - -enum hva_h264_sei_payload_type { - SEI_BUFFERING_PERIOD = 0, - SEI_PICTURE_TIMING = 1, - SEI_STEREO_VIDEO_INFO = 21, - SEI_FRAME_PACKING_ARRANGEMENT = 45 -}; - -/* - * stereo Video Info struct - */ -struct hva_h264_stereo_video_sei { - u8 field_views_flag; - u8 top_field_is_left_view_flag; - u8 current_frame_is_left_view_flag; - u8 next_frame_is_second_view_flag; - u8 left_view_self_contained_flag; - u8 right_view_self_contained_flag; -}; - -/* - * struct hva_h264_td - * - * @frame_width: width in pixels of the buffer containing the input frame - * @frame_height: height in pixels of the buffer containing the input frame - * @frame_num: the parameter to be written in the slice header - * @picture_coding_type: type I, P or B - * @pic_order_cnt_type: POC mode, as defined in H264 std : can be 0,1,2 - * @first_picture_in_sequence: flag telling to encoder that this is the - * first picture in a video sequence. - * Used for VBR - * @slice_size_type: 0 = no constraint to close the slice - * 1= a slice is closed as soon as the slice_mb_size limit - * is reached - * 2= a slice is closed as soon as the slice_byte_size limit - * is reached - * 3= a slice is closed as soon as either the slice_byte_size - * limit or the slice_mb_size limit is reached - * @slice_mb_size: defines the slice size in number of macroblocks - * (used when slice_size_type=1 or slice_size_type=3) - * @ir_param_option: defines the number of macroblocks per frame to be - * refreshed by AIR algorithm OR the refresh period - * by CIR algorithm - * @intra_refresh_type: enables the adaptive intra refresh algorithm. - * Disable=0 / Adaptative=1 and Cycle=2 as intra refresh - * @use_constrained_intra_flag: constrained_intra_pred_flag from PPS - * @transform_mode: controls the use of 4x4/8x8 transform mode - * @disable_deblocking_filter_idc: - * 0: specifies that all luma and chroma block edges of - * the slice are filtered. - * 1: specifies that deblocking is disabled for all block - * edges of the slice. - * 2: specifies that all luma and chroma block edges of - * the slice are filtered with exception of the block edges - * that coincide with slice boundaries - * @slice_alpha_c0_offset_div2: to be written in slice header, - * controls deblocking - * @slice_beta_offset_div2: to be written in slice header, - * controls deblocking - * @encoder_complexity: encoder complexity control (IME). - * 0 = I_16x16, P_16x16, Full ME Complexity - * 1 = I_16x16, I_NxN, P_16x16, Full ME Complexity - * 2 = I_16x16, I_NXN, P_16x16, P_WxH, Full ME Complexity - * 4 = I_16x16, P_16x16, Reduced ME Complexity - * 5 = I_16x16, I_NxN, P_16x16, Reduced ME Complexity - * 6 = I_16x16, I_NXN, P_16x16, P_WxH, Reduced ME Complexity - * @chroma_qp_index_offset: coming from picture parameter set - * (PPS see [H.264 STD] 7.4.2.2) - * @entropy_coding_mode: entropy coding mode. - * 0 = CAVLC - * 1 = CABAC - * @brc_type: selects the bit-rate control algorithm - * 0 = constant Qp, (no BRC) - * 1 = CBR - * 2 = VBR - * @quant: Quantization param used in case of fix QP encoding (no BRC) - * @non_VCL_NALU_Size: size of non-VCL NALUs (SPS, PPS, filler), - * used by BRC - * @cpb_buffer_size: size of Coded Picture Buffer, used by BRC - * @bit_rate: target bitrate, for BRC - * @qp_min: min QP threshold - * @qp_max: max QP threshold - * @framerate_num: target framerate numerator , used by BRC - * @framerate_den: target framerate denomurator , used by BRC - * @delay: End-to-End Initial Delay - * @strict_HRD_compliancy: flag for HDR compliancy (1) - * May impact quality encoding - * @addr_source_buffer: address of input frame buffer for current frame - * @addr_fwd_Ref_Buffer: address of reference frame buffer - * @addr_rec_buffer: address of reconstructed frame buffer - * @addr_output_bitstream_start: output bitstream start address - * @addr_output_bitstream_end: output bitstream end address - * @addr_external_sw : address of external search window - * @addr_lctx : address of context picture buffer - * @addr_local_rec_buffer: address of local reconstructed buffer - * @addr_spatial_context: address of spatial context buffer - * @bitstream_offset: offset in bits between aligned bitstream start - * address and first bit to be written by HVA. - * Range value is [0..63] - * @sampling_mode: Input picture format . - * 0: YUV420 semi_planar Interleaved - * 1: YUV422 raster Interleaved - * @addr_param_out: address of output parameters structure - * @addr_scaling_matrix: address to the coefficient of - * the inverse scaling matrix - * @addr_scaling_matrix_dir: address to the coefficient of - * the direct scaling matrix - * @addr_cabac_context_buffer: address of cabac context buffer - * @GmvX: Input information about the horizontal global displacement of - * the encoded frame versus the previous one - * @GmvY: Input information about the vertical global displacement of - * the encoded frame versus the previous one - * @window_width: width in pixels of the window to be encoded inside - * the input frame - * @window_height: width in pixels of the window to be encoded inside - * the input frame - * @window_horizontal_offset: horizontal offset in pels for input window - * within input frame - * @window_vertical_offset: vertical offset in pels for input window - * within input frame - * @addr_roi: Map of QP offset for the Region of Interest algorithm and - * also used for Error map. - * Bit 0-6 used for qp offset (value -64 to 63). - * Bit 7 used to force intra - * @addr_slice_header: address to slice header - * @slice_header_size_in_bits: size in bits of the Slice header - * @slice_header_offset0: Slice header offset where to insert - * first_Mb_in_slice - * @slice_header_offset1: Slice header offset where to insert - * slice_qp_delta - * @slice_header_offset2: Slice header offset where to insert - * num_MBs_in_slice - * @slice_synchro_enable: enable "slice ready" interrupt after each slice - * @max_slice_number: Maximum number of slice in a frame - * (0 is strictly forbidden) - * @rgb2_yuv_y_coeff: Four coefficients (C0C1C2C3) to convert from RGB to - * YUV for the Y component. - * Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) - * @rgb2_yuv_u_coeff: four coefficients (C0C1C2C3) to convert from RGB to - * YUV for the Y component. - * Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) - * @rgb2_yuv_v_coeff: Four coefficients (C0C1C2C3) to convert from RGB to - * YUV for the U (Cb) component. - * U = C0*R + C1*G + C2*B + C3 (C0 is on byte 0) - * @slice_byte_size: maximum slice size in bytes - * (used when slice_size_type=2 or slice_size_type=3) - * @max_air_intra_mb_nb: Maximum number of intra macroblock in a frame - * for the AIR algorithm - * @brc_no_skip: Disable skipping in the Bitrate Controller - * @addr_brc_in_out_parameter: address of static buffer for BRC parameters - */ -struct hva_h264_td { - u16 frame_width; - u16 frame_height; - u32 frame_num; - u16 picture_coding_type; - u16 reserved1; - u16 pic_order_cnt_type; - u16 first_picture_in_sequence; - u16 slice_size_type; - u16 reserved2; - u32 slice_mb_size; - u16 ir_param_option; - u16 intra_refresh_type; - u16 use_constrained_intra_flag; - u16 transform_mode; - u16 disable_deblocking_filter_idc; - s16 slice_alpha_c0_offset_div2; - s16 slice_beta_offset_div2; - u16 encoder_complexity; - s16 chroma_qp_index_offset; - u16 entropy_coding_mode; - u16 brc_type; - u16 quant; - u32 non_vcl_nalu_size; - u32 cpb_buffer_size; - u32 bit_rate; - u16 qp_min; - u16 qp_max; - u16 framerate_num; - u16 framerate_den; - u16 delay; - u16 strict_hrd_compliancy; - u32 addr_source_buffer; - u32 addr_fwd_ref_buffer; - u32 addr_rec_buffer; - u32 addr_output_bitstream_start; - u32 addr_output_bitstream_end; - u32 addr_external_sw; - u32 addr_lctx; - u32 addr_local_rec_buffer; - u32 addr_spatial_context; - u16 bitstream_offset; - u16 sampling_mode; - u32 addr_param_out; - u32 addr_scaling_matrix; - u32 addr_scaling_matrix_dir; - u32 addr_cabac_context_buffer; - u32 reserved3; - u32 reserved4; - s16 gmv_x; - s16 gmv_y; - u16 window_width; - u16 window_height; - u16 window_horizontal_offset; - u16 window_vertical_offset; - u32 addr_roi; - u32 addr_slice_header; - u16 slice_header_size_in_bits; - u16 slice_header_offset0; - u16 slice_header_offset1; - u16 slice_header_offset2; - u32 reserved5; - u32 reserved6; - u16 reserved7; - u16 reserved8; - u16 slice_synchro_enable; - u16 max_slice_number; - u32 rgb2_yuv_y_coeff; - u32 rgb2_yuv_u_coeff; - u32 rgb2_yuv_v_coeff; - u32 slice_byte_size; - u16 max_air_intra_mb_nb; - u16 brc_no_skip; - u32 addr_temporal_context; - u32 addr_brc_in_out_parameter; -}; - -/* - * struct hva_h264_slice_po - * - * @ slice_size: slice size - * @ slice_start_time: start time - * @ slice_stop_time: stop time - * @ slice_num: slice number - */ -struct hva_h264_slice_po { - u32 slice_size; - u32 slice_start_time; - u32 slice_end_time; - u32 slice_num; -}; - -/* - * struct hva_h264_po - * - * @ bitstream_size: bitstream size - * @ dct_bitstream_size: dtc bitstream size - * @ stuffing_bits: number of stuffing bits inserted by the encoder - * @ removal_time: removal time of current frame (nb of ticks 1/framerate) - * @ hvc_start_time: hvc start time - * @ hvc_stop_time: hvc stop time - * @ slice_count: slice count - */ -struct hva_h264_po { - u32 bitstream_size; - u32 dct_bitstream_size; - u32 stuffing_bits; - u32 removal_time; - u32 hvc_start_time; - u32 hvc_stop_time; - u32 slice_count; - u32 reserved0; - struct hva_h264_slice_po slice_params[16]; -}; - -struct hva_h264_task { - struct hva_h264_td td; - struct hva_h264_po po; -}; - -/* - * struct hva_h264_ctx - * - * @seq_info: sequence information buffer - * @ref_frame: reference frame buffer - * @rec_frame: reconstructed frame buffer - * @task: task descriptor - */ -struct hva_h264_ctx { - struct hva_buffer *seq_info; - struct hva_buffer *ref_frame; - struct hva_buffer *rec_frame; - struct hva_buffer *task; -}; - -static int hva_h264_fill_slice_header(struct hva_ctx *pctx, - u8 *slice_header_addr, - struct hva_controls *ctrls, - int frame_num, - u16 *header_size, - u16 *header_offset0, - u16 *header_offset1, - u16 *header_offset2) -{ - /* - * with this HVA hardware version, part of the slice header is computed - * on host and part by hardware. - * The part of host is precomputed and available through this array. - */ - struct device *dev = ctx_to_dev(pctx); - int cabac = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC; - static const unsigned char slice_header[] = { - 0x00, 0x00, 0x00, 0x01, - 0x41, 0x34, 0x07, 0x00 - }; - int idr_pic_id = frame_num % 2; - enum hva_picture_coding_type type; - u32 frame_order = frame_num % ctrls->gop_size; - - if (!(frame_num % ctrls->gop_size)) - type = PICTURE_CODING_TYPE_I; - else - type = PICTURE_CODING_TYPE_P; - - memcpy(slice_header_addr, slice_header, sizeof(slice_header)); - - *header_size = 56; - *header_offset0 = 40; - *header_offset1 = 13; - *header_offset2 = 0; - - if (type == PICTURE_CODING_TYPE_I) { - slice_header_addr[4] = 0x65; - slice_header_addr[5] = 0x11; - - /* toggle the I frame */ - if ((frame_num / ctrls->gop_size) % 2) { - *header_size += 4; - *header_offset1 += 4; - slice_header_addr[6] = 0x04; - slice_header_addr[7] = 0x70; - - } else { - *header_size += 2; - *header_offset1 += 2; - slice_header_addr[6] = 0x09; - slice_header_addr[7] = 0xC0; - } - } else { - if (ctrls->entropy_mode == cabac) { - *header_size += 1; - *header_offset1 += 1; - slice_header_addr[7] = 0x80; - } - /* - * update slice header with P frame order - * frame order is limited to 16 (coded on 4bits only) - */ - slice_header_addr[5] += ((frame_order & 0x0C) >> 2); - slice_header_addr[6] += ((frame_order & 0x03) << 6); - } - - dev_dbg(dev, - "%s %s slice header order %d idrPicId %d header size %d\n", - pctx->name, __func__, frame_order, idr_pic_id, *header_size); - return 0; -} - -static int hva_h264_fill_data_nal(struct hva_ctx *pctx, - unsigned int stuffing_bytes, u8 *addr, - unsigned int stream_size, unsigned int *size) -{ - struct device *dev = ctx_to_dev(pctx); - static const u8 start[] = { 0x00, 0x00, 0x00, 0x01 }; - - dev_dbg(dev, "%s %s stuffing bytes %d\n", pctx->name, __func__, - stuffing_bytes); - - if ((*size + stuffing_bytes + H264_FILLER_DATA_SIZE) > stream_size) { - dev_dbg(dev, "%s %s too many stuffing bytes %d\n", - pctx->name, __func__, stuffing_bytes); - return 0; - } - - /* start code */ - memcpy(addr + *size, start, sizeof(start)); - *size += sizeof(start); - - /* nal_unit_type */ - addr[*size] = NALU_TYPE_FILLER_DATA; - *size += 1; - - memset(addr + *size, 0xff, stuffing_bytes); - *size += stuffing_bytes; - - addr[*size] = 0x80; - *size += 1; - - return 0; -} - -static int hva_h264_fill_sei_nal(struct hva_ctx *pctx, - enum hva_h264_sei_payload_type type, - u8 *addr, u32 *size) -{ - struct device *dev = ctx_to_dev(pctx); - static const u8 start[] = { 0x00, 0x00, 0x00, 0x01 }; - struct hva_h264_stereo_video_sei info; - u8 offset = 7; - u8 msg = 0; - - /* start code */ - memcpy(addr + *size, start, sizeof(start)); - *size += sizeof(start); - - /* nal_unit_type */ - addr[*size] = NALU_TYPE_SEI; - *size += 1; - - /* payload type */ - addr[*size] = type; - *size += 1; - - switch (type) { - case SEI_STEREO_VIDEO_INFO: - memset(&info, 0, sizeof(info)); - - /* set to top/bottom frame packing arrangement */ - info.field_views_flag = 1; - info.top_field_is_left_view_flag = 1; - - /* payload size */ - addr[*size] = 1; - *size += 1; - - /* payload */ - msg = info.field_views_flag << offset--; - - if (info.field_views_flag) { - msg |= info.top_field_is_left_view_flag << - offset--; - } else { - msg |= info.current_frame_is_left_view_flag << - offset--; - msg |= info.next_frame_is_second_view_flag << - offset--; - } - msg |= info.left_view_self_contained_flag << offset--; - msg |= info.right_view_self_contained_flag << offset--; - - addr[*size] = msg; - *size += 1; - - addr[*size] = 0x80; - *size += 1; - - return 0; - case SEI_BUFFERING_PERIOD: - case SEI_PICTURE_TIMING: - case SEI_FRAME_PACKING_ARRANGEMENT: - default: - dev_err(dev, "%s sei nal type not supported %d\n", - pctx->name, type); - return -EINVAL; - } -} - -static int hva_h264_prepare_task(struct hva_ctx *pctx, - struct hva_h264_task *task, - struct hva_frame *frame, - struct hva_stream *stream) -{ - struct hva_dev *hva = ctx_to_hdev(pctx); - struct device *dev = ctx_to_dev(pctx); - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; - struct hva_buffer *seq_info = ctx->seq_info; - struct hva_buffer *fwd_ref_frame = ctx->ref_frame; - struct hva_buffer *loc_rec_frame = ctx->rec_frame; - struct hva_h264_td *td = &task->td; - struct hva_controls *ctrls = &pctx->ctrls; - struct v4l2_fract *time_per_frame = &pctx->ctrls.time_per_frame; - int cavlc = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; - u32 frame_num = pctx->stream_num; - u32 addr_esram = hva->esram_addr; - enum v4l2_mpeg_video_h264_level level; - dma_addr_t paddr = 0; - u8 *slice_header_vaddr; - u32 frame_width = frame->info.aligned_width; - u32 frame_height = frame->info.aligned_height; - u32 max_cpb_buffer_size; - unsigned int payload = stream->bytesused; - u32 max_bitrate; - - /* check width and height parameters */ - if ((frame_width > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H)) || - (frame_height > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H))) { - dev_err(dev, - "%s width(%d) or height(%d) exceeds limits (%dx%d)\n", - pctx->name, frame_width, frame_height, - H264_MAX_SIZE_W, H264_MAX_SIZE_H); - pctx->frame_errors++; - return -EINVAL; - } - - level = ctrls->level; - - memset(td, 0, sizeof(struct hva_h264_td)); - - td->frame_width = frame_width; - td->frame_height = frame_height; - - /* set frame alignment */ - td->window_width = frame_width; - td->window_height = frame_height; - td->window_horizontal_offset = 0; - td->window_vertical_offset = 0; - - td->first_picture_in_sequence = (!frame_num) ? 1 : 0; - - /* pic_order_cnt_type hard coded to '2' as only I & P frames */ - td->pic_order_cnt_type = 2; - - /* useConstrainedIntraFlag set to false for better coding efficiency */ - td->use_constrained_intra_flag = false; - td->brc_type = (ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) - ? BRC_TYPE_CBR : BRC_TYPE_VBR; - - td->entropy_coding_mode = (ctrls->entropy_mode == cavlc) ? CAVLC : - CABAC; - - td->bit_rate = ctrls->bitrate; - - /* set framerate, framerate = 1 n/ time per frame */ - if (time_per_frame->numerator >= 536) { - /* - * due to a hardware bug, framerate denominator can't exceed - * 536 (BRC overflow). Compute nearest framerate - */ - td->framerate_den = 1; - td->framerate_num = (time_per_frame->denominator + - (time_per_frame->numerator >> 1) - 1) / - time_per_frame->numerator; - - /* - * update bitrate to introduce a correction due to - * the new framerate - * new bitrate = (old bitrate * new framerate) / old framerate - */ - td->bit_rate /= time_per_frame->numerator; - td->bit_rate *= time_per_frame->denominator; - td->bit_rate /= td->framerate_num; - } else { - td->framerate_den = time_per_frame->numerator; - td->framerate_num = time_per_frame->denominator; - } - - /* compute maximum bitrate depending on profile */ - if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) - max_bitrate = h264_infos_list[level].max_bitrate * - H264_FACTOR_HIGH; - else - max_bitrate = h264_infos_list[level].max_bitrate * - H264_FACTOR_BASELINE; - - /* check if bitrate doesn't exceed max size */ - if (td->bit_rate > max_bitrate) { - dev_dbg(dev, - "%s bitrate (%d) larger than level and profile allow, clip to %d\n", - pctx->name, td->bit_rate, max_bitrate); - td->bit_rate = max_bitrate; - } - - /* convert cpb_buffer_size in bits */ - td->cpb_buffer_size = ctrls->cpb_size * 8000; - - /* compute maximum cpb buffer size depending on profile */ - if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) - max_cpb_buffer_size = - h264_infos_list[level].max_cpb_size * H264_FACTOR_HIGH; - else - max_cpb_buffer_size = - h264_infos_list[level].max_cpb_size * H264_FACTOR_BASELINE; - - /* check if cpb buffer size doesn't exceed max size */ - if (td->cpb_buffer_size > max_cpb_buffer_size) { - dev_dbg(dev, - "%s cpb size larger than level %d allows, clip to %d\n", - pctx->name, td->cpb_buffer_size, max_cpb_buffer_size); - td->cpb_buffer_size = max_cpb_buffer_size; - } - - /* enable skipping in the Bitrate Controller */ - td->brc_no_skip = 0; - - /* initial delay */ - if ((ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) && - td->bit_rate) - td->delay = 1000 * (td->cpb_buffer_size / td->bit_rate); - else - td->delay = 0; - - switch (frame->info.pixelformat) { - case V4L2_PIX_FMT_NV12: - td->sampling_mode = SAMPLING_MODE_NV12; - break; - case V4L2_PIX_FMT_NV21: - td->sampling_mode = SAMPLING_MODE_NV21; - break; - default: - dev_err(dev, "%s invalid source pixel format\n", - pctx->name); - pctx->frame_errors++; - return -EINVAL; - } - - /* - * fill matrix color converter (RGB to YUV) - * Y = 0,299 R + 0,587 G + 0,114 B - * Cb = -0,1687 R -0,3313 G + 0,5 B + 128 - * Cr = 0,5 R - 0,4187 G - 0,0813 B + 128 - */ - td->rgb2_yuv_y_coeff = 0x12031008; - td->rgb2_yuv_u_coeff = 0x800EF7FB; - td->rgb2_yuv_v_coeff = 0x80FEF40E; - - /* enable/disable transform mode */ - td->transform_mode = ctrls->dct8x8; - - /* encoder complexity fix to 2, ENCODE_I_16x16_I_NxN_P_16x16_P_WxH */ - td->encoder_complexity = 2; - - /* quant fix to 28, default VBR value */ - td->quant = 28; - - if (td->framerate_den == 0) { - dev_err(dev, "%s invalid framerate\n", pctx->name); - pctx->frame_errors++; - return -EINVAL; - } - - /* if automatic framerate, deactivate bitrate controller */ - if (td->framerate_num == 0) - td->brc_type = 0; - - /* compliancy fix to true */ - td->strict_hrd_compliancy = 1; - - /* set minimum & maximum quantizers */ - td->qp_min = clamp_val(ctrls->qpmin, 0, 51); - td->qp_max = clamp_val(ctrls->qpmax, 0, 51); - - td->addr_source_buffer = frame->paddr; - td->addr_fwd_ref_buffer = fwd_ref_frame->paddr; - td->addr_rec_buffer = loc_rec_frame->paddr; - - td->addr_output_bitstream_end = (u32)stream->paddr + stream->size; - - td->addr_output_bitstream_start = (u32)stream->paddr; - td->bitstream_offset = (((u32)stream->paddr & 0xF) << 3) & - BITSTREAM_OFFSET_MASK; - - td->addr_param_out = (u32)ctx->task->paddr + - offsetof(struct hva_h264_task, po); - - /* swap spatial and temporal context */ - if (frame_num % 2) { - paddr = seq_info->paddr; - td->addr_spatial_context = ALIGN(paddr, 0x100); - paddr = seq_info->paddr + DATA_SIZE(frame_width, - frame_height); - td->addr_temporal_context = ALIGN(paddr, 0x100); - } else { - paddr = seq_info->paddr; - td->addr_temporal_context = ALIGN(paddr, 0x100); - paddr = seq_info->paddr + DATA_SIZE(frame_width, - frame_height); - td->addr_spatial_context = ALIGN(paddr, 0x100); - } - - paddr = seq_info->paddr + 2 * DATA_SIZE(frame_width, frame_height); - - td->addr_brc_in_out_parameter = ALIGN(paddr, 0x100); - - paddr = td->addr_brc_in_out_parameter + BRC_DATA_SIZE; - td->addr_slice_header = ALIGN(paddr, 0x100); - td->addr_external_sw = ALIGN(addr_esram, 0x100); - - addr_esram += SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width); - td->addr_local_rec_buffer = ALIGN(addr_esram, 0x100); - - addr_esram += LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width); - td->addr_lctx = ALIGN(addr_esram, 0x100); - - addr_esram += CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height)); - td->addr_cabac_context_buffer = ALIGN(addr_esram, 0x100); - - if (!(frame_num % ctrls->gop_size)) { - td->picture_coding_type = PICTURE_CODING_TYPE_I; - stream->vbuf.flags |= V4L2_BUF_FLAG_KEYFRAME; - } else { - td->picture_coding_type = PICTURE_CODING_TYPE_P; - stream->vbuf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; - } - - /* fill the slice header part */ - slice_header_vaddr = seq_info->vaddr + (td->addr_slice_header - - seq_info->paddr); - - hva_h264_fill_slice_header(pctx, slice_header_vaddr, ctrls, frame_num, - &td->slice_header_size_in_bits, - &td->slice_header_offset0, - &td->slice_header_offset1, - &td->slice_header_offset2); - - td->chroma_qp_index_offset = 2; - td->slice_synchro_enable = 0; - td->max_slice_number = 1; - - /* - * check the sps/pps header size for key frame only - * sps/pps header was previously fill by libv4l - * during qbuf of stream buffer - */ - if ((stream->vbuf.flags == V4L2_BUF_FLAG_KEYFRAME) && - (payload > MAX_SPS_PPS_SIZE)) { - dev_err(dev, "%s invalid sps/pps size %d\n", pctx->name, - payload); - pctx->frame_errors++; - return -EINVAL; - } - - if (stream->vbuf.flags != V4L2_BUF_FLAG_KEYFRAME) - payload = 0; - - /* add SEI nal (video stereo info) */ - if (ctrls->sei_fp && hva_h264_fill_sei_nal(pctx, SEI_STEREO_VIDEO_INFO, - (u8 *)stream->vaddr, - &payload)) { - dev_err(dev, "%s fail to get SEI nal\n", pctx->name); - pctx->frame_errors++; - return -EINVAL; - } - - /* fill size of non-VCL NAL units (SPS, PPS, filler and SEI) */ - td->non_vcl_nalu_size = payload * 8; - - /* compute bitstream offset & new start address of bitstream */ - td->addr_output_bitstream_start += ((payload >> 4) << 4); - td->bitstream_offset += (payload - ((payload >> 4) << 4)) * 8; - - stream->bytesused = payload; - - return 0; -} - -static unsigned int hva_h264_get_stream_size(struct hva_h264_task *task) -{ - struct hva_h264_po *po = &task->po; - - return po->bitstream_size; -} - -static u32 hva_h264_get_stuffing_bytes(struct hva_h264_task *task) -{ - struct hva_h264_po *po = &task->po; - - return po->stuffing_bits >> 3; -} - -static int hva_h264_open(struct hva_ctx *pctx) -{ - struct device *dev = ctx_to_dev(pctx); - struct hva_h264_ctx *ctx; - struct hva_dev *hva = ctx_to_hdev(pctx); - u32 frame_width = pctx->frameinfo.aligned_width; - u32 frame_height = pctx->frameinfo.aligned_height; - u32 size; - int ret; - - /* check esram size necessary to encode a frame */ - size = SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width) + - LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width) + - CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height)) + - CABAC_CONTEXT_BUFFER_MAX_SIZE(frame_width); - - if (hva->esram_size < size) { - dev_err(dev, "%s not enough esram (max:%d request:%d)\n", - pctx->name, hva->esram_size, size); - ret = -EINVAL; - goto err; - } - - /* allocate context for codec */ - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - ret = -ENOMEM; - goto err; - } - - /* allocate sequence info buffer */ - ret = hva_mem_alloc(pctx, - 2 * DATA_SIZE(frame_width, frame_height) + - SLICE_HEADER_SIZE + - BRC_DATA_SIZE, - "hva sequence info", - &ctx->seq_info); - if (ret) { - dev_err(dev, - "%s failed to allocate sequence info buffer\n", - pctx->name); - goto err_ctx; - } - - /* allocate reference frame buffer */ - ret = hva_mem_alloc(pctx, - frame_width * frame_height * 3 / 2, - "hva reference frame", - &ctx->ref_frame); - if (ret) { - dev_err(dev, "%s failed to allocate reference frame buffer\n", - pctx->name); - goto err_seq_info; - } - - /* allocate reconstructed frame buffer */ - ret = hva_mem_alloc(pctx, - frame_width * frame_height * 3 / 2, - "hva reconstructed frame", - &ctx->rec_frame); - if (ret) { - dev_err(dev, - "%s failed to allocate reconstructed frame buffer\n", - pctx->name); - goto err_ref_frame; - } - - /* allocate task descriptor */ - ret = hva_mem_alloc(pctx, - sizeof(struct hva_h264_task), - "hva task descriptor", - &ctx->task); - if (ret) { - dev_err(dev, - "%s failed to allocate task descriptor\n", - pctx->name); - goto err_rec_frame; - } - - pctx->priv = (void *)ctx; - - return 0; - -err_rec_frame: - hva_mem_free(pctx, ctx->rec_frame); -err_ref_frame: - hva_mem_free(pctx, ctx->ref_frame); -err_seq_info: - hva_mem_free(pctx, ctx->seq_info); -err_ctx: - devm_kfree(dev, ctx); -err: - pctx->sys_errors++; - return ret; -} - -static int hva_h264_close(struct hva_ctx *pctx) -{ - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; - struct device *dev = ctx_to_dev(pctx); - - if (ctx->seq_info) - hva_mem_free(pctx, ctx->seq_info); - - if (ctx->ref_frame) - hva_mem_free(pctx, ctx->ref_frame); - - if (ctx->rec_frame) - hva_mem_free(pctx, ctx->rec_frame); - - if (ctx->task) - hva_mem_free(pctx, ctx->task); - - devm_kfree(dev, ctx); - - return 0; -} - -static int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame, - struct hva_stream *stream) -{ - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; - struct hva_h264_task *task = (struct hva_h264_task *)ctx->task->vaddr; - u32 stuffing_bytes = 0; - int ret = 0; - - ret = hva_h264_prepare_task(pctx, task, frame, stream); - if (ret) - goto err; - - ret = hva_hw_execute_task(pctx, H264_ENC, ctx->task); - if (ret) - goto err; - - pctx->stream_num++; - stream->bytesused += hva_h264_get_stream_size(task); - - stuffing_bytes = hva_h264_get_stuffing_bytes(task); - - if (stuffing_bytes) - hva_h264_fill_data_nal(pctx, stuffing_bytes, - (u8 *)stream->vaddr, - stream->size, - &stream->bytesused); - - /* switch reference & reconstructed frame */ - swap(ctx->ref_frame, ctx->rec_frame); - - return 0; -err: - stream->bytesused = 0; - return ret; -} - -const struct hva_enc nv12h264enc = { - .name = "H264(NV12)", - .pixelformat = V4L2_PIX_FMT_NV12, - .streamformat = V4L2_PIX_FMT_H264, - .max_width = H264_MAX_SIZE_W, - .max_height = H264_MAX_SIZE_H, - .open = hva_h264_open, - .close = hva_h264_close, - .encode = hva_h264_encode, -}; - -const struct hva_enc nv21h264enc = { - .name = "H264(NV21)", - .pixelformat = V4L2_PIX_FMT_NV21, - .streamformat = V4L2_PIX_FMT_H264, - .max_width = H264_MAX_SIZE_W, - .max_height = H264_MAX_SIZE_H, - .open = hva_h264_open, - .close = hva_h264_close, - .encode = hva_h264_encode, -}; |