1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
From 0a4165c181d6b65e753be675d46aff79748d4526 Mon Sep 17 00:00:00 2001
From: Jianfeng Liu <liujianfeng1994@gmail.com>
Date: Mon, 1 Dec 2025 18:30:31 -0800
Subject: [PATCH] media/gpu/v4l2: Add AV1 |{width,height}_in_sbs_minus_1| to
tile info
|{width,height}_in_sbs_minus_1| are necessary for verisilicon av1
decoder driver supported by mainline kernel since v6.5 for RK3588 SoC.
libgav1 doesn't have |tile_{column_width,row_height}_in_superblocks|
values when uniform_spacing is enabled, so we have to calculate the
values of |{width,height}_in_sbs_minus_1| from info of
|tile_{columns,rows}|.
Bug: 464638992
Change-Id: I65a84d8f7d1e2baa3d5fd479bec57d76e347d0c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7212655
Reviewed-by: Fritz Koenig <frkoenig@chromium.org>
Reviewed-by: Nathan Hebert <nhebert@chromium.org>
Commit-Queue: Fritz Koenig <frkoenig@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1552534}
---
.../v4l2/v4l2_video_decoder_delegate_av1.cc | 72 +++++++++++++++----
1 file changed, 58 insertions(+), 14 deletions(-)
diff --git a/media/gpu/v4l2/v4l2_video_decoder_delegate_av1.cc b/media/gpu/v4l2/v4l2_video_decoder_delegate_av1.cc
index 7ae87a31b62b86..08fc20b2542fba 100644
--- a/media/gpu/v4l2/v4l2_video_decoder_delegate_av1.cc
+++ b/media/gpu/v4l2/v4l2_video_decoder_delegate_av1.cc
@@ -253,16 +253,22 @@ struct v4l2_av1_tile_info FillTileInfo(const libgav1::TileInfo& ti) {
base::checked_cast<uint32_t>(ti.tile_row_start[i]);
}
+ // Confirmed that |kMaxTileColumns| is enough size for
+ // |width_in_sbs_minus_1| and |kMaxTileRows| is enough size for
+ // |height_in_sbs_minus_1|
+ // https://b.corp.google.com/issues/187828854#comment19
+ static_assert(
+ std::size(decltype(v4l2_ti.width_in_sbs_minus_1){}) ==
+ libgav1::kMaxTileColumns,
+ "Size of |width_in_sbs_minus_1| array in |v4l2_av1_tile_info| struct "
+ "does not match libgav1 expectation");
+ static_assert(
+ std::size(decltype(v4l2_ti.height_in_sbs_minus_1){}) ==
+ libgav1::kMaxTileRows,
+ "Size of |height_in_sbs_minus_1| array in |v4l2_av1_tile_info| struct "
+ "does not match libgav1 expectation");
+
if (!ti.uniform_spacing) {
- // Confirmed that |kMaxTileColumns| is enough size for
- // |width_in_sbs_minus_1| and |kMaxTileRows| is enough size for
- // |height_in_sbs_minus_1|
- // https://b.corp.google.com/issues/187828854#comment19
- static_assert(
- std::size(decltype(v4l2_ti.width_in_sbs_minus_1){}) ==
- libgav1::kMaxTileColumns,
- "Size of |width_in_sbs_minus_1| array in |v4l2_av1_tile_info| struct "
- "does not match libgav1 expectation");
for (size_t i = 0; i < libgav1::kMaxTileColumns; i++) {
if (ti.tile_column_width_in_superblocks[i] >= 1) {
v4l2_ti.width_in_sbs_minus_1[i] = base::checked_cast<uint32_t>(
@@ -270,17 +276,55 @@ struct v4l2_av1_tile_info FillTileInfo(const libgav1::TileInfo& ti) {
}
}
- static_assert(
- std::size(decltype(v4l2_ti.height_in_sbs_minus_1){}) ==
- libgav1::kMaxTileRows,
- "Size of |height_in_sbs_minus_1| array in |v4l2_av1_tile_info| struct "
- "does not match libgav1 expectation");
for (size_t i = 0; i < libgav1::kMaxTileRows; i++) {
if (ti.tile_row_height_in_superblocks[i] >= 1) {
v4l2_ti.height_in_sbs_minus_1[i] = base::checked_cast<uint32_t>(
ti.tile_row_height_in_superblocks[i] - 1);
}
}
+ } else {
+ // libgav1 doesn't provide tile_column_width_in_superblocks and
+ // tile_row_height_in_superblocks values when uniform_spacing is set,
+ // so we have to calculate width and height of superblocks via
+ // other column/row info.
+ const uint32_t cols4x4 =
+ base::checked_cast<uint32_t>(ti.tile_column_start[ti.tile_columns]);
+ const uint32_t sb_cols = base::checked_cast<uint32_t>(ti.sb_columns);
+ const uint32_t sb_cols_64 = (cols4x4 + 15) >> 4;
+ const uint32_t sb_cols_128 = (cols4x4 + 31) >> 5;
+ uint32_t sb_shift = 0;
+ if (sb_cols_64 == sb_cols) {
+ sb_shift = 4;
+ } else {
+ DCHECK_EQ(sb_cols_128, sb_cols);
+ sb_shift = 5;
+ }
+
+ const uint32_t sb_size_mi = 1u << sb_shift;
+
+ for (size_t i = 0; i < static_cast<uint32_t>(ti.tile_columns); ++i) {
+ const uint32_t mi_start =
+ base::checked_cast<uint32_t>(ti.tile_column_start[i]);
+ const uint32_t mi_end =
+ base::checked_cast<uint32_t>(ti.tile_column_start[i + 1]);
+ const uint32_t mi_width = mi_end - mi_start;
+
+ const uint32_t sb_w = (mi_width + sb_size_mi - 1) >> sb_shift;
+ DCHECK_GE(sb_w, 1u);
+ v4l2_ti.width_in_sbs_minus_1[i] = sb_w - 1;
+ }
+
+ for (size_t i = 0; i < static_cast<uint32_t>(ti.tile_rows); ++i) {
+ const uint32_t mi_start =
+ base::checked_cast<uint32_t>(ti.tile_row_start[i]);
+ const uint32_t mi_end =
+ base::checked_cast<uint32_t>(ti.tile_row_start[i + 1]);
+ const uint32_t mi_height = mi_end - mi_start;
+
+ const uint32_t sb_h = (mi_height + sb_size_mi - 1) >> sb_shift;
+ DCHECK_GE(sb_h, 1u);
+ v4l2_ti.height_in_sbs_minus_1[i] = sb_h - 1;
+ }
}
v4l2_ti.tile_size_bytes = ti.tile_size_bytes;
|