b47938e0bc
build and publish packages / distcc-avahi-aarch64 (push) Successful in 1m3s
build and publish packages / lmcp-any (push) Successful in 9s
build and publish packages / lmcp-debian (push) Successful in 4s
build and publish packages / claude-his-any (push) Failing after 4s
build and publish packages / ffmpeg-v4l2-request-aarch64 (push) Has been skipped
build and publish packages / claude-his-debian (push) Has been skipped
Mirrors phase6/step1/ from the ohm_gl_fix campaign. Contract-correct
hantro multi-planar / chromium-149-era stateless H.264 port of
bootlin's libva-v4l2-request, patches 0001..0018 + fourier-local.
Honest characterisation in README:
- Builds cleanly on chromium-builder LXC (boltzmann)
- vainfo enumerates H.264 profiles cleanly with LIBVA_DRIVER_NAME=v4l2_request
- NOT on Brave's decode path on ohm_gl_fix stack — Brave uses
Chromium's own V4L2VideoDecoder in media/gpu/v4l2/.
- Most likely useful for a future Firefox-via-libavcodec-vaapi
campaign, modulo a separate Mesa-panfrost WSI pitch issue.
- DEBUG patches (0010, 0011, 0014) intentionally kept in series
for development; remove for cleaner production runs.
Audit trail in the source repo at ohm_gl_fix:
phase6/step1/audit_0008_decode_params_2026-05-01.md
phase6/step1/api_contract_findings_2026-05-01.md
phase3_remeasure_2026-05-02/B3_decoder_discovery.md (why this
isn't on Brave's path)
1058 lines
33 KiB
Diff
1058 lines
33 KiB
Diff
diff --git a/include/h264-ctrls.h b/include/h264-ctrls.h
|
|
index e1404d7..e877bf1 100644
|
|
--- a/include/h264-ctrls.h
|
|
+++ b/include/h264-ctrls.h
|
|
@@ -14,7 +14,7 @@
|
|
#include <linux/videodev2.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 */
|
|
+#define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */
|
|
|
|
/*
|
|
* This is put insanely high to avoid conflicting with controls that
|
|
@@ -26,6 +26,8 @@
|
|
#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)
|
|
+#define V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE (V4L2_CID_MPEG_BASE+1005)
|
|
+#define V4L2_CID_MPEG_VIDEO_H264_START_CODE (V4L2_CID_MPEG_BASE+1006)
|
|
|
|
/* enum v4l2_ctrl_type type values */
|
|
#define V4L2_CTRL_TYPE_H264_SPS 0x0110
|
|
@@ -34,6 +36,16 @@
|
|
#define V4L2_CTRL_TYPE_H264_SLICE_PARAMS 0x0113
|
|
#define V4L2_CTRL_TYPE_H264_DECODE_PARAMS 0x0114
|
|
|
|
+enum v4l2_mpeg_video_h264_decode_mode {
|
|
+ V4L2_MPEG_VIDEO_H264_DECODE_MODE_SLICE_BASED,
|
|
+ V4L2_MPEG_VIDEO_H264_DECODE_MODE_FRAME_BASED,
|
|
+};
|
|
+
|
|
+enum v4l2_mpeg_video_h264_start_code {
|
|
+ V4L2_MPEG_VIDEO_H264_START_CODE_NONE,
|
|
+ V4L2_MPEG_VIDEO_H264_START_CODE_ANNEX_B,
|
|
+};
|
|
+
|
|
#define V4L2_H264_SPS_CONSTRAINT_SET0_FLAG 0x01
|
|
#define V4L2_H264_SPS_CONSTRAINT_SET1_FLAG 0x02
|
|
#define V4L2_H264_SPS_CONSTRAINT_SET2_FLAG 0x04
|
|
@@ -125,6 +137,10 @@ struct v4l2_h264_pred_weight_table {
|
|
struct v4l2_ctrl_h264_slice_params {
|
|
/* Size in bytes, including header */
|
|
__u32 size;
|
|
+
|
|
+ /* Offset in bytes to the start of slice in the OUTPUT buffer. */
|
|
+ __u32 start_byte_offset;
|
|
+
|
|
/* Offset in bits to slice_data() from the beginning of this slice. */
|
|
__u32 header_bit_size;
|
|
|
|
@@ -186,9 +202,6 @@ 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_* */
|
|
diff --git a/include/hevc-ctrls.h b/include/hevc-ctrls.h
|
|
index 2de83d9..d802692 100644
|
|
--- a/include/hevc-ctrls.h
|
|
+++ b/include/hevc-ctrls.h
|
|
@@ -1,185 +1,9 @@
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
-/*
|
|
- * These are the HEVC state controls for use with stateless HEVC
|
|
- * codec drivers.
|
|
- *
|
|
- * 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.
|
|
- */
|
|
-
|
|
-#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];
|
|
-};
|
|
-
|
|
+/* Fourier-local override: HEVC controls are upstream since linux-media
|
|
+ * 6.6+, so defer to the kernel's linux/v4l2-controls.h instead of
|
|
+ * duplicating the struct definitions (duplication causes redefinition
|
|
+ * errors on newer linux-api-headers). */
|
|
+#ifndef _LIBVA_V4L2_REQUEST_HEVC_CTRLS_H
|
|
+#define _LIBVA_V4L2_REQUEST_HEVC_CTRLS_H
|
|
+#include <linux/v4l2-controls.h>
|
|
#endif
|
|
diff --git a/src/config.c b/src/config.c
|
|
index e396268..04a9c3a 100644
|
|
--- a/src/config.c
|
|
+++ b/src/config.c
|
|
@@ -35,7 +35,6 @@
|
|
#include <linux/videodev2.h>
|
|
|
|
#include <mpeg2-ctrls.h>
|
|
-#include <h264-ctrls.h>
|
|
#include <hevc-ctrls.h>
|
|
|
|
#include "utils.h"
|
|
@@ -54,18 +53,17 @@ VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile,
|
|
int i, index;
|
|
|
|
switch (profile) {
|
|
- case VAProfileMPEG2Simple:
|
|
- case VAProfileMPEG2Main:
|
|
+
|
|
case VAProfileH264Main:
|
|
case VAProfileH264High:
|
|
case VAProfileH264ConstrainedBaseline:
|
|
case VAProfileH264MultiviewHigh:
|
|
case VAProfileH264StereoHigh:
|
|
- case VAProfileHEVCMain:
|
|
- if (entrypoint != VAEntrypointVLD)
|
|
- return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
|
|
+ // FIXME
|
|
break;
|
|
-
|
|
+ case VAProfileMPEG2Simple:
|
|
+ case VAProfileMPEG2Main:
|
|
+ case VAProfileHEVCMain:
|
|
default:
|
|
return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
|
}
|
|
@@ -120,6 +118,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 +129,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 +143,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;
|
|
diff --git a/src/config.h b/src/config.h
|
|
index b7b12e7..1377e49 100644
|
|
--- a/src/config.h
|
|
+++ b/src/config.h
|
|
@@ -43,6 +43,7 @@ struct object_config {
|
|
VAEntrypoint entrypoint;
|
|
VAConfigAttrib attributes[V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES];
|
|
int attributes_count;
|
|
+ unsigned int pixelformat;
|
|
};
|
|
|
|
VAStatus RequestCreateConfig(VADriverContextP context, VAProfile profile,
|
|
diff --git a/src/context.c b/src/context.c
|
|
index 04ba9a6..d07cea6 100644
|
|
--- a/src/context.c
|
|
+++ b/src/context.c
|
|
@@ -40,7 +40,6 @@
|
|
#include <linux/videodev2.h>
|
|
|
|
#include <mpeg2-ctrls.h>
|
|
-#include <h264-ctrls.h>
|
|
#include <hevc-ctrls.h>
|
|
|
|
#include "utils.h"
|
|
@@ -65,7 +64,6 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
|
VAContextID id;
|
|
VAStatus status;
|
|
unsigned int output_type, capture_type;
|
|
- unsigned int pixelformat;
|
|
unsigned int index_base;
|
|
unsigned int index;
|
|
unsigned int i;
|
|
@@ -92,37 +90,6 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
|
}
|
|
memset(&context_object->dpb, 0, sizeof(context_object->dpb));
|
|
|
|
- switch (config_object->profile) {
|
|
-
|
|
- case VAProfileMPEG2Simple:
|
|
- case VAProfileMPEG2Main:
|
|
- pixelformat = V4L2_PIX_FMT_MPEG2_SLICE;
|
|
- break;
|
|
-
|
|
- case VAProfileH264Main:
|
|
- case VAProfileH264High:
|
|
- case VAProfileH264ConstrainedBaseline:
|
|
- case VAProfileH264MultiviewHigh:
|
|
- case VAProfileH264StereoHigh:
|
|
- pixelformat = V4L2_PIX_FMT_H264_SLICE_RAW;
|
|
- break;
|
|
-
|
|
- case VAProfileHEVCMain:
|
|
- pixelformat = V4L2_PIX_FMT_HEVC_SLICE;
|
|
- break;
|
|
-
|
|
- default:
|
|
- status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
|
- goto error;
|
|
- }
|
|
-
|
|
- rc = v4l2_set_format(driver_data->video_fd, output_type, pixelformat,
|
|
- picture_width, picture_height);
|
|
- if (rc < 0) {
|
|
- status = VA_STATUS_ERROR_OPERATION_FAILED;
|
|
- goto error;
|
|
- }
|
|
-
|
|
rc = v4l2_create_buffers(driver_data->video_fd, output_type,
|
|
surfaces_count, &index_base);
|
|
if (rc < 0) {
|
|
diff --git a/src/context.h b/src/context.h
|
|
index cd0910a..8f4f70f 100644
|
|
--- a/src/context.h
|
|
+++ b/src/context.h
|
|
@@ -50,6 +50,7 @@ struct object_context {
|
|
|
|
/* H264 only */
|
|
struct h264_dpb dpb;
|
|
+ bool h264_start_code;
|
|
};
|
|
|
|
VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
|
diff --git a/src/h264.c b/src/h264.c
|
|
index 25bc8cb..fb6c13a 100644
|
|
--- a/src/h264.c
|
|
+++ b/src/h264.c
|
|
@@ -33,9 +33,9 @@
|
|
#include <sys/mman.h>
|
|
|
|
#include <linux/videodev2.h>
|
|
-#include <h264-ctrls.h>
|
|
|
|
#include "request.h"
|
|
+#include "utils.h"
|
|
#include "surface.h"
|
|
#include "v4l2.h"
|
|
|
|
@@ -95,7 +95,8 @@ static struct h264_dpb_entry *dpb_find_entry(struct object_context *context)
|
|
}
|
|
|
|
static struct h264_dpb_entry *dpb_lookup(struct object_context *context,
|
|
- VAPictureH264 *pic, unsigned int *idx)
|
|
+ VAPictureH264 *pic, unsigned int *idx,
|
|
+ unsigned char *fields)
|
|
{
|
|
unsigned int i;
|
|
|
|
@@ -109,6 +110,16 @@ static struct h264_dpb_entry *dpb_lookup(struct object_context *context,
|
|
if (idx)
|
|
*idx = i;
|
|
|
|
+ if (fields) {
|
|
+ //if (entry->pic.TopFieldOrderCnt < entry->pic.BottomFieldOrderCnt) {
|
|
+ // *fields = V4L2_H264_TOP_FIELD_REF;
|
|
+ //} else if (entry->pic.TopFieldOrderCnt > entry->pic.BottomFieldOrderCnt) {
|
|
+ // *fields = V4L2_H264_BOTTOM_FIELD_REF;
|
|
+ //} else {
|
|
+ *fields = V4L2_H264_FRAME_REF;
|
|
+ //}
|
|
+ }
|
|
+
|
|
return entry;
|
|
}
|
|
}
|
|
@@ -130,7 +141,7 @@ static void dpb_insert(struct object_context *context, VAPictureH264 *pic,
|
|
if (is_picture_null(pic))
|
|
return;
|
|
|
|
- if (dpb_lookup(context, pic, NULL))
|
|
+ if (dpb_lookup(context, pic, NULL, NULL))
|
|
return;
|
|
|
|
if (!entry)
|
|
@@ -165,7 +176,7 @@ static void dpb_update(struct object_context *context,
|
|
if (is_picture_null(pic))
|
|
continue;
|
|
|
|
- entry = dpb_lookup(context, pic, NULL);
|
|
+ entry = dpb_lookup(context, pic, NULL, NULL);
|
|
if (entry) {
|
|
entry->age = context->dpb.age;
|
|
entry->used = true;
|
|
@@ -197,6 +208,7 @@ static void h264_fill_dpb(struct request_data *data,
|
|
}
|
|
|
|
dpb->frame_num = entry->pic.frame_idx;
|
|
+ dpb->pic_num = entry->pic.picture_id;
|
|
dpb->top_field_order_cnt = entry->pic.TopFieldOrderCnt;
|
|
dpb->bottom_field_order_cnt = entry->pic.BottomFieldOrderCnt;
|
|
|
|
@@ -218,9 +230,23 @@ static void h264_va_picture_to_v4l2(struct request_data *driver_data,
|
|
struct v4l2_ctrl_h264_pps *pps,
|
|
struct v4l2_ctrl_h264_sps *sps)
|
|
{
|
|
+ unsigned char *b;
|
|
+ unsigned char nal_ref_idc;
|
|
+ unsigned char nal_unit_type;
|
|
+
|
|
+ /* Extract missing nal_ref_idc and nal_unit_type */
|
|
+ b = surface->source_data;
|
|
+ if (context->h264_start_code)
|
|
+ b += 3;
|
|
+ nal_ref_idc = (b[0] >> 5) & 0x3;
|
|
+ nal_unit_type = b[0] & 0x1f;
|
|
+
|
|
h264_fill_dpb(driver_data, context, decode);
|
|
|
|
- decode->num_slices = surface->slices_count;
|
|
+ //decode->num_slices = surface->slices_count;
|
|
+ decode->nal_ref_idc = nal_ref_idc;
|
|
+ if (nal_unit_type == 5)
|
|
+ decode->flags = V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC;
|
|
decode->top_field_order_cnt = VAPicture->CurrPic.TopFieldOrderCnt;
|
|
decode->bottom_field_order_cnt = VAPicture->CurrPic.BottomFieldOrderCnt;
|
|
|
|
@@ -255,6 +281,7 @@ static void h264_va_picture_to_v4l2(struct request_data *driver_data,
|
|
if (VAPicture->pic_fields.bits.redundant_pic_cnt_present_flag)
|
|
pps->flags |= V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT;
|
|
|
|
+ sps->max_num_ref_frames = VAPicture->num_ref_frames;
|
|
sps->chroma_format_idc = VAPicture->seq_fields.bits.chroma_format_idc;
|
|
sps->bit_depth_luma_minus8 = VAPicture->bit_depth_luma_minus8;
|
|
sps->bit_depth_chroma_minus8 = VAPicture->bit_depth_chroma_minus8;
|
|
@@ -327,10 +354,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 *weights)
|
|
{
|
|
- slice->size = VASlice->slice_data_size;
|
|
slice->header_bit_size = VASlice->slice_data_bit_offset;
|
|
+ //if (context->h264_start_code)
|
|
+ // slice->header_bit_size += 3 * 8;
|
|
slice->first_mb_in_slice = VASlice->first_mb_in_slice;
|
|
slice->slice_type = VASlice->slice_type;
|
|
slice->cabac_init_idc = VASlice->cabac_init_idc;
|
|
@@ -351,12 +380,14 @@ static void h264_va_slice_to_v4l2(struct request_data *driver_data,
|
|
VAPictureH264 *pic = &VASlice->RefPicList0[i];
|
|
struct h264_dpb_entry *entry;
|
|
unsigned int idx;
|
|
+ unsigned char fields;
|
|
|
|
- entry = dpb_lookup(context, pic, &idx);
|
|
+ entry = dpb_lookup(context, pic, &idx, &fields);
|
|
if (!entry)
|
|
continue;
|
|
|
|
- slice->ref_pic_list0[i] = idx;
|
|
+ slice->ref_pic_list0[i].index = idx;
|
|
+ slice->ref_pic_list0[i].fields = fields;
|
|
}
|
|
}
|
|
|
|
@@ -370,26 +401,28 @@ static void h264_va_slice_to_v4l2(struct request_data *driver_data,
|
|
VAPictureH264 *pic = &VASlice->RefPicList1[i];
|
|
struct h264_dpb_entry *entry;
|
|
unsigned int idx;
|
|
+ unsigned char fields;
|
|
|
|
- entry = dpb_lookup(context, pic, &idx);
|
|
+ entry = dpb_lookup(context, pic, &idx, &fields);
|
|
if (!entry)
|
|
continue;
|
|
|
|
- slice->ref_pic_list1[i] = idx;
|
|
+ slice->ref_pic_list1[i].index = idx;
|
|
+ slice->ref_pic_list0[i].fields = fields;
|
|
}
|
|
}
|
|
|
|
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 =
|
|
+ weights->chroma_log2_weight_denom =
|
|
VASlice->chroma_log2_weight_denom;
|
|
- slice->pred_weight_table.luma_log2_weight_denom =
|
|
+ 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(&weights->weight_factors[0],
|
|
slice->num_ref_idx_l0_active_minus1 + 1,
|
|
VASlice->luma_weight_l0,
|
|
VASlice->luma_offset_l0,
|
|
@@ -397,7 +430,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(&weights->weight_factors[1],
|
|
slice->num_ref_idx_l1_active_minus1 + 1,
|
|
VASlice->luma_weight_l1,
|
|
VASlice->luma_offset_l1,
|
|
@@ -405,20 +438,81 @@ static void h264_va_slice_to_v4l2(struct request_data *driver_data,
|
|
VASlice->chroma_offset_l1);
|
|
}
|
|
|
|
+int h264_get_controls(struct request_data *driver_data,
|
|
+ struct object_context *context)
|
|
+{
|
|
+ struct v4l2_ext_control controls[2] = {
|
|
+ {
|
|
+ .id = V4L2_CID_STATELESS_H264_DECODE_MODE,
|
|
+ }, {
|
|
+ .id = V4L2_CID_STATELESS_H264_START_CODE,
|
|
+ }
|
|
+ };
|
|
+ int rc;
|
|
+
|
|
+ rc = v4l2_get_controls(driver_data->video_fd, -1, controls, 2);
|
|
+ if (rc < 0)
|
|
+ return VA_STATUS_ERROR_OPERATION_FAILED;
|
|
+
|
|
+ switch (controls[0].value) {
|
|
+ case V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED:
|
|
+ break;
|
|
+ case V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED:
|
|
+ break;
|
|
+ default:
|
|
+ request_log("Unsupported decode mode\n");
|
|
+ return VA_STATUS_ERROR_OPERATION_FAILED;
|
|
+ }
|
|
+
|
|
+ switch (controls[1].value) {
|
|
+ case V4L2_STATELESS_H264_START_CODE_NONE:
|
|
+ context->h264_start_code = false;
|
|
+ break;
|
|
+ case V4L2_STATELESS_H264_START_CODE_ANNEX_B:
|
|
+ context->h264_start_code = true;
|
|
+ break;
|
|
+ default:
|
|
+ request_log("Unsupported start code\n");
|
|
+ return VA_STATUS_ERROR_OPERATION_FAILED;
|
|
+ }
|
|
+
|
|
+ return VA_STATUS_SUCCESS;
|
|
+}
|
|
+
|
|
+static inline __u8 h264_profile_to_idc(VAProfile profile)
|
|
+{
|
|
+ switch (profile) {
|
|
+ case VAProfileH264Main:
|
|
+ return 77;
|
|
+ case VAProfileH264High:
|
|
+ return 100;
|
|
+ case VAProfileH264ConstrainedBaseline:
|
|
+ return 66;
|
|
+ case VAProfileH264MultiviewHigh:
|
|
+ return 118;
|
|
+ case VAProfileH264StereoHigh:
|
|
+ return 128;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
int h264_set_controls(struct request_data *driver_data,
|
|
struct object_context *context,
|
|
+ VAProfile profile,
|
|
struct object_surface *surface)
|
|
{
|
|
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 weights = { 0 };
|
|
struct v4l2_ctrl_h264_pps pps = { 0 };
|
|
struct v4l2_ctrl_h264_sps sps = { 0 };
|
|
struct h264_dpb_entry *output;
|
|
int rc;
|
|
|
|
output = dpb_lookup(context, &surface->params.h264.picture.CurrPic,
|
|
- NULL);
|
|
+ NULL, NULL);
|
|
if (!output)
|
|
output = dpb_find_entry(context);
|
|
|
|
@@ -433,33 +527,40 @@ 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);
|
|
-
|
|
- rc = v4l2_set_control(driver_data->video_fd, surface->request_fd,
|
|
- V4L2_CID_MPEG_VIDEO_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,
|
|
- 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));
|
|
- 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));
|
|
- if (rc < 0)
|
|
- return VA_STATUS_ERROR_OPERATION_FAILED;
|
|
+ &surface->params.h264.picture, &slice, &weights);
|
|
+
|
|
+ sps.profile_idc = h264_profile_to_idc(profile);
|
|
+
|
|
+ struct v4l2_ext_control controls[6] = {
|
|
+ {
|
|
+ .id = V4L2_CID_STATELESS_H264_SPS,
|
|
+ .p_h264_sps = &sps,
|
|
+ .size = sizeof(sps),
|
|
+ }, {
|
|
+ .id = V4L2_CID_STATELESS_H264_PPS,
|
|
+ .p_h264_pps = &pps,
|
|
+ .size = sizeof(pps),
|
|
+ }, {
|
|
+ .id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
|
|
+ .p_h264_scaling_matrix = &matrix,
|
|
+ .size = sizeof(matrix),
|
|
+ }, {
|
|
+ .id = V4L2_CID_STATELESS_H264_SLICE_PARAMS,
|
|
+ .p_h264_slice_params = &slice,
|
|
+ .size = sizeof(slice),
|
|
+ }, {
|
|
+ .id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
|
|
+ .p_h264_decode_params = &decode,
|
|
+ .size = sizeof(decode),
|
|
+ }, {
|
|
+ .id = V4L2_CID_STATELESS_H264_PRED_WEIGHTS,
|
|
+ .ptr = &weights,
|
|
+ .size = sizeof(weights),
|
|
+ }
|
|
+ };
|
|
|
|
- rc = v4l2_set_control(driver_data->video_fd, surface->request_fd,
|
|
- V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX, &matrix,
|
|
- sizeof(matrix));
|
|
+ rc = v4l2_set_controls(driver_data->video_fd, surface->request_fd,
|
|
+ controls, 6);
|
|
if (rc < 0)
|
|
return VA_STATUS_ERROR_OPERATION_FAILED;
|
|
|
|
diff --git a/src/h264.h b/src/h264.h
|
|
index 35ef31d..da0b87f 100644
|
|
--- a/src/h264.h
|
|
+++ b/src/h264.h
|
|
@@ -51,8 +51,11 @@ struct h264_dpb {
|
|
unsigned int age;
|
|
};
|
|
|
|
+int h264_get_controls(struct request_data *driver_data,
|
|
+ struct object_context *context);
|
|
int h264_set_controls(struct request_data *data,
|
|
struct object_context *context,
|
|
+ VAProfile profile,
|
|
struct object_surface *surface);
|
|
|
|
#endif
|
|
diff --git a/src/image.c b/src/image.c
|
|
index fa8b0ea..05ed455 100644
|
|
--- a/src/image.c
|
|
+++ b/src/image.c
|
|
@@ -155,6 +155,7 @@ static VAStatus copy_surface_to_image (struct request_data *driver_data,
|
|
return VA_STATUS_ERROR_INVALID_BUFFER;
|
|
|
|
for (i = 0; i < surface_object->destination_planes_count; i++) {
|
|
+#ifdef __arm__
|
|
if (!video_format_is_linear(driver_data->video_format))
|
|
tiled_to_planar(surface_object->destination_data[i],
|
|
buffer_object->data + image->offsets[i],
|
|
@@ -162,10 +163,13 @@ static VAStatus copy_surface_to_image (struct request_data *driver_data,
|
|
i == 0 ? image->height :
|
|
image->height / 2);
|
|
else {
|
|
+#endif
|
|
memcpy(buffer_object->data + image->offsets[i],
|
|
surface_object->destination_data[i],
|
|
surface_object->destination_sizes[i]);
|
|
+#ifdef __arm__
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
return VA_STATUS_SUCCESS;
|
|
diff --git a/src/meson.build b/src/meson.build
|
|
index d73abb1..b7ed642 100644
|
|
--- a/src/meson.build
|
|
+++ b/src/meson.build
|
|
@@ -44,7 +44,7 @@ sources = [
|
|
'v4l2.c',
|
|
'mpeg2.c',
|
|
'h264.c',
|
|
- 'h265.c'
|
|
+# 'h265.c'
|
|
]
|
|
|
|
headers = [
|
|
@@ -64,7 +64,7 @@ headers = [
|
|
'v4l2.h',
|
|
'mpeg2.h',
|
|
'h264.h',
|
|
- 'h265.h'
|
|
+# 'h265.h'
|
|
]
|
|
|
|
includes = [
|
|
diff --git a/src/picture.c b/src/picture.c
|
|
index aa86265..3713f00 100644
|
|
--- a/src/picture.c
|
|
+++ b/src/picture.c
|
|
@@ -51,6 +51,7 @@
|
|
#include "autoconfig.h"
|
|
|
|
static VAStatus codec_store_buffer(struct request_data *driver_data,
|
|
+ struct object_context *context,
|
|
VAProfile profile,
|
|
struct object_surface *surface_object,
|
|
struct object_buffer *buffer_object)
|
|
@@ -63,6 +64,14 @@ static VAStatus codec_store_buffer(struct request_data *driver_data,
|
|
* RenderPicture), we can't use a V4L2 buffer directly
|
|
* and have to copy from a regular buffer.
|
|
*/
|
|
+ if (context->h264_start_code) {
|
|
+ static const char start_code[3] = { 0x00, 0x00, 0x01 };
|
|
+
|
|
+ memcpy(surface_object->source_data +
|
|
+ surface_object->slices_size,
|
|
+ start_code, sizeof(start_code));
|
|
+ surface_object->slices_size += sizeof(start_code);
|
|
+ }
|
|
memcpy(surface_object->source_data +
|
|
surface_object->slices_size,
|
|
buffer_object->data,
|
|
@@ -184,16 +193,15 @@ static VAStatus codec_set_controls(struct request_data *driver_data,
|
|
case VAProfileH264ConstrainedBaseline:
|
|
case VAProfileH264MultiviewHigh:
|
|
case VAProfileH264StereoHigh:
|
|
- rc = h264_set_controls(driver_data, context, surface_object);
|
|
+ rc = h264_set_controls(driver_data, context, profile,
|
|
+ surface_object);
|
|
if (rc < 0)
|
|
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;
|
|
+ /* Fourier-local: HEVC stripped, no HW support on RK3566. */
|
|
+ return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
|
|
|
default:
|
|
return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
|
@@ -255,7 +263,8 @@ VAStatus RequestRenderPicture(VADriverContextP context, VAContextID context_id,
|
|
if (buffer_object == NULL)
|
|
return VA_STATUS_ERROR_INVALID_BUFFER;
|
|
|
|
- rc = codec_store_buffer(driver_data, config_object->profile,
|
|
+ rc = codec_store_buffer(driver_data, context_object,
|
|
+ config_object->profile,
|
|
surface_object, buffer_object);
|
|
if (rc != VA_STATUS_SUCCESS)
|
|
return rc;
|
|
diff --git a/src/surface.c b/src/surface.c
|
|
index a6abb9b..478f0cc 100644
|
|
--- a/src/surface.c
|
|
+++ b/src/surface.c
|
|
@@ -46,6 +46,8 @@
|
|
#include "v4l2.h"
|
|
#include "video.h"
|
|
|
|
+bool SET_FORMAT_OF_OUTPUT_ONCE = false;
|
|
+
|
|
VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
|
|
unsigned int width, unsigned int height,
|
|
VASurfaceID *surfaces_ids,
|
|
@@ -68,10 +70,34 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
|
|
bool found;
|
|
int rc;
|
|
|
|
+ //////////// HACK: this portion of the code should get cleaned up.
|
|
+
|
|
+ // v4l2_set_format needs to be called BEFORE we create any buffers
|
|
+ //
|
|
+ // we originally did this for the output stream in context.c, but
|
|
+ // RequestCreateSurfaces2 gets called multiple times before RequestCreateContext
|
|
+ // to allocate & map buffers. this doesn't seem to work in recent kernel versions.
|
|
+ //
|
|
+ // we declare SET_FORMAT_OF_OUTPUT_ONCE to ensure v4l2_set_format only gets called once
|
|
+ // (in the first RequestCreateSurfaces2 call BEFORE any buffers are created later on)
|
|
+ unsigned int pixelformat = V4L2_PIX_FMT_H264_SLICE;
|
|
+ unsigned int output_type = v4l2_type_video_output(false);
|
|
+
|
|
+ if (!SET_FORMAT_OF_OUTPUT_ONCE) {
|
|
+ rc = v4l2_set_format(driver_data->video_fd, output_type, pixelformat,
|
|
+ width, height);
|
|
+ if (rc < 0) {
|
|
+ return VA_STATUS_ERROR_OPERATION_FAILED;
|
|
+ }
|
|
+
|
|
+ SET_FORMAT_OF_OUTPUT_ONCE = true;
|
|
+ }
|
|
+
|
|
+ /////////// ENDHACK
|
|
+
|
|
if (format != VA_RT_FORMAT_YUV420)
|
|
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,
|
|
diff --git a/src/surface.h b/src/surface.h
|
|
index 41007f8..a9be915 100644
|
|
--- a/src/surface.h
|
|
+++ b/src/surface.h
|
|
@@ -40,7 +40,7 @@
|
|
struct object_surface {
|
|
struct object_base base;
|
|
|
|
- VAStatus status;
|
|
+ VASurfaceStatus status;
|
|
int width;
|
|
int height;
|
|
|
|
diff --git a/src/tiled_yuv.S b/src/tiled_yuv.S
|
|
index c6fa833..4bce33f 100644
|
|
--- a/src/tiled_yuv.S
|
|
+++ b/src/tiled_yuv.S
|
|
@@ -27,7 +27,7 @@
|
|
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
|
|
#endif
|
|
|
|
-#ifndef __aarch64__
|
|
+#ifdef __arm__
|
|
|
|
.text
|
|
.syntax unified
|
|
diff --git a/src/v4l2.c b/src/v4l2.c
|
|
index d5000ac..3addb33 100644
|
|
--- a/src/v4l2.c
|
|
+++ b/src/v4l2.c
|
|
@@ -428,37 +428,71 @@ int v4l2_export_buffer(int video_fd, unsigned int type, unsigned int index,
|
|
return 0;
|
|
}
|
|
|
|
-int v4l2_set_control(int video_fd, int request_fd, unsigned int id, void *data,
|
|
- unsigned int size)
|
|
+static int v4l2_ioctl_controls(int video_fd, int request_fd, unsigned long ioc,
|
|
+ struct v4l2_ext_control *control_array,
|
|
+ unsigned int num_controls)
|
|
{
|
|
- struct v4l2_ext_control control;
|
|
struct v4l2_ext_controls controls;
|
|
- int rc;
|
|
|
|
- memset(&control, 0, sizeof(control));
|
|
memset(&controls, 0, sizeof(controls));
|
|
|
|
- control.id = id;
|
|
- control.ptr = data;
|
|
- control.size = size;
|
|
-
|
|
- controls.controls = &control;
|
|
- controls.count = 1;
|
|
+ controls.controls = control_array;
|
|
+ controls.count = num_controls;
|
|
|
|
if (request_fd >= 0) {
|
|
controls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
|
|
controls.request_fd = request_fd;
|
|
}
|
|
|
|
- rc = ioctl(video_fd, VIDIOC_S_EXT_CTRLS, &controls);
|
|
+ return ioctl(video_fd, ioc, &controls);
|
|
+}
|
|
+
|
|
+int v4l2_get_controls(int video_fd, int request_fd,
|
|
+ struct v4l2_ext_control *control_array,
|
|
+ unsigned int num_controls)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = v4l2_ioctl_controls(video_fd, request_fd, VIDIOC_G_EXT_CTRLS,
|
|
+ control_array, num_controls);
|
|
if (rc < 0) {
|
|
- request_log("Unable to set control: %s\n", strerror(errno));
|
|
+ request_log("Unable to get control(s): %s\n", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
+int v4l2_set_controls(int video_fd, int request_fd,
|
|
+ struct v4l2_ext_control *control_array,
|
|
+ unsigned int num_controls)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = v4l2_ioctl_controls(video_fd, request_fd, VIDIOC_S_EXT_CTRLS,
|
|
+ control_array, num_controls);
|
|
+ if (rc < 0) {
|
|
+ request_log("Unable to set control(s): %s\n", strerror(errno));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int v4l2_set_control(int video_fd, int request_fd, unsigned int id, void *data,
|
|
+ unsigned int size)
|
|
+{
|
|
+ struct v4l2_ext_control control;
|
|
+
|
|
+ memset(&control, 0, sizeof(control));
|
|
+
|
|
+ control.id = id;
|
|
+ control.ptr = data;
|
|
+ control.size = size;
|
|
+
|
|
+ return v4l2_set_controls(video_fd, request_fd, &control, 1);
|
|
+}
|
|
+
|
|
int v4l2_set_stream(int video_fd, unsigned int type, bool enable)
|
|
{
|
|
enum v4l2_buf_type buf_type = type;
|
|
diff --git a/src/v4l2.h b/src/v4l2.h
|
|
index 73e9a42..24c12a0 100644
|
|
--- a/src/v4l2.h
|
|
+++ b/src/v4l2.h
|
|
@@ -54,6 +54,12 @@ int v4l2_dequeue_buffer(int video_fd, int request_fd, unsigned int type,
|
|
int v4l2_export_buffer(int video_fd, unsigned int type, unsigned int index,
|
|
unsigned int flags, int *export_fds,
|
|
unsigned int export_fds_count);
|
|
+int v4l2_get_controls(int video_fd, int request_fd,
|
|
+ struct v4l2_ext_control *controls,
|
|
+ unsigned int num_controls);
|
|
+int v4l2_set_controls(int video_fd, int request_fd,
|
|
+ struct v4l2_ext_control *controls,
|
|
+ unsigned int num_controls);
|
|
int v4l2_set_control(int video_fd, int request_fd, unsigned int id, void *data,
|
|
unsigned int size);
|
|
int v4l2_set_stream(int video_fd, unsigned int type, bool enable);
|
|
diff --git a/src/video.c b/src/video.c
|
|
index 3ccbb29..9fae332 100644
|
|
--- a/src/video.c
|
|
+++ b/src/video.c
|
|
@@ -45,6 +45,8 @@ static struct video_format formats[] = {
|
|
.planes_count = 2,
|
|
.bpp = 16,
|
|
},
|
|
+// Code to handle this DRM_FORMAT is __arm__ only
|
|
+#ifdef __arm__
|
|
{
|
|
.description = "Sunxi tiled NV12 YUV",
|
|
.v4l2_format = V4L2_PIX_FMT_SUNXI_TILED_NV12,
|
|
@@ -55,6 +57,7 @@ static struct video_format formats[] = {
|
|
.planes_count = 2,
|
|
.bpp = 16
|
|
},
|
|
+#endif
|
|
};
|
|
|
|
static unsigned int formats_count = sizeof(formats) / sizeof(formats[0]);
|