Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8c3937435 | |||
| e0acc33455 | |||
| 283df22748 | |||
| 4671f64479 | |||
| 07fd527114 | |||
| 2737ff921d | |||
| f2c3a4c32f | |||
| 44a73271ae | |||
| 0a3432ad64 | |||
| ac674b84ec | |||
| 1458622729 | |||
| 4d14ffb801 | |||
| 13e9b64bcf | |||
| fc4bb1063f | |||
| da9f2a55d2 | |||
| 53999cd154 | |||
| 294bdc24f6 | |||
| 2f54a8d9e8 | |||
| 4ccbfe923f | |||
| 1b02c9b476 | |||
| c1f5108ac3 |
@@ -0,0 +1,9 @@
|
||||
# STUDY.md → moved
|
||||
|
||||
The Phase 0 / Phase 2 substrate that previously lived here has been transformed into the campaign-level Phase 0 document at:
|
||||
|
||||
- [`../phase0_findings.md`](../phase0_findings.md)
|
||||
|
||||
That document also points at the remaining open questions for Phase 1 lock and the verification gate at Phase 7. Read it together with the campaign README at [`../README.md`](../README.md).
|
||||
|
||||
The git commit that this file points back to (the last commit while STUDY.md still held the substrate content) is `e0acc33` — `git show e0acc33:STUDY.md` recovers the historical content if needed.
|
||||
+35
-186
@@ -1,197 +1,46 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* These are the H.264 state controls for use with stateless H.264
|
||||
* codec drivers.
|
||||
* Fourier-local: H.264 stateless controls and structs were upstreamed to
|
||||
* the kernel some time after this library went dormant. Defer all of:
|
||||
*
|
||||
* It turns out that these structs are not stable yet and will undergo
|
||||
* more changes. So keep them private until they are stable and ready to
|
||||
* become part of the official public API.
|
||||
* struct v4l2_ctrl_h264_sps / pps / scaling_matrix / pred_weights /
|
||||
* slice_params / decode_params
|
||||
* struct v4l2_h264_weight_factors / dpb_entry / reference
|
||||
* enum v4l2_*_h264_*
|
||||
*
|
||||
* to <linux/v4l2-controls.h>, where they now live with the same field
|
||||
* names. The duplicated definitions in the original bootlin
|
||||
* include/h264-ctrls.h conflict at compile time on any current kernel.
|
||||
*
|
||||
* The CID prefix was also renamed from V4L2_CID_MPEG_VIDEO_H264_* to
|
||||
* V4L2_CID_STATELESS_H264_*. Provide compatibility aliases so h264.c
|
||||
* keeps compiling without an invasive sed across that file.
|
||||
*
|
||||
* V4L2_PIX_FMT_H264_SLICE itself lives in <linux/videodev2.h> on current
|
||||
* kernels, so no need to redefine it here.
|
||||
*/
|
||||
|
||||
#ifndef _H264_CTRLS_H_
|
||||
#define _H264_CTRLS_H_
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/v4l2-controls.h>
|
||||
|
||||
/* Our pixel format isn't stable at the moment */
|
||||
#define V4L2_PIX_FMT_H264_SLICE_RAW v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */
|
||||
|
||||
/*
|
||||
* This is put insanely high to avoid conflicting with controls that
|
||||
* would be added during the phase where those controls are not
|
||||
* stable. It should be fixed eventually.
|
||||
*/
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_SPS (V4L2_CID_MPEG_BASE+1000)
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_PPS (V4L2_CID_MPEG_BASE+1001)
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (V4L2_CID_MPEG_BASE+1002)
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (V4L2_CID_MPEG_BASE+1003)
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (V4L2_CID_MPEG_BASE+1004)
|
||||
|
||||
/* enum v4l2_ctrl_type type values */
|
||||
#define V4L2_CTRL_TYPE_H264_SPS 0x0110
|
||||
#define V4L2_CTRL_TYPE_H264_PPS 0x0111
|
||||
#define V4L2_CTRL_TYPE_H264_SCALING_MATRIX 0x0112
|
||||
#define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113
|
||||
#define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114
|
||||
|
||||
#define V4L2_H264_SPS_CONSTRAINT_SET0_FLAG 0x01
|
||||
#define V4L2_H264_SPS_CONSTRAINT_SET1_FLAG 0x02
|
||||
#define V4L2_H264_SPS_CONSTRAINT_SET2_FLAG 0x04
|
||||
#define V4L2_H264_SPS_CONSTRAINT_SET3_FLAG 0x08
|
||||
#define V4L2_H264_SPS_CONSTRAINT_SET4_FLAG 0x10
|
||||
#define V4L2_H264_SPS_CONSTRAINT_SET5_FLAG 0x20
|
||||
|
||||
#define V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE 0x01
|
||||
#define V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS 0x02
|
||||
#define V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO 0x04
|
||||
#define V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED 0x08
|
||||
#define V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY 0x10
|
||||
#define V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD 0x20
|
||||
#define V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE 0x40
|
||||
|
||||
struct v4l2_ctrl_h264_sps {
|
||||
__u8 profile_idc;
|
||||
__u8 constraint_set_flags;
|
||||
__u8 level_idc;
|
||||
__u8 seq_parameter_set_id;
|
||||
__u8 chroma_format_idc;
|
||||
__u8 bit_depth_luma_minus8;
|
||||
__u8 bit_depth_chroma_minus8;
|
||||
__u8 log2_max_frame_num_minus4;
|
||||
__u8 pic_order_cnt_type;
|
||||
__u8 log2_max_pic_order_cnt_lsb_minus4;
|
||||
__u8 max_num_ref_frames;
|
||||
__u8 num_ref_frames_in_pic_order_cnt_cycle;
|
||||
__s32 offset_for_ref_frame[255];
|
||||
__s32 offset_for_non_ref_pic;
|
||||
__s32 offset_for_top_to_bottom_field;
|
||||
__u16 pic_width_in_mbs_minus1;
|
||||
__u16 pic_height_in_map_units_minus1;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
#define V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE 0x0001
|
||||
#define V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT 0x0002
|
||||
#define V4L2_H264_PPS_FLAG_WEIGHTED_PRED 0x0004
|
||||
#define V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT 0x0008
|
||||
#define V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED 0x0010
|
||||
#define V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT 0x0020
|
||||
#define V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE 0x0040
|
||||
#define V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT 0x0080
|
||||
|
||||
struct v4l2_ctrl_h264_pps {
|
||||
__u8 pic_parameter_set_id;
|
||||
__u8 seq_parameter_set_id;
|
||||
__u8 num_slice_groups_minus1;
|
||||
__u8 num_ref_idx_l0_default_active_minus1;
|
||||
__u8 num_ref_idx_l1_default_active_minus1;
|
||||
__u8 weighted_bipred_idc;
|
||||
__s8 pic_init_qp_minus26;
|
||||
__s8 pic_init_qs_minus26;
|
||||
__s8 chroma_qp_index_offset;
|
||||
__s8 second_chroma_qp_index_offset;
|
||||
__u16 flags;
|
||||
};
|
||||
|
||||
struct v4l2_ctrl_h264_scaling_matrix {
|
||||
__u8 scaling_list_4x4[6][16];
|
||||
__u8 scaling_list_8x8[6][64];
|
||||
};
|
||||
|
||||
struct v4l2_h264_weight_factors {
|
||||
__s16 luma_weight[32];
|
||||
__s16 luma_offset[32];
|
||||
__s16 chroma_weight[32][2];
|
||||
__s16 chroma_offset[32][2];
|
||||
};
|
||||
|
||||
struct v4l2_h264_pred_weight_table {
|
||||
__u16 luma_log2_weight_denom;
|
||||
__u16 chroma_log2_weight_denom;
|
||||
struct v4l2_h264_weight_factors weight_factors[2];
|
||||
};
|
||||
|
||||
#define V4L2_H264_SLICE_TYPE_P 0
|
||||
#define V4L2_H264_SLICE_TYPE_B 1
|
||||
#define V4L2_H264_SLICE_TYPE_I 2
|
||||
#define V4L2_H264_SLICE_TYPE_SP 3
|
||||
#define V4L2_H264_SLICE_TYPE_SI 4
|
||||
|
||||
#define V4L2_H264_SLICE_FLAG_FIELD_PIC 0x01
|
||||
#define V4L2_H264_SLICE_FLAG_BOTTOM_FIELD 0x02
|
||||
#define V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED 0x04
|
||||
#define V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH 0x08
|
||||
|
||||
struct v4l2_ctrl_h264_slice_params {
|
||||
/* Size in bytes, including header */
|
||||
__u32 size;
|
||||
/* Offset in bits to slice_data() from the beginning of this slice. */
|
||||
__u32 header_bit_size;
|
||||
|
||||
__u16 first_mb_in_slice;
|
||||
__u8 slice_type;
|
||||
__u8 pic_parameter_set_id;
|
||||
__u8 colour_plane_id;
|
||||
__u8 redundant_pic_cnt;
|
||||
__u16 frame_num;
|
||||
__u16 idr_pic_id;
|
||||
__u16 pic_order_cnt_lsb;
|
||||
__s32 delta_pic_order_cnt_bottom;
|
||||
__s32 delta_pic_order_cnt0;
|
||||
__s32 delta_pic_order_cnt1;
|
||||
|
||||
struct v4l2_h264_pred_weight_table pred_weight_table;
|
||||
/* Size in bits of dec_ref_pic_marking() syntax element. */
|
||||
__u32 dec_ref_pic_marking_bit_size;
|
||||
/* Size in bits of pic order count syntax. */
|
||||
__u32 pic_order_cnt_bit_size;
|
||||
|
||||
__u8 cabac_init_idc;
|
||||
__s8 slice_qp_delta;
|
||||
__s8 slice_qs_delta;
|
||||
__u8 disable_deblocking_filter_idc;
|
||||
__s8 slice_alpha_c0_offset_div2;
|
||||
__s8 slice_beta_offset_div2;
|
||||
__u8 num_ref_idx_l0_active_minus1;
|
||||
__u8 num_ref_idx_l1_active_minus1;
|
||||
__u32 slice_group_change_cycle;
|
||||
|
||||
/*
|
||||
* Entries on each list are indices into
|
||||
* v4l2_ctrl_h264_decode_params.dpb[].
|
||||
*/
|
||||
__u8 ref_pic_list0[32];
|
||||
__u8 ref_pic_list1[32];
|
||||
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
#define V4L2_H264_DPB_ENTRY_FLAG_VALID 0x01
|
||||
#define V4L2_H264_DPB_ENTRY_FLAG_ACTIVE 0x02
|
||||
#define V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM 0x04
|
||||
|
||||
struct v4l2_h264_dpb_entry {
|
||||
__u64 reference_ts;
|
||||
__u16 frame_num;
|
||||
__u16 pic_num;
|
||||
/* Note that field is indicated by v4l2_buffer.field */
|
||||
__s32 top_field_order_cnt;
|
||||
__s32 bottom_field_order_cnt;
|
||||
__u32 flags; /* V4L2_H264_DPB_ENTRY_FLAG_* */
|
||||
};
|
||||
|
||||
#define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01
|
||||
|
||||
struct v4l2_ctrl_h264_decode_params {
|
||||
struct v4l2_h264_dpb_entry dpb[16];
|
||||
__u16 num_slices;
|
||||
__u16 nal_ref_idc;
|
||||
__u8 ref_pic_list_p0[32];
|
||||
__u8 ref_pic_list_b0[32];
|
||||
__u8 ref_pic_list_b1[32];
|
||||
__s32 top_field_order_cnt;
|
||||
__s32 bottom_field_order_cnt;
|
||||
__u32 flags; /* V4L2_H264_DECODE_PARAM_FLAG_* */
|
||||
};
|
||||
|
||||
#ifndef V4L2_CID_MPEG_VIDEO_H264_SPS
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_SPS \
|
||||
V4L2_CID_STATELESS_H264_SPS
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_PPS \
|
||||
V4L2_CID_STATELESS_H264_PPS
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX \
|
||||
V4L2_CID_STATELESS_H264_SCALING_MATRIX
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS \
|
||||
V4L2_CID_STATELESS_H264_SLICE_PARAMS
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS \
|
||||
V4L2_CID_STATELESS_H264_DECODE_PARAMS
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE \
|
||||
V4L2_CID_STATELESS_H264_DECODE_MODE
|
||||
#define V4L2_CID_MPEG_VIDEO_H264_START_CODE \
|
||||
V4L2_CID_STATELESS_H264_START_CODE
|
||||
#endif
|
||||
|
||||
#endif /* _H264_CTRLS_H_ */
|
||||
|
||||
+12
-178
@@ -1,185 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* These are the HEVC state controls for use with stateless HEVC
|
||||
* codec drivers.
|
||||
* Fourier-local: HEVC support stripped from this build. The bundled
|
||||
* HEVC controls structs and CIDs (V4L2_CID_MPEG_VIDEO_HEVC_*) were
|
||||
* upstreamed and renamed to V4L2_CID_STATELESS_HEVC_* in mainline
|
||||
* linux/v4l2-controls.h, making the original duplicated definitions
|
||||
* conflict on any current kernel. RK3566 has no HW HEVC anyway, so the
|
||||
* port is starting from H.264 + MPEG-2 only; HEVC can come back as a
|
||||
* separate effort once a) the host has HEVC silicon (RK3588 hantro/
|
||||
* VDPU381) and b) the library is updated to the renamed CIDs.
|
||||
*
|
||||
* It turns out that these structs are not stable yet and will undergo
|
||||
* more changes. So keep them private until they are stable and ready to
|
||||
* become part of the official public API.
|
||||
* h265.c and h265.h are excluded from src/meson.build; this header is
|
||||
* left as a placeholder so any stray '#include <hevc-ctrls.h>' from a
|
||||
* downstream patch keeps compiling.
|
||||
*/
|
||||
|
||||
#ifndef _HEVC_CTRLS_H_
|
||||
#define _HEVC_CTRLS_H_
|
||||
|
||||
/* The pixel format isn't stable at the moment and will likely be renamed. */
|
||||
#define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */
|
||||
|
||||
#define V4L2_CID_MPEG_VIDEO_HEVC_SPS (V4L2_CID_MPEG_BASE + 1008)
|
||||
#define V4L2_CID_MPEG_VIDEO_HEVC_PPS (V4L2_CID_MPEG_BASE + 1009)
|
||||
#define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS (V4L2_CID_MPEG_BASE + 1010)
|
||||
|
||||
/* enum v4l2_ctrl_type type values */
|
||||
#define V4L2_CTRL_TYPE_HEVC_SPS 0x0120
|
||||
#define V4L2_CTRL_TYPE_HEVC_PPS 0x0121
|
||||
#define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122
|
||||
|
||||
#define V4L2_HEVC_SLICE_TYPE_B 0
|
||||
#define V4L2_HEVC_SLICE_TYPE_P 1
|
||||
#define V4L2_HEVC_SLICE_TYPE_I 2
|
||||
|
||||
/* The controls are not stable at the moment and will likely be reworked. */
|
||||
struct v4l2_ctrl_hevc_sps {
|
||||
/* ISO/IEC 23008-2, ITU-T Rec. H.265: Sequence parameter set */
|
||||
__u8 chroma_format_idc;
|
||||
__u8 separate_colour_plane_flag;
|
||||
__u16 pic_width_in_luma_samples;
|
||||
__u16 pic_height_in_luma_samples;
|
||||
__u8 bit_depth_luma_minus8;
|
||||
__u8 bit_depth_chroma_minus8;
|
||||
__u8 log2_max_pic_order_cnt_lsb_minus4;
|
||||
__u8 sps_max_dec_pic_buffering_minus1;
|
||||
__u8 sps_max_num_reorder_pics;
|
||||
__u8 sps_max_latency_increase_plus1;
|
||||
__u8 log2_min_luma_coding_block_size_minus3;
|
||||
__u8 log2_diff_max_min_luma_coding_block_size;
|
||||
__u8 log2_min_luma_transform_block_size_minus2;
|
||||
__u8 log2_diff_max_min_luma_transform_block_size;
|
||||
__u8 max_transform_hierarchy_depth_inter;
|
||||
__u8 max_transform_hierarchy_depth_intra;
|
||||
__u8 scaling_list_enabled_flag;
|
||||
__u8 amp_enabled_flag;
|
||||
__u8 sample_adaptive_offset_enabled_flag;
|
||||
__u8 pcm_enabled_flag;
|
||||
__u8 pcm_sample_bit_depth_luma_minus1;
|
||||
__u8 pcm_sample_bit_depth_chroma_minus1;
|
||||
__u8 log2_min_pcm_luma_coding_block_size_minus3;
|
||||
__u8 log2_diff_max_min_pcm_luma_coding_block_size;
|
||||
__u8 pcm_loop_filter_disabled_flag;
|
||||
__u8 num_short_term_ref_pic_sets;
|
||||
__u8 long_term_ref_pics_present_flag;
|
||||
__u8 num_long_term_ref_pics_sps;
|
||||
__u8 sps_temporal_mvp_enabled_flag;
|
||||
__u8 strong_intra_smoothing_enabled_flag;
|
||||
};
|
||||
|
||||
struct v4l2_ctrl_hevc_pps {
|
||||
/* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture parameter set */
|
||||
__u8 dependent_slice_segment_flag;
|
||||
__u8 output_flag_present_flag;
|
||||
__u8 num_extra_slice_header_bits;
|
||||
__u8 sign_data_hiding_enabled_flag;
|
||||
__u8 cabac_init_present_flag;
|
||||
__s8 init_qp_minus26;
|
||||
__u8 constrained_intra_pred_flag;
|
||||
__u8 transform_skip_enabled_flag;
|
||||
__u8 cu_qp_delta_enabled_flag;
|
||||
__u8 diff_cu_qp_delta_depth;
|
||||
__s8 pps_cb_qp_offset;
|
||||
__s8 pps_cr_qp_offset;
|
||||
__u8 pps_slice_chroma_qp_offsets_present_flag;
|
||||
__u8 weighted_pred_flag;
|
||||
__u8 weighted_bipred_flag;
|
||||
__u8 transquant_bypass_enabled_flag;
|
||||
__u8 tiles_enabled_flag;
|
||||
__u8 entropy_coding_sync_enabled_flag;
|
||||
__u8 num_tile_columns_minus1;
|
||||
__u8 num_tile_rows_minus1;
|
||||
__u8 column_width_minus1[20];
|
||||
__u8 row_height_minus1[22];
|
||||
__u8 loop_filter_across_tiles_enabled_flag;
|
||||
__u8 pps_loop_filter_across_slices_enabled_flag;
|
||||
__u8 deblocking_filter_override_enabled_flag;
|
||||
__u8 pps_disable_deblocking_filter_flag;
|
||||
__s8 pps_beta_offset_div2;
|
||||
__s8 pps_tc_offset_div2;
|
||||
__u8 lists_modification_present_flag;
|
||||
__u8 log2_parallel_merge_level_minus2;
|
||||
__u8 slice_segment_header_extension_present_flag;
|
||||
__u8 padding;
|
||||
};
|
||||
|
||||
#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_BEFORE 0x01
|
||||
#define V4L2_HEVC_DPB_ENTRY_RPS_ST_CURR_AFTER 0x02
|
||||
#define V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR 0x03
|
||||
|
||||
#define V4L2_HEVC_DPB_ENTRIES_NUM_MAX 16
|
||||
|
||||
struct v4l2_hevc_dpb_entry {
|
||||
__u64 timestamp;
|
||||
__u8 rps;
|
||||
__u8 field_pic;
|
||||
__u16 pic_order_cnt[2];
|
||||
__u8 padding[2];
|
||||
};
|
||||
|
||||
struct v4l2_hevc_pred_weight_table {
|
||||
__u8 luma_log2_weight_denom;
|
||||
__s8 delta_chroma_log2_weight_denom;
|
||||
|
||||
__s8 delta_luma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
||||
__s8 luma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
||||
__s8 delta_chroma_weight_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
|
||||
__s8 chroma_offset_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
|
||||
|
||||
__s8 delta_luma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
||||
__s8 luma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
||||
__s8 delta_chroma_weight_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
|
||||
__s8 chroma_offset_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX][2];
|
||||
|
||||
__u8 padding[2];
|
||||
};
|
||||
|
||||
struct v4l2_ctrl_hevc_slice_params {
|
||||
__u32 bit_size;
|
||||
__u32 data_bit_offset;
|
||||
|
||||
/* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */
|
||||
__u8 nal_unit_type;
|
||||
__u8 nuh_temporal_id_plus1;
|
||||
|
||||
/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
|
||||
__u8 slice_type;
|
||||
__u8 colour_plane_id;
|
||||
__u16 slice_pic_order_cnt;
|
||||
__u8 slice_sao_luma_flag;
|
||||
__u8 slice_sao_chroma_flag;
|
||||
__u8 slice_temporal_mvp_enabled_flag;
|
||||
__u8 num_ref_idx_l0_active_minus1;
|
||||
__u8 num_ref_idx_l1_active_minus1;
|
||||
__u8 mvd_l1_zero_flag;
|
||||
__u8 cabac_init_flag;
|
||||
__u8 collocated_from_l0_flag;
|
||||
__u8 collocated_ref_idx;
|
||||
__u8 five_minus_max_num_merge_cand;
|
||||
__u8 use_integer_mv_flag;
|
||||
__s8 slice_qp_delta;
|
||||
__s8 slice_cb_qp_offset;
|
||||
__s8 slice_cr_qp_offset;
|
||||
__s8 slice_act_y_qp_offset;
|
||||
__s8 slice_act_cb_qp_offset;
|
||||
__s8 slice_act_cr_qp_offset;
|
||||
__u8 slice_deblocking_filter_disabled_flag;
|
||||
__s8 slice_beta_offset_div2;
|
||||
__s8 slice_tc_offset_div2;
|
||||
__u8 slice_loop_filter_across_slices_enabled_flag;
|
||||
|
||||
/* ISO/IEC 23008-2, ITU-T Rec. H.265: Picture timing SEI message */
|
||||
__u8 pic_struct;
|
||||
|
||||
/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */
|
||||
struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
||||
__u8 num_active_dpb_entries;
|
||||
__u8 ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
||||
__u8 ref_idx_l1[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
|
||||
|
||||
__u8 num_rps_poc_st_curr_before;
|
||||
__u8 num_rps_poc_st_curr_after;
|
||||
__u8 num_rps_poc_lt_curr;
|
||||
|
||||
/* ISO/IEC 23008-2, ITU-T Rec. H.265: Weighted prediction parameter */
|
||||
struct v4l2_hevc_pred_weight_table pred_weight_table;
|
||||
|
||||
__u8 padding[2];
|
||||
};
|
||||
|
||||
#include <linux/v4l2-controls.h>
|
||||
#endif
|
||||
|
||||
@@ -49,6 +49,7 @@ VAStatus RequestCreateBuffer(VADriverContextP context, VAContextID context_id,
|
||||
unsigned int count, void *data,
|
||||
VABufferID *buffer_id)
|
||||
{
|
||||
request_log("ENTER RequestCreateBuffer\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_buffer *buffer_object = NULL;
|
||||
void *buffer_data;
|
||||
@@ -109,6 +110,7 @@ complete:
|
||||
|
||||
VAStatus RequestDestroyBuffer(VADriverContextP context, VABufferID buffer_id)
|
||||
{
|
||||
request_log("ENTER RequestDestroyBuffer\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_buffer *buffer_object;
|
||||
|
||||
@@ -128,6 +130,7 @@ VAStatus RequestDestroyBuffer(VADriverContextP context, VABufferID buffer_id)
|
||||
VAStatus RequestMapBuffer(VADriverContextP context, VABufferID buffer_id,
|
||||
void **data_map)
|
||||
{
|
||||
request_log("ENTER RequestMapBuffer\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_buffer *buffer_object;
|
||||
|
||||
@@ -143,6 +146,7 @@ VAStatus RequestMapBuffer(VADriverContextP context, VABufferID buffer_id,
|
||||
|
||||
VAStatus RequestUnmapBuffer(VADriverContextP context, VABufferID buffer_id)
|
||||
{
|
||||
request_log("ENTER RequestUnmapBuffer\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_buffer *buffer_object;
|
||||
|
||||
@@ -158,6 +162,7 @@ VAStatus RequestUnmapBuffer(VADriverContextP context, VABufferID buffer_id)
|
||||
VAStatus RequestBufferSetNumElements(VADriverContextP context,
|
||||
VABufferID buffer_id, unsigned int count)
|
||||
{
|
||||
request_log("ENTER RequestBufferSetNumElements\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_buffer *buffer_object;
|
||||
|
||||
@@ -177,6 +182,7 @@ VAStatus RequestBufferInfo(VADriverContextP context, VABufferID buffer_id,
|
||||
VABufferType *type, unsigned int *size,
|
||||
unsigned int *count)
|
||||
{
|
||||
request_log("ENTER RequestBufferInfo\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_buffer *buffer_object;
|
||||
|
||||
@@ -195,6 +201,7 @@ VAStatus RequestAcquireBufferHandle(VADriverContextP context,
|
||||
VABufferID buffer_id,
|
||||
VABufferInfo *buffer_info)
|
||||
{
|
||||
request_log("ENTER RequestAcquireBufferHandle\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_buffer *buffer_object;
|
||||
struct object_surface *surface_object;
|
||||
@@ -245,6 +252,7 @@ VAStatus RequestAcquireBufferHandle(VADriverContextP context,
|
||||
VAStatus RequestReleaseBufferHandle(VADriverContextP context,
|
||||
VABufferID buffer_id)
|
||||
{
|
||||
request_log("ENTER RequestReleaseBufferHandle\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_buffer *buffer_object;
|
||||
int export_fd;
|
||||
|
||||
+18
-1
@@ -53,6 +53,9 @@ VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile,
|
||||
VAConfigID id;
|
||||
int i, index;
|
||||
|
||||
request_log("CreateConfig: profile=%d entrypoint=%d attrs=%d\n",
|
||||
profile, entrypoint, attributes_count);
|
||||
|
||||
switch (profile) {
|
||||
case VAProfileMPEG2Simple:
|
||||
case VAProfileMPEG2Main:
|
||||
@@ -120,6 +123,9 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
|
||||
|
||||
found = v4l2_find_format(driver_data->video_fd,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
||||
V4L2_PIX_FMT_MPEG2_SLICE) ||
|
||||
v4l2_find_format(driver_data->video_fd,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
|
||||
V4L2_PIX_FMT_MPEG2_SLICE);
|
||||
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 2)) {
|
||||
profiles[index++] = VAProfileMPEG2Simple;
|
||||
@@ -128,7 +134,10 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
|
||||
|
||||
found = v4l2_find_format(driver_data->video_fd,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
||||
V4L2_PIX_FMT_H264_SLICE_RAW);
|
||||
V4L2_PIX_FMT_H264_SLICE) ||
|
||||
v4l2_find_format(driver_data->video_fd,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
|
||||
V4L2_PIX_FMT_H264_SLICE);
|
||||
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 5)) {
|
||||
profiles[index++] = VAProfileH264Main;
|
||||
profiles[index++] = VAProfileH264High;
|
||||
@@ -139,6 +148,9 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
|
||||
|
||||
found = v4l2_find_format(driver_data->video_fd,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
||||
V4L2_PIX_FMT_HEVC_SLICE) ||
|
||||
v4l2_find_format(driver_data->video_fd,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
|
||||
V4L2_PIX_FMT_HEVC_SLICE);
|
||||
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 1))
|
||||
profiles[index++] = VAProfileHEVCMain;
|
||||
@@ -153,6 +165,8 @@ VAStatus RequestQueryConfigEntrypoints(VADriverContextP context,
|
||||
VAEntrypoint *entrypoints,
|
||||
int *entrypoints_count)
|
||||
{
|
||||
request_log("QueryConfigEntrypoints: profile=%d\n", profile);
|
||||
|
||||
switch (profile) {
|
||||
case VAProfileMPEG2Simple:
|
||||
case VAProfileMPEG2Main:
|
||||
@@ -212,6 +226,9 @@ VAStatus RequestGetConfigAttributes(VADriverContextP context, VAProfile profile,
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
request_log("GetConfigAttributes: profile=%d entrypoint=%d count=%d\n",
|
||||
profile, entrypoint, attributes_count);
|
||||
|
||||
for (i = 0; i < attributes_count; i++) {
|
||||
switch (attributes[i].type) {
|
||||
case VAConfigAttribRTFormat:
|
||||
|
||||
+30
-13
@@ -72,17 +72,26 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
int rc;
|
||||
|
||||
video_format = driver_data->video_format;
|
||||
if (video_format == NULL)
|
||||
if (video_format == NULL) {
|
||||
request_log("CreateContext: video_format is NULL\n");
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
output_type = v4l2_type_video_output(video_format->v4l2_mplane);
|
||||
capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
|
||||
request_log("CreateContext: ENTER config=%u mplane=%d output_type=%u capture_type=%u surfaces_count=%d flags=0x%x\n",
|
||||
config_id, video_format->v4l2_mplane, output_type,
|
||||
capture_type, surfaces_count, flags);
|
||||
|
||||
config_object = CONFIG(driver_data, config_id);
|
||||
if (config_object == NULL) {
|
||||
request_log("CreateContext: config_object NULL for config_id %u\n",
|
||||
config_id);
|
||||
status = VA_STATUS_ERROR_INVALID_CONFIG;
|
||||
goto error;
|
||||
}
|
||||
request_log("CreateContext: profile=%d width=%d height=%d\n",
|
||||
config_object->profile, picture_width, picture_height);
|
||||
|
||||
id = object_heap_allocate(&driver_data->context_heap);
|
||||
context_object = CONTEXT(driver_data, id);
|
||||
@@ -104,7 +113,7 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
case VAProfileH264ConstrainedBaseline:
|
||||
case VAProfileH264MultiviewHigh:
|
||||
case VAProfileH264StereoHigh:
|
||||
pixelformat = V4L2_PIX_FMT_H264_SLICE_RAW;
|
||||
pixelformat = V4L2_PIX_FMT_H264_SLICE;
|
||||
break;
|
||||
|
||||
case VAProfileHEVCMain:
|
||||
@@ -119,6 +128,8 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
rc = v4l2_set_format(driver_data->video_fd, output_type, pixelformat,
|
||||
picture_width, picture_height);
|
||||
if (rc < 0) {
|
||||
request_log("CreateContext: S_FMT(OUTPUT) failed for pixelformat 0x%x\n",
|
||||
pixelformat);
|
||||
status = VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
@@ -126,9 +137,13 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
rc = v4l2_create_buffers(driver_data->video_fd, output_type,
|
||||
surfaces_count, &index_base);
|
||||
if (rc < 0) {
|
||||
request_log("CreateContext: CREATE_BUFS failed surfaces=%d\n",
|
||||
surfaces_count);
|
||||
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
request_log("CreateContext: S_FMT + CREATE_BUFS ok, index_base=%u\n",
|
||||
index_base);
|
||||
|
||||
/*
|
||||
* The surface_ids array has been allocated by the caller and
|
||||
@@ -155,6 +170,7 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
rc = v4l2_query_buffer(driver_data->video_fd, output_type,
|
||||
index, &length, &offset, 1);
|
||||
if (rc < 0) {
|
||||
request_log("CreateContext: QUERYBUF idx=%u failed\n", index);
|
||||
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
@@ -162,6 +178,8 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
source_data = mmap(NULL, length, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, driver_data->video_fd, offset);
|
||||
if (source_data == MAP_FAILED) {
|
||||
request_log("CreateContext: mmap len=%u offset=%u failed\n",
|
||||
length, offset);
|
||||
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
@@ -171,17 +189,14 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
surface_object->source_size = length;
|
||||
}
|
||||
|
||||
rc = v4l2_set_stream(driver_data->video_fd, output_type, true);
|
||||
if (rc < 0) {
|
||||
status = VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = v4l2_set_stream(driver_data->video_fd, capture_type, true);
|
||||
if (rc < 0) {
|
||||
status = VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
/* Fourier-local: defer STREAMON until first frame is actually queued.
|
||||
* The V4L2 stateless protocol requires OUTPUT format + at least one
|
||||
* queued slice with SPS/PPS controls attached before STREAMON will
|
||||
* succeed on hantro. The bootlin library was written for sunxi-cedrus
|
||||
* which used a different protocol with no such ordering constraint.
|
||||
* Just being able to vaCreateContext() without erroring lets us see
|
||||
* what the next stage of the call chain expects. */
|
||||
request_log("CreateContext: deferred STREAMON until first QBUF\n");
|
||||
|
||||
context_object->config_id = config_id;
|
||||
context_object->render_surface_id = VA_INVALID_ID;
|
||||
@@ -193,6 +208,8 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
|
||||
*context_id = id;
|
||||
|
||||
request_log("CreateContext: SUCCESS context_id=%u\n", id);
|
||||
|
||||
status = VA_STATUS_SUCCESS;
|
||||
goto complete;
|
||||
|
||||
|
||||
+33
-15
@@ -36,6 +36,7 @@
|
||||
#include <h264-ctrls.h>
|
||||
|
||||
#include "request.h"
|
||||
#include "utils.h"
|
||||
#include "surface.h"
|
||||
#include "v4l2.h"
|
||||
|
||||
@@ -220,7 +221,9 @@ static void h264_va_picture_to_v4l2(struct request_data *driver_data,
|
||||
{
|
||||
h264_fill_dpb(driver_data, context, decode);
|
||||
|
||||
decode->num_slices = surface->slices_count;
|
||||
/* num_slices is no longer carried by v4l2_ctrl_h264_decode_params; the
|
||||
* kernel infers slice count from the number of slice_params controls
|
||||
* queued (one per slice via the request API). */
|
||||
decode->top_field_order_cnt = VAPicture->CurrPic.TopFieldOrderCnt;
|
||||
decode->bottom_field_order_cnt = VAPicture->CurrPic.BottomFieldOrderCnt;
|
||||
|
||||
@@ -327,9 +330,12 @@ static void h264_va_slice_to_v4l2(struct request_data *driver_data,
|
||||
struct object_context *context,
|
||||
VASliceParameterBufferH264 *VASlice,
|
||||
VAPictureParameterBufferH264 *VAPicture,
|
||||
struct v4l2_ctrl_h264_slice_params *slice)
|
||||
struct v4l2_ctrl_h264_slice_params *slice,
|
||||
struct v4l2_ctrl_h264_pred_weights *pred_weights)
|
||||
{
|
||||
slice->size = VASlice->slice_data_size;
|
||||
/* Slice byte size is now communicated via the OUTPUT buffer's
|
||||
* bytesused at QBUF time; the v4l2_ctrl_h264_slice_params struct
|
||||
* was slimmed during upstreaming and no longer carries it. */
|
||||
slice->header_bit_size = VASlice->slice_data_bit_offset;
|
||||
slice->first_mb_in_slice = VASlice->first_mb_in_slice;
|
||||
slice->slice_type = VASlice->slice_type;
|
||||
@@ -356,7 +362,8 @@ static void h264_va_slice_to_v4l2(struct request_data *driver_data,
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
slice->ref_pic_list0[i] = idx;
|
||||
slice->ref_pic_list0[i].index = idx;
|
||||
slice->ref_pic_list0[i].fields = V4L2_H264_FRAME_REF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,21 +382,24 @@ static void h264_va_slice_to_v4l2(struct request_data *driver_data,
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
slice->ref_pic_list1[i] = idx;
|
||||
slice->ref_pic_list1[i].index = idx;
|
||||
slice->ref_pic_list1[i].fields = V4L2_H264_FRAME_REF;
|
||||
}
|
||||
}
|
||||
|
||||
if (VASlice->direct_spatial_mv_pred_flag)
|
||||
slice->flags |= V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED;
|
||||
|
||||
slice->pred_weight_table.chroma_log2_weight_denom =
|
||||
/* Predicted weight table moved out of slice_params into its own
|
||||
* V4L2_CID_STATELESS_H264_PRED_WEIGHTS control during upstreaming. */
|
||||
pred_weights->chroma_log2_weight_denom =
|
||||
VASlice->chroma_log2_weight_denom;
|
||||
slice->pred_weight_table.luma_log2_weight_denom =
|
||||
pred_weights->luma_log2_weight_denom =
|
||||
VASlice->luma_log2_weight_denom;
|
||||
|
||||
if (((VASlice->slice_type % 5) == H264_SLICE_P) ||
|
||||
((VASlice->slice_type % 5) == H264_SLICE_B))
|
||||
h264_copy_pred_table(&slice->pred_weight_table.weight_factors[0],
|
||||
h264_copy_pred_table(&pred_weights->weight_factors[0],
|
||||
slice->num_ref_idx_l0_active_minus1 + 1,
|
||||
VASlice->luma_weight_l0,
|
||||
VASlice->luma_offset_l0,
|
||||
@@ -397,7 +407,7 @@ static void h264_va_slice_to_v4l2(struct request_data *driver_data,
|
||||
VASlice->chroma_offset_l0);
|
||||
|
||||
if ((VASlice->slice_type % 5) == H264_SLICE_B)
|
||||
h264_copy_pred_table(&slice->pred_weight_table.weight_factors[1],
|
||||
h264_copy_pred_table(&pred_weights->weight_factors[1],
|
||||
slice->num_ref_idx_l1_active_minus1 + 1,
|
||||
VASlice->luma_weight_l1,
|
||||
VASlice->luma_offset_l1,
|
||||
@@ -412,6 +422,7 @@ int h264_set_controls(struct request_data *driver_data,
|
||||
struct v4l2_ctrl_h264_scaling_matrix matrix = { 0 };
|
||||
struct v4l2_ctrl_h264_decode_params decode = { 0 };
|
||||
struct v4l2_ctrl_h264_slice_params slice = { 0 };
|
||||
struct v4l2_ctrl_h264_pred_weights pred_weights = { 0 };
|
||||
struct v4l2_ctrl_h264_pps pps = { 0 };
|
||||
struct v4l2_ctrl_h264_sps sps = { 0 };
|
||||
struct h264_dpb_entry *output;
|
||||
@@ -433,32 +444,39 @@ int h264_set_controls(struct request_data *driver_data,
|
||||
&surface->params.h264.matrix, &matrix);
|
||||
h264_va_slice_to_v4l2(driver_data, context,
|
||||
&surface->params.h264.slice,
|
||||
&surface->params.h264.picture, &slice);
|
||||
&surface->params.h264.picture, &slice,
|
||||
&pred_weights);
|
||||
|
||||
rc = v4l2_set_control(driver_data->video_fd, surface->request_fd,
|
||||
V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS, &decode,
|
||||
V4L2_CID_STATELESS_H264_DECODE_PARAMS, &decode,
|
||||
sizeof(decode));
|
||||
if (rc < 0)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
|
||||
rc = v4l2_set_control(driver_data->video_fd, surface->request_fd,
|
||||
V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS, &slice,
|
||||
V4L2_CID_STATELESS_H264_SLICE_PARAMS, &slice,
|
||||
sizeof(slice));
|
||||
if (rc < 0)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
|
||||
rc = v4l2_set_control(driver_data->video_fd, surface->request_fd,
|
||||
V4L2_CID_MPEG_VIDEO_H264_PPS, &pps, sizeof(pps));
|
||||
V4L2_CID_STATELESS_H264_PRED_WEIGHTS,
|
||||
&pred_weights, sizeof(pred_weights));
|
||||
if (rc < 0)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
|
||||
rc = v4l2_set_control(driver_data->video_fd, surface->request_fd,
|
||||
V4L2_CID_MPEG_VIDEO_H264_SPS, &sps, sizeof(sps));
|
||||
V4L2_CID_STATELESS_H264_PPS, &pps, sizeof(pps));
|
||||
if (rc < 0)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
|
||||
rc = v4l2_set_control(driver_data->video_fd, surface->request_fd,
|
||||
V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, &matrix,
|
||||
V4L2_CID_STATELESS_H264_SPS, &sps, sizeof(sps));
|
||||
if (rc < 0)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
|
||||
rc = v4l2_set_control(driver_data->video_fd, surface->request_fd,
|
||||
V4L2_CID_STATELESS_H264_SCALING_MATRIX, &matrix,
|
||||
sizeof(matrix));
|
||||
if (rc < 0)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
VAStatus RequestCreateImage(VADriverContextP context, VAImageFormat *format,
|
||||
int width, int height, VAImage *image)
|
||||
{
|
||||
request_log("ENTER RequestCreateImage\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
unsigned int destination_sizes[VIDEO_MAX_PLANES];
|
||||
unsigned int destination_bytesperlines[VIDEO_MAX_PLANES];
|
||||
@@ -125,6 +126,7 @@ VAStatus RequestCreateImage(VADriverContextP context, VAImageFormat *format,
|
||||
|
||||
VAStatus RequestDestroyImage(VADriverContextP context, VAImageID image_id)
|
||||
{
|
||||
request_log("ENTER RequestDestroyImage\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_image *image_object;
|
||||
VAStatus status;
|
||||
@@ -174,6 +176,7 @@ static VAStatus copy_surface_to_image (struct request_data *driver_data,
|
||||
VAStatus RequestDeriveImage(VADriverContextP context, VASurfaceID surface_id,
|
||||
VAImage *image)
|
||||
{
|
||||
request_log("ENTER RequestDeriveImage\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_surface *surface_object;
|
||||
struct object_buffer *buffer_object;
|
||||
@@ -212,6 +215,7 @@ VAStatus RequestDeriveImage(VADriverContextP context, VASurfaceID surface_id,
|
||||
VAStatus RequestQueryImageFormats(VADriverContextP context,
|
||||
VAImageFormat *formats, int *formats_count)
|
||||
{
|
||||
request_log("ENTER RequestQueryImageFormats\n");
|
||||
formats[0].fourcc = VA_FOURCC_NV12;
|
||||
*formats_count = 1;
|
||||
|
||||
@@ -221,6 +225,7 @@ VAStatus RequestQueryImageFormats(VADriverContextP context,
|
||||
VAStatus RequestSetImagePalette(VADriverContextP context, VAImageID image_id,
|
||||
unsigned char *palette)
|
||||
{
|
||||
request_log("ENTER RequestSetImagePalette\n");
|
||||
return VA_STATUS_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
@@ -228,6 +233,7 @@ VAStatus RequestGetImage(VADriverContextP context, VASurfaceID surface_id,
|
||||
int x, int y, unsigned int width, unsigned int height,
|
||||
VAImageID image_id)
|
||||
{
|
||||
request_log("ENTER RequestGetImage\n");
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_surface *surface_object;
|
||||
struct object_image *image_object;
|
||||
@@ -254,5 +260,6 @@ VAStatus RequestPutImage(VADriverContextP context, VASurfaceID surface_id,
|
||||
int dst_x, int dst_y, unsigned int dst_width,
|
||||
unsigned int dst_height)
|
||||
{
|
||||
request_log("ENTER RequestPutImage\n");
|
||||
return VA_STATUS_ERROR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ sources = [
|
||||
'v4l2.c',
|
||||
'mpeg2.c',
|
||||
'h264.c',
|
||||
'h265.c'
|
||||
# 'h265.c' # Fourier-local: HEVC stripped (see commit log)
|
||||
]
|
||||
|
||||
headers = [
|
||||
@@ -64,7 +64,7 @@ headers = [
|
||||
'v4l2.h',
|
||||
'mpeg2.h',
|
||||
'h264.h',
|
||||
'h265.h'
|
||||
# 'h265.h' # Fourier-local: HEVC stripped (see commit log)
|
||||
]
|
||||
|
||||
includes = [
|
||||
|
||||
+3
-24
@@ -91,12 +91,6 @@ static VAStatus codec_store_buffer(struct request_data *driver_data,
|
||||
sizeof(surface_object->params.h264.picture));
|
||||
break;
|
||||
|
||||
case VAProfileHEVCMain:
|
||||
memcpy(&surface_object->params.h265.picture,
|
||||
buffer_object->data,
|
||||
sizeof(surface_object->params.h265.picture));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -114,12 +108,6 @@ static VAStatus codec_store_buffer(struct request_data *driver_data,
|
||||
sizeof(surface_object->params.h264.slice));
|
||||
break;
|
||||
|
||||
case VAProfileHEVCMain:
|
||||
memcpy(&surface_object->params.h265.slice,
|
||||
buffer_object->data,
|
||||
sizeof(surface_object->params.h265.slice));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -145,13 +133,6 @@ static VAStatus codec_store_buffer(struct request_data *driver_data,
|
||||
sizeof(surface_object->params.h264.matrix));
|
||||
break;
|
||||
|
||||
case VAProfileHEVCMain:
|
||||
memcpy(&surface_object->params.h265.iqmatrix,
|
||||
buffer_object->data,
|
||||
sizeof(surface_object->params.h265.iqmatrix));
|
||||
surface_object->params.h265.iqmatrix_set = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -189,11 +170,9 @@ static VAStatus codec_set_controls(struct request_data *driver_data,
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
break;
|
||||
|
||||
case VAProfileHEVCMain:
|
||||
rc = h265_set_controls(driver_data, context, surface_object);
|
||||
if (rc < 0)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
break;
|
||||
/* HEVC stripped: kernel V4L2_CID_MPEG_VIDEO_HEVC_* CIDs were renamed
|
||||
* to V4L2_CID_STATELESS_HEVC_* upstream, and ohm's hantro VPU has no
|
||||
* HEVC support anyway. Falls through to the default case below. */
|
||||
|
||||
default:
|
||||
return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "request.h"
|
||||
#include "utils.h"
|
||||
#include "v4l2.h"
|
||||
#include "video.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@@ -179,6 +180,19 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context)
|
||||
driver_data->video_fd = video_fd;
|
||||
driver_data->media_fd = media_fd;
|
||||
|
||||
/* Probe the CAPTURE pixel format eagerly so vaCreateContext doesn't
|
||||
* race ahead of vaCreateSurfaces. Fine if this returns NULL — we
|
||||
* still let the driver init succeed and let surface creation try
|
||||
* again later (preserves the original lazy behaviour for any caller
|
||||
* that needs it). */
|
||||
driver_data->video_format = video_format_probe(video_fd);
|
||||
if (driver_data->video_format != NULL)
|
||||
request_log("Init: detected CAPTURE format %s (mplane=%d)\n",
|
||||
driver_data->video_format->description,
|
||||
driver_data->video_format->v4l2_mplane);
|
||||
else
|
||||
request_log("Init: no CAPTURE format detected at probe time\n");
|
||||
|
||||
status = VA_STATUS_SUCCESS;
|
||||
goto complete;
|
||||
|
||||
|
||||
+67
-36
@@ -65,54 +65,60 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
|
||||
unsigned int index;
|
||||
unsigned int i, j;
|
||||
VASurfaceID id;
|
||||
bool found;
|
||||
int rc;
|
||||
|
||||
if (format != VA_RT_FORMAT_YUV420)
|
||||
request_log("CreateSurfaces2: format=0x%x %dx%d count=%d\n",
|
||||
format, width, height, surfaces_count);
|
||||
|
||||
if (format != VA_RT_FORMAT_YUV420) {
|
||||
request_log("CreateSurfaces2: rejecting RT_FORMAT 0x%x\n", format);
|
||||
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
|
||||
}
|
||||
|
||||
|
||||
if (!driver_data->video_format) {
|
||||
found = v4l2_find_format(driver_data->video_fd,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_PIX_FMT_SUNXI_TILED_NV12);
|
||||
if (found)
|
||||
video_format = video_format_find(V4L2_PIX_FMT_SUNXI_TILED_NV12);
|
||||
|
||||
found = v4l2_find_format(driver_data->video_fd,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_PIX_FMT_NV12);
|
||||
if (found)
|
||||
video_format = video_format_find(V4L2_PIX_FMT_NV12);
|
||||
|
||||
if (video_format == NULL)
|
||||
if (!driver_data->video_format) {
|
||||
/* Could happen if RequestInit's eager probe came back NULL —
|
||||
* try one more time here in case the device only became
|
||||
* format-enumerable after streaming setup. */
|
||||
driver_data->video_format = video_format_probe(driver_data->video_fd);
|
||||
if (driver_data->video_format == NULL) {
|
||||
request_log("CreateSurfaces2: video_format probe still NULL\n");
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
driver_data->video_format = video_format;
|
||||
video_format = driver_data->video_format;
|
||||
capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
|
||||
|
||||
capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
|
||||
|
||||
rc = v4l2_set_format(driver_data->video_fd, capture_type,
|
||||
video_format->v4l2_format, width, height);
|
||||
if (rc < 0)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
} else {
|
||||
video_format = driver_data->video_format;
|
||||
capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
|
||||
/* Set the CAPTURE format on first surface creation so the size is
|
||||
* pinned to the picture dimensions the caller passed in. */
|
||||
rc = v4l2_set_format(driver_data->video_fd, capture_type,
|
||||
video_format->v4l2_format, width, height);
|
||||
if (rc < 0) {
|
||||
request_log("CreateSurfaces2: S_FMT(CAPTURE) failed for fmt=0x%x %dx%d\n",
|
||||
video_format->v4l2_format, width, height);
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
rc = v4l2_get_format(driver_data->video_fd, capture_type, &format_width,
|
||||
&format_height, destination_bytesperlines,
|
||||
destination_sizes, NULL);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
request_log("CreateSurfaces2: G_FMT(CAPTURE) failed\n");
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
request_log("CreateSurfaces2: G_FMT got %dx%d bpl[0]=%d size[0]=%d\n",
|
||||
format_width, format_height,
|
||||
destination_bytesperlines[0], destination_sizes[0]);
|
||||
|
||||
destination_planes_count = video_format->planes_count;
|
||||
|
||||
rc = v4l2_create_buffers(driver_data->video_fd, capture_type,
|
||||
surfaces_count, &index_base);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
request_log("CreateSurfaces2: CREATE_BUFS(CAPTURE) failed\n");
|
||||
return VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
}
|
||||
request_log("CreateSurfaces2: CREATE_BUFS ok index_base=%u\n", index_base);
|
||||
|
||||
for (i = 0; i < surfaces_count; i++) {
|
||||
index = index_base + i;
|
||||
@@ -127,8 +133,10 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
|
||||
surface_object->destination_map_lengths,
|
||||
surface_object->destination_map_offsets,
|
||||
video_format->v4l2_buffers_count);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
request_log("CreateSurfaces2: QUERYBUF idx=%u failed\n", index);
|
||||
return VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
}
|
||||
|
||||
for (j = 0; j < video_format->v4l2_buffers_count; j++) {
|
||||
surface_object->destination_map[j] =
|
||||
@@ -138,8 +146,13 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
|
||||
driver_data->video_fd,
|
||||
surface_object->destination_map_offsets[j]);
|
||||
|
||||
if (surface_object->destination_map[j] == MAP_FAILED)
|
||||
if (surface_object->destination_map[j] == MAP_FAILED) {
|
||||
request_log("CreateSurfaces2: mmap idx=%u plane=%u len=%u offset=%u failed\n",
|
||||
index, j,
|
||||
surface_object->destination_map_lengths[j],
|
||||
surface_object->destination_map_offsets[j]);
|
||||
return VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -177,6 +190,9 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
|
||||
destination_bytesperlines[j];
|
||||
}
|
||||
} else {
|
||||
request_log("CreateSurfaces2: buffers_count=%u planes_count=%u mismatch\n",
|
||||
video_format->v4l2_buffers_count,
|
||||
destination_planes_count);
|
||||
return VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
}
|
||||
|
||||
@@ -345,6 +361,9 @@ VAStatus RequestQuerySurfaceAttributes(VADriverContextP context,
|
||||
int memory_types;
|
||||
unsigned int i = 0;
|
||||
|
||||
request_log("QuerySurfaceAttributes: config=%u attrs=%p count=%p\n",
|
||||
config, attributes, attributes_count);
|
||||
|
||||
attributes_list = malloc(attributes_list_size);
|
||||
memset(attributes_list, 0, attributes_list_size);
|
||||
|
||||
@@ -469,16 +488,26 @@ VAStatus RequestExportSurfaceHandle(VADriverContextP context,
|
||||
VAStatus status;
|
||||
int rc;
|
||||
|
||||
video_format = driver_data->video_format;
|
||||
if (video_format == NULL)
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
request_log("ExportSurfaceHandle: surface_id=%u mem_type=0x%x flags=0x%x\n",
|
||||
surface_id, mem_type, flags);
|
||||
|
||||
if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
|
||||
video_format = driver_data->video_format;
|
||||
if (video_format == NULL) {
|
||||
request_log("ExportSurfaceHandle: video_format NULL\n");
|
||||
return VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) {
|
||||
request_log("ExportSurfaceHandle: rejecting mem_type 0x%x (only DRM_PRIME_2)\n",
|
||||
mem_type);
|
||||
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
|
||||
}
|
||||
|
||||
surface_object = SURFACE(driver_data, surface_id);
|
||||
if (surface_object == NULL)
|
||||
if (surface_object == NULL) {
|
||||
request_log("ExportSurfaceHandle: invalid surface_id\n");
|
||||
return VA_STATUS_ERROR_INVALID_SURFACE;
|
||||
}
|
||||
|
||||
export_fds_count = surface_object->destination_buffers_count;
|
||||
export_fds = malloc(export_fds_count * sizeof(*export_fds));
|
||||
@@ -489,6 +518,8 @@ VAStatus RequestExportSurfaceHandle(VADriverContextP context,
|
||||
surface_object->destination_index, O_RDONLY,
|
||||
export_fds, export_fds_count);
|
||||
if (rc < 0) {
|
||||
request_log("ExportSurfaceHandle: EXPBUF idx=%u count=%u failed\n",
|
||||
surface_object->destination_index, export_fds_count);
|
||||
status = VA_STATUS_ERROR_OPERATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -182,4 +182,19 @@ thumb_function tiled_deinterleave_to_planar
|
||||
b 7b
|
||||
end_function tiled_deinterleave_to_planar
|
||||
|
||||
#else /* __aarch64__ */
|
||||
|
||||
/* Fourier-local: aarch64 stub. The body of this file is ARMv7 NEON Thumb
|
||||
* assembly used by sunxi-cedrus (Allwinner-tiled NV12 → linear NV12) and
|
||||
* is never reached on aarch64 hosts because video_format_is_linear()
|
||||
* returns true for our NV12 entries. Provide a stub so the shared object
|
||||
* still resolves the symbol; if ever actually called, return immediately. */
|
||||
.text
|
||||
.global tiled_to_planar
|
||||
.type tiled_to_planar, %function
|
||||
.hidden tiled_to_planar
|
||||
tiled_to_planar:
|
||||
ret
|
||||
.size tiled_to_planar, .-tiled_to_planar
|
||||
|
||||
#endif
|
||||
|
||||
+14
@@ -33,10 +33,24 @@
|
||||
void request_log(const char *format, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
static FILE *trace_fp;
|
||||
|
||||
fprintf(stderr, "%s: ", V4L2_REQUEST_STR_VENDOR);
|
||||
|
||||
va_start(arguments, format);
|
||||
vfprintf(stderr, format, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
/* Fourier-local: also tee to /tmp/libva-fourier.log so messages are
|
||||
* visible from sandboxed GPU processes (Chromium etc.) where stderr
|
||||
* is redirected. Append-mode, lazy-open. */
|
||||
if (trace_fp == NULL)
|
||||
trace_fp = fopen("/tmp/libva-fourier.log", "a");
|
||||
if (trace_fp != NULL) {
|
||||
fprintf(trace_fp, "%s: ", V4L2_REQUEST_STR_VENDOR);
|
||||
va_start(arguments, format);
|
||||
vfprintf(trace_fp, format, arguments);
|
||||
va_end(arguments);
|
||||
fflush(trace_fp);
|
||||
}
|
||||
}
|
||||
|
||||
+48
-2
@@ -32,6 +32,7 @@
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "v4l2.h"
|
||||
#include "video.h"
|
||||
|
||||
static struct video_format formats[] = {
|
||||
@@ -45,6 +46,16 @@ static struct video_format formats[] = {
|
||||
.planes_count = 2,
|
||||
.bpp = 16,
|
||||
},
|
||||
{
|
||||
.description = "NV12 YUV (multi-plane)",
|
||||
.v4l2_format = V4L2_PIX_FMT_NV12,
|
||||
.v4l2_buffers_count = 1,
|
||||
.v4l2_mplane = true,
|
||||
.drm_format = DRM_FORMAT_NV12,
|
||||
.drm_modifier = DRM_FORMAT_MOD_NONE,
|
||||
.planes_count = 2,
|
||||
.bpp = 16,
|
||||
},
|
||||
{
|
||||
.description = "Sunxi tiled NV12 YUV",
|
||||
.v4l2_format = V4L2_PIX_FMT_SUNXI_TILED_NV12,
|
||||
@@ -59,17 +70,52 @@ static struct video_format formats[] = {
|
||||
|
||||
static unsigned int formats_count = sizeof(formats) / sizeof(formats[0]);
|
||||
|
||||
struct video_format *video_format_find(unsigned int pixelformat)
|
||||
struct video_format *video_format_find(unsigned int pixelformat, bool mplane)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < formats_count; i++)
|
||||
if (formats[i].v4l2_format == pixelformat)
|
||||
if (formats[i].v4l2_format == pixelformat &&
|
||||
formats[i].v4l2_mplane == mplane)
|
||||
return &formats[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe the V4L2 video device for a supported CAPTURE pixel format and
|
||||
* return the matching video_format entry. Tries single-plane CAPTURE first
|
||||
* (the original sunxi-cedrus path: SUNXI_TILED_NV12 or NV12), then falls
|
||||
* back to multi-plane CAPTURE (Rockchip hantro / RK3588 VDPU381). Returns
|
||||
* NULL if no match.
|
||||
*
|
||||
* Centralised here so RequestInit can populate driver_data->video_format
|
||||
* before any vaCreateContext call. The original library set it lazily in
|
||||
* RequestCreateSurfaces, but Chromium's vaapi_video_decoder may call
|
||||
* vaCreateContext first (with surfaces=NULL, surfaces_count=0) and only
|
||||
* create surfaces afterwards via vaCreateSurfaces2.
|
||||
*/
|
||||
struct video_format *video_format_probe(int video_fd)
|
||||
{
|
||||
struct video_format *format = NULL;
|
||||
|
||||
if (v4l2_find_format(video_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_PIX_FMT_SUNXI_TILED_NV12))
|
||||
format = video_format_find(V4L2_PIX_FMT_SUNXI_TILED_NV12, false);
|
||||
|
||||
if (format == NULL &&
|
||||
v4l2_find_format(video_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_PIX_FMT_NV12))
|
||||
format = video_format_find(V4L2_PIX_FMT_NV12, false);
|
||||
|
||||
if (format == NULL &&
|
||||
v4l2_find_format(video_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
|
||||
V4L2_PIX_FMT_NV12))
|
||||
format = video_format_find(V4L2_PIX_FMT_NV12, true);
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
bool video_format_is_linear(struct video_format *format)
|
||||
{
|
||||
if (format == NULL)
|
||||
|
||||
+2
-1
@@ -38,7 +38,8 @@ struct video_format {
|
||||
unsigned int bpp;
|
||||
};
|
||||
|
||||
struct video_format *video_format_find(unsigned int pixelformat);
|
||||
struct video_format *video_format_find(unsigned int pixelformat, bool mplane);
|
||||
struct video_format *video_format_probe(int video_fd);
|
||||
bool video_format_is_linear(struct video_format *format);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user