av1_vaapi_video_decoder_delegate.cc 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h"
  5. #include <string.h>
  6. #include <va/va.h>
  7. #include <algorithm>
  8. #include <vector>
  9. #include "base/callback_helpers.h"
  10. #include "base/logging.h"
  11. #include "base/memory/scoped_refptr.h"
  12. #include "build/chromeos_buildflags.h"
  13. #include "media/gpu/av1_picture.h"
  14. #include "media/gpu/decode_surface_handler.h"
  15. #include "media/gpu/vaapi/vaapi_common.h"
  16. #include "media/gpu/vaapi/vaapi_wrapper.h"
  17. #include "third_party/libgav1/src/src/obu_parser.h"
  18. #include "third_party/libgav1/src/src/utils/types.h"
  19. #include "third_party/libgav1/src/src/warp_prediction.h"
  20. namespace media {
  21. using DecodeStatus = AV1Decoder::AV1Accelerator::Status;
  22. namespace {
  23. #define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0]))
  24. #define STD_ARRAY_SIZE(ar) (std::tuple_size<decltype(ar)>::value)
  25. void FillSegmentInfo(VASegmentationStructAV1& va_seg_info,
  26. const libgav1::Segmentation& segmentation) {
  27. auto& va_seg_info_fields = va_seg_info.segment_info_fields.bits;
  28. va_seg_info_fields.enabled = segmentation.enabled;
  29. va_seg_info_fields.update_map = segmentation.update_map;
  30. va_seg_info_fields.temporal_update = segmentation.temporal_update;
  31. va_seg_info_fields.update_data = segmentation.update_data;
  32. static_assert(libgav1::kMaxSegments == 8 && libgav1::kSegmentFeatureMax == 8,
  33. "Invalid Segment array size");
  34. static_assert(ARRAY_SIZE(segmentation.feature_data) == 8 &&
  35. ARRAY_SIZE(segmentation.feature_data[0]) == 8 &&
  36. ARRAY_SIZE(segmentation.feature_enabled) == 8 &&
  37. ARRAY_SIZE(segmentation.feature_enabled[0]) == 8,
  38. "Invalid segmentation array size");
  39. static_assert(ARRAY_SIZE(va_seg_info.feature_data) == 8 &&
  40. ARRAY_SIZE(va_seg_info.feature_data[0]) == 8 &&
  41. ARRAY_SIZE(va_seg_info.feature_mask) == 8,
  42. "Invalid feature array size");
  43. for (size_t i = 0; i < libgav1::kMaxSegments; ++i) {
  44. for (size_t j = 0; j < libgav1::kSegmentFeatureMax; ++j)
  45. va_seg_info.feature_data[i][j] = segmentation.feature_data[i][j];
  46. }
  47. for (size_t i = 0; i < libgav1::kMaxSegments; ++i) {
  48. uint8_t feature_mask = 0;
  49. for (size_t j = 0; j < libgav1::kSegmentFeatureMax; ++j) {
  50. if (segmentation.feature_enabled[i][j])
  51. feature_mask |= 1 << j;
  52. }
  53. va_seg_info.feature_mask[i] = feature_mask;
  54. }
  55. }
  56. void FillFilmGrainInfo(VAFilmGrainStructAV1& va_film_grain_info,
  57. const libgav1::FilmGrainParams& film_grain_params) {
  58. if (!film_grain_params.apply_grain)
  59. return;
  60. #define COPY_FILM_GRAIN_FIELD(a) \
  61. va_film_grain_info.film_grain_info_fields.bits.a = film_grain_params.a
  62. COPY_FILM_GRAIN_FIELD(apply_grain);
  63. COPY_FILM_GRAIN_FIELD(chroma_scaling_from_luma);
  64. COPY_FILM_GRAIN_FIELD(grain_scale_shift);
  65. COPY_FILM_GRAIN_FIELD(overlap_flag);
  66. COPY_FILM_GRAIN_FIELD(clip_to_restricted_range);
  67. #undef COPY_FILM_GRAIN_FIELD
  68. va_film_grain_info.film_grain_info_fields.bits.ar_coeff_lag =
  69. film_grain_params.auto_regression_coeff_lag;
  70. DCHECK_GE(film_grain_params.chroma_scaling, 8u);
  71. DCHECK_GE(film_grain_params.auto_regression_shift, 6u);
  72. va_film_grain_info.film_grain_info_fields.bits.grain_scaling_minus_8 =
  73. film_grain_params.chroma_scaling - 8;
  74. va_film_grain_info.film_grain_info_fields.bits.ar_coeff_shift_minus_6 =
  75. film_grain_params.auto_regression_shift - 6;
  76. constexpr size_t kFilmGrainPointYSize = 14;
  77. constexpr size_t kFilmGrainPointUVSize = 10;
  78. static_assert(
  79. ARRAY_SIZE(va_film_grain_info.point_y_value) == kFilmGrainPointYSize &&
  80. ARRAY_SIZE(va_film_grain_info.point_y_scaling) ==
  81. kFilmGrainPointYSize &&
  82. ARRAY_SIZE(va_film_grain_info.point_cb_value) ==
  83. kFilmGrainPointUVSize &&
  84. ARRAY_SIZE(va_film_grain_info.point_cb_scaling) ==
  85. kFilmGrainPointUVSize &&
  86. ARRAY_SIZE(va_film_grain_info.point_cr_value) ==
  87. kFilmGrainPointUVSize &&
  88. ARRAY_SIZE(va_film_grain_info.point_cr_scaling) ==
  89. kFilmGrainPointUVSize &&
  90. ARRAY_SIZE(film_grain_params.point_y_value) == kFilmGrainPointYSize &&
  91. ARRAY_SIZE(film_grain_params.point_y_scaling) ==
  92. kFilmGrainPointYSize &&
  93. ARRAY_SIZE(film_grain_params.point_u_value) ==
  94. kFilmGrainPointUVSize &&
  95. ARRAY_SIZE(film_grain_params.point_u_scaling) ==
  96. kFilmGrainPointUVSize &&
  97. ARRAY_SIZE(film_grain_params.point_v_value) ==
  98. kFilmGrainPointUVSize &&
  99. ARRAY_SIZE(film_grain_params.point_v_scaling) ==
  100. kFilmGrainPointUVSize,
  101. "Invalid array size of film grain values");
  102. DCHECK_LE(film_grain_params.num_y_points, kFilmGrainPointYSize);
  103. DCHECK_LE(film_grain_params.num_u_points, kFilmGrainPointUVSize);
  104. DCHECK_LE(film_grain_params.num_v_points, kFilmGrainPointUVSize);
  105. #define COPY_FILM_GRAIN_FIELD2(a, b) va_film_grain_info.a = film_grain_params.b
  106. #define COPY_FILM_GRAIN_FIELD3(a) COPY_FILM_GRAIN_FIELD2(a, a)
  107. COPY_FILM_GRAIN_FIELD3(grain_seed);
  108. COPY_FILM_GRAIN_FIELD3(num_y_points);
  109. for (uint8_t i = 0; i < film_grain_params.num_y_points; ++i) {
  110. COPY_FILM_GRAIN_FIELD3(point_y_value[i]);
  111. COPY_FILM_GRAIN_FIELD3(point_y_scaling[i]);
  112. }
  113. #undef COPY_FILM_GRAIN_FIELD3
  114. COPY_FILM_GRAIN_FIELD2(num_cb_points, num_u_points);
  115. for (uint8_t i = 0; i < film_grain_params.num_u_points; ++i) {
  116. COPY_FILM_GRAIN_FIELD2(point_cb_value[i], point_u_value[i]);
  117. COPY_FILM_GRAIN_FIELD2(point_cb_scaling[i], point_u_scaling[i]);
  118. }
  119. COPY_FILM_GRAIN_FIELD2(num_cr_points, num_v_points);
  120. for (uint8_t i = 0; i < film_grain_params.num_v_points; ++i) {
  121. COPY_FILM_GRAIN_FIELD2(point_cr_value[i], point_v_value[i]);
  122. COPY_FILM_GRAIN_FIELD2(point_cr_scaling[i], point_v_scaling[i]);
  123. }
  124. constexpr size_t kAutoRegressionCoeffYSize = 24;
  125. constexpr size_t kAutoRegressionCoeffUVSize = 25;
  126. static_assert(
  127. ARRAY_SIZE(va_film_grain_info.ar_coeffs_y) == kAutoRegressionCoeffYSize &&
  128. ARRAY_SIZE(va_film_grain_info.ar_coeffs_cb) ==
  129. kAutoRegressionCoeffUVSize &&
  130. ARRAY_SIZE(va_film_grain_info.ar_coeffs_cr) ==
  131. kAutoRegressionCoeffUVSize &&
  132. ARRAY_SIZE(film_grain_params.auto_regression_coeff_y) ==
  133. kAutoRegressionCoeffYSize &&
  134. ARRAY_SIZE(film_grain_params.auto_regression_coeff_u) ==
  135. kAutoRegressionCoeffUVSize &&
  136. ARRAY_SIZE(film_grain_params.auto_regression_coeff_v) ==
  137. kAutoRegressionCoeffUVSize,
  138. "Invalid array size of auto-regressive coefficients");
  139. const size_t num_pos_y = (film_grain_params.auto_regression_coeff_lag * 2) *
  140. (film_grain_params.auto_regression_coeff_lag + 1);
  141. const size_t num_pos_uv = num_pos_y + (film_grain_params.num_y_points > 0);
  142. if (film_grain_params.num_y_points > 0) {
  143. DCHECK_LE(num_pos_y, kAutoRegressionCoeffYSize);
  144. for (size_t i = 0; i < num_pos_y; ++i)
  145. COPY_FILM_GRAIN_FIELD2(ar_coeffs_y[i], auto_regression_coeff_y[i]);
  146. }
  147. if (film_grain_params.chroma_scaling_from_luma ||
  148. film_grain_params.num_u_points > 0 ||
  149. film_grain_params.num_v_points > 0) {
  150. DCHECK_LE(num_pos_uv, kAutoRegressionCoeffUVSize);
  151. for (size_t i = 0; i < num_pos_uv; ++i) {
  152. if (film_grain_params.chroma_scaling_from_luma ||
  153. film_grain_params.num_u_points > 0) {
  154. COPY_FILM_GRAIN_FIELD2(ar_coeffs_cb[i], auto_regression_coeff_u[i]);
  155. }
  156. if (film_grain_params.chroma_scaling_from_luma ||
  157. film_grain_params.num_v_points > 0) {
  158. COPY_FILM_GRAIN_FIELD2(ar_coeffs_cr[i], auto_regression_coeff_v[i]);
  159. }
  160. }
  161. }
  162. if (film_grain_params.num_u_points > 0) {
  163. COPY_FILM_GRAIN_FIELD2(cb_mult, u_multiplier + 128);
  164. COPY_FILM_GRAIN_FIELD2(cb_luma_mult, u_luma_multiplier + 128);
  165. COPY_FILM_GRAIN_FIELD2(cb_offset, u_offset + 256);
  166. }
  167. if (film_grain_params.num_v_points > 0) {
  168. COPY_FILM_GRAIN_FIELD2(cr_mult, v_multiplier + 128);
  169. COPY_FILM_GRAIN_FIELD2(cr_luma_mult, v_luma_multiplier + 128);
  170. COPY_FILM_GRAIN_FIELD2(cr_offset, v_offset + 256);
  171. }
  172. #undef COPY_FILM_GRAIN_FIELD2
  173. }
  174. void FillGlobalMotionInfo(
  175. VAWarpedMotionParamsAV1 va_warped_motion[7],
  176. const std::array<libgav1::GlobalMotion, libgav1::kNumReferenceFrameTypes>&
  177. global_motion) {
  178. // global_motion[0] (for kReferenceFrameIntra) is not used.
  179. constexpr size_t kWarpedMotionSize = libgav1::kNumReferenceFrameTypes - 1;
  180. for (size_t i = 0; i < kWarpedMotionSize; ++i) {
  181. // Copy |global_motion| because SetupShear updates the affine variables of
  182. // the |global_motion|.
  183. auto gm = global_motion[i + 1];
  184. switch (gm.type) {
  185. case libgav1::kGlobalMotionTransformationTypeIdentity:
  186. va_warped_motion[i].wmtype = VAAV1TransformationIdentity;
  187. break;
  188. case libgav1::kGlobalMotionTransformationTypeTranslation:
  189. va_warped_motion[i].wmtype = VAAV1TransformationTranslation;
  190. break;
  191. case libgav1::kGlobalMotionTransformationTypeRotZoom:
  192. va_warped_motion[i].wmtype = VAAV1TransformationRotzoom;
  193. break;
  194. case libgav1::kGlobalMotionTransformationTypeAffine:
  195. va_warped_motion[i].wmtype = VAAV1TransformationAffine;
  196. break;
  197. default:
  198. NOTREACHED() << "Invalid global motion transformation type, "
  199. << va_warped_motion[i].wmtype;
  200. }
  201. static_assert(ARRAY_SIZE(va_warped_motion[i].wmmat) == 8 &&
  202. ARRAY_SIZE(gm.params) == 6,
  203. "Invalid size of warp motion parameters");
  204. for (size_t j = 0; j < 6; ++j)
  205. va_warped_motion[i].wmmat[j] = gm.params[j];
  206. va_warped_motion[i].wmmat[6] = 0;
  207. va_warped_motion[i].wmmat[7] = 0;
  208. va_warped_motion[i].invalid = !libgav1::SetupShear(&gm);
  209. }
  210. }
  211. bool FillTileInfo(VADecPictureParameterBufferAV1& va_pic_param,
  212. const libgav1::TileInfo& tile_info) {
  213. // Since gav1 decoder doesn't support decoding with tile lists (i.e. large
  214. // scale tile decoding), libgav1::ObuParser doesn't parse tile list, so that
  215. // we cannot acquire anchor_frames_num, anchor_frames_list, tile_count_minus_1
  216. // and output_frame_width/height_in_tiles_minus_1, and thus must set them and
  217. // large_scale_tile to 0 or false. This is already done by the memset in
  218. // SubmitDecode(). libgav1::ObuParser returns kStatusUnimplemented on
  219. // ParseOneFrame(), a fallback to av1 software decoder happens in the large
  220. // scale tile decoding.
  221. // TODO(hiroh): Support the large scale tile decoding once libgav1::ObuParser
  222. // supports it.
  223. va_pic_param.tile_cols = base::checked_cast<uint8_t>(tile_info.tile_columns);
  224. va_pic_param.tile_rows = base::checked_cast<uint8_t>(tile_info.tile_rows);
  225. if (!tile_info.uniform_spacing) {
  226. constexpr int kVaSizeOfTileWidthAndHeightArray = 63;
  227. static_assert(
  228. ARRAY_SIZE(tile_info.tile_column_width_in_superblocks) == 65 &&
  229. ARRAY_SIZE(tile_info.tile_row_height_in_superblocks) == 65 &&
  230. ARRAY_SIZE(va_pic_param.width_in_sbs_minus_1) ==
  231. kVaSizeOfTileWidthAndHeightArray &&
  232. ARRAY_SIZE(va_pic_param.height_in_sbs_minus_1) ==
  233. kVaSizeOfTileWidthAndHeightArray,
  234. "Invalid sizes of tile column widths and row heights");
  235. const int tile_columns =
  236. std::min(kVaSizeOfTileWidthAndHeightArray, tile_info.tile_columns);
  237. for (int i = 0; i < tile_columns; i++) {
  238. if (!base::CheckSub<int>(tile_info.tile_column_width_in_superblocks[i], 1)
  239. .AssignIfValid(&va_pic_param.width_in_sbs_minus_1[i])) {
  240. return false;
  241. }
  242. }
  243. const int tile_rows =
  244. std::min(kVaSizeOfTileWidthAndHeightArray, tile_info.tile_rows);
  245. for (int i = 0; i < tile_rows; i++) {
  246. if (!base::CheckSub<int>(tile_info.tile_row_height_in_superblocks[i], 1)
  247. .AssignIfValid(&va_pic_param.height_in_sbs_minus_1[i])) {
  248. return false;
  249. }
  250. }
  251. }
  252. va_pic_param.context_update_tile_id =
  253. base::checked_cast<uint16_t>(tile_info.context_update_id);
  254. return true;
  255. }
  256. void FillLoopFilterInfo(VADecPictureParameterBufferAV1& va_pic_param,
  257. const libgav1::LoopFilter& loop_filter) {
  258. static_assert(STD_ARRAY_SIZE(loop_filter.level) == libgav1::kFrameLfCount &&
  259. libgav1::kFrameLfCount == 4 &&
  260. ARRAY_SIZE(va_pic_param.filter_level) == 2,
  261. "Invalid size of loop filter strength array");
  262. va_pic_param.filter_level[0] =
  263. base::checked_cast<uint8_t>(loop_filter.level[0]);
  264. va_pic_param.filter_level[1] =
  265. base::checked_cast<uint8_t>(loop_filter.level[1]);
  266. va_pic_param.filter_level_u =
  267. base::checked_cast<uint8_t>(loop_filter.level[2]);
  268. va_pic_param.filter_level_v =
  269. base::checked_cast<uint8_t>(loop_filter.level[3]);
  270. va_pic_param.loop_filter_info_fields.bits.sharpness_level =
  271. loop_filter.sharpness;
  272. va_pic_param.loop_filter_info_fields.bits.mode_ref_delta_enabled =
  273. loop_filter.delta_enabled;
  274. va_pic_param.loop_filter_info_fields.bits.mode_ref_delta_update =
  275. loop_filter.delta_update;
  276. static_assert(libgav1::kNumReferenceFrameTypes == 8 &&
  277. ARRAY_SIZE(va_pic_param.ref_deltas) ==
  278. libgav1::kNumReferenceFrameTypes &&
  279. STD_ARRAY_SIZE(loop_filter.ref_deltas) ==
  280. libgav1::kNumReferenceFrameTypes,
  281. "Invalid size of ref deltas array");
  282. static_assert(libgav1::kLoopFilterMaxModeDeltas == 2 &&
  283. ARRAY_SIZE(va_pic_param.mode_deltas) ==
  284. libgav1::kLoopFilterMaxModeDeltas &&
  285. STD_ARRAY_SIZE(loop_filter.mode_deltas) ==
  286. libgav1::kLoopFilterMaxModeDeltas,
  287. "Invalid size of mode deltas array");
  288. for (size_t i = 0; i < libgav1::kNumReferenceFrameTypes; i++)
  289. va_pic_param.ref_deltas[i] = loop_filter.ref_deltas[i];
  290. for (size_t i = 0; i < libgav1::kLoopFilterMaxModeDeltas; i++)
  291. va_pic_param.mode_deltas[i] = loop_filter.mode_deltas[i];
  292. }
  293. void FillQuantizationInfo(VADecPictureParameterBufferAV1& va_pic_param,
  294. const libgav1::QuantizerParameters& quant_param) {
  295. va_pic_param.base_qindex = quant_param.base_index;
  296. static_assert(
  297. libgav1::kPlaneY == 0 && libgav1::kPlaneU == 1 && libgav1::kPlaneV == 2,
  298. "Invalid plane index");
  299. static_assert(libgav1::kMaxPlanes == 3 &&
  300. ARRAY_SIZE(quant_param.delta_dc) == libgav1::kMaxPlanes &&
  301. ARRAY_SIZE(quant_param.delta_ac) == libgav1::kMaxPlanes,
  302. "Invalid size of delta dc/ac array");
  303. va_pic_param.y_dc_delta_q = quant_param.delta_dc[0];
  304. va_pic_param.u_dc_delta_q = quant_param.delta_dc[1];
  305. va_pic_param.v_dc_delta_q = quant_param.delta_dc[2];
  306. // quant_param.delta_ac[0] is useless as it is always 0.
  307. va_pic_param.u_ac_delta_q = quant_param.delta_ac[1];
  308. va_pic_param.v_ac_delta_q = quant_param.delta_ac[2];
  309. va_pic_param.qmatrix_fields.bits.using_qmatrix = quant_param.use_matrix;
  310. if (!quant_param.use_matrix)
  311. return;
  312. static_assert(ARRAY_SIZE(quant_param.matrix_level) == libgav1::kMaxPlanes,
  313. "Invalid size of matrix levels");
  314. va_pic_param.qmatrix_fields.bits.qm_y =
  315. base::checked_cast<uint16_t>(quant_param.matrix_level[0]);
  316. va_pic_param.qmatrix_fields.bits.qm_u =
  317. base::checked_cast<uint16_t>(quant_param.matrix_level[1]);
  318. va_pic_param.qmatrix_fields.bits.qm_v =
  319. base::checked_cast<uint16_t>(quant_param.matrix_level[2]);
  320. }
  321. void FillCdefInfo(VADecPictureParameterBufferAV1& va_pic_param,
  322. const libgav1::Cdef& cdef,
  323. uint8_t color_bitdepth) {
  324. // Damping value parsed in libgav1 is from the spec + (bitdepth - 8).
  325. // All the strength values parsed in libgav1 are from the spec and left
  326. // shifted by (bitdepth - 8).
  327. CHECK_GE(color_bitdepth, 8u);
  328. const uint8_t coeff_shift = color_bitdepth - 8u;
  329. va_pic_param.cdef_damping_minus_3 =
  330. base::checked_cast<uint8_t>(cdef.damping - coeff_shift - 3u);
  331. va_pic_param.cdef_bits = cdef.bits;
  332. static_assert(
  333. libgav1::kMaxCdefStrengths == 8 &&
  334. ARRAY_SIZE(cdef.y_primary_strength) == libgav1::kMaxCdefStrengths &&
  335. ARRAY_SIZE(cdef.y_secondary_strength) == libgav1::kMaxCdefStrengths &&
  336. ARRAY_SIZE(cdef.uv_primary_strength) == libgav1::kMaxCdefStrengths &&
  337. ARRAY_SIZE(cdef.uv_secondary_strength) ==
  338. libgav1::kMaxCdefStrengths &&
  339. ARRAY_SIZE(va_pic_param.cdef_y_strengths) ==
  340. libgav1::kMaxCdefStrengths &&
  341. ARRAY_SIZE(va_pic_param.cdef_uv_strengths) ==
  342. libgav1::kMaxCdefStrengths,
  343. "Invalid size of cdef strengths");
  344. const size_t num_cdef_strengths = 1 << cdef.bits;
  345. DCHECK_LE(num_cdef_strengths,
  346. static_cast<size_t>(libgav1::kMaxCdefStrengths));
  347. for (size_t i = 0; i < num_cdef_strengths; ++i) {
  348. const uint8_t prim_strength = cdef.y_primary_strength[i] >> coeff_shift;
  349. uint8_t sec_strength = cdef.y_secondary_strength[i] >> coeff_shift;
  350. DCHECK_LE(sec_strength, 4u);
  351. if (sec_strength == 4)
  352. sec_strength--;
  353. va_pic_param.cdef_y_strengths[i] =
  354. ((prim_strength & 0xf) << 2) | (sec_strength & 0x03);
  355. }
  356. for (size_t i = 0; i < num_cdef_strengths; ++i) {
  357. const uint8_t prim_strength = cdef.uv_primary_strength[i] >> coeff_shift;
  358. uint8_t sec_strength = cdef.uv_secondary_strength[i] >> coeff_shift;
  359. DCHECK_LE(sec_strength, 4u);
  360. if (sec_strength == 4)
  361. sec_strength--;
  362. va_pic_param.cdef_uv_strengths[i] =
  363. ((prim_strength & 0xf) << 2) | (sec_strength & 0x03);
  364. }
  365. }
  366. void FillModeControlInfo(VADecPictureParameterBufferAV1& va_pic_param,
  367. const libgav1::ObuFrameHeader& frame_header) {
  368. auto& mode_control = va_pic_param.mode_control_fields.bits;
  369. mode_control.delta_q_present_flag = frame_header.delta_q.present;
  370. mode_control.log2_delta_q_res = frame_header.delta_q.scale;
  371. mode_control.delta_lf_present_flag = frame_header.delta_lf.present;
  372. mode_control.log2_delta_lf_res = frame_header.delta_lf.scale;
  373. mode_control.delta_lf_multi = frame_header.delta_lf.multi;
  374. DCHECK_LE(0u, frame_header.tx_mode);
  375. DCHECK_LE(frame_header.tx_mode, 2u);
  376. mode_control.tx_mode = frame_header.tx_mode;
  377. mode_control.reference_select = frame_header.reference_mode_select;
  378. mode_control.reduced_tx_set_used = frame_header.reduced_tx_set;
  379. mode_control.skip_mode_present = frame_header.skip_mode_present;
  380. }
  381. void FillLoopRestorationInfo(VADecPictureParameterBufferAV1& va_pic_param,
  382. const libgav1::LoopRestoration& loop_restoration) {
  383. auto to_frame_restoration_type =
  384. [](libgav1::LoopRestorationType lr_type) -> uint16_t {
  385. // Spec. 6.10.15
  386. switch (lr_type) {
  387. case libgav1::LoopRestorationType::kLoopRestorationTypeNone:
  388. return 0;
  389. case libgav1::LoopRestorationType::kLoopRestorationTypeSwitchable:
  390. return 3;
  391. case libgav1::LoopRestorationType::kLoopRestorationTypeWiener:
  392. return 1;
  393. case libgav1::LoopRestorationType::kLoopRestorationTypeSgrProj:
  394. return 2;
  395. default:
  396. NOTREACHED() << "Invalid restoration type"
  397. << base::strict_cast<int>(lr_type);
  398. return 0;
  399. }
  400. };
  401. static_assert(
  402. libgav1::kMaxPlanes == 3 &&
  403. ARRAY_SIZE(loop_restoration.type) == libgav1::kMaxPlanes &&
  404. ARRAY_SIZE(loop_restoration.unit_size_log2) == libgav1::kMaxPlanes,
  405. "Invalid size of loop restoration values");
  406. auto& va_loop_restoration = va_pic_param.loop_restoration_fields.bits;
  407. va_loop_restoration.yframe_restoration_type =
  408. to_frame_restoration_type(loop_restoration.type[0]);
  409. va_loop_restoration.cbframe_restoration_type =
  410. to_frame_restoration_type(loop_restoration.type[1]);
  411. va_loop_restoration.crframe_restoration_type =
  412. to_frame_restoration_type(loop_restoration.type[2]);
  413. const size_t num_planes = libgav1::kMaxPlanes;
  414. const bool use_loop_restoration =
  415. std::find_if(std::begin(loop_restoration.type),
  416. std::begin(loop_restoration.type) + num_planes,
  417. [](const auto type) {
  418. return type != libgav1::kLoopRestorationTypeNone;
  419. }) != (loop_restoration.type + num_planes);
  420. if (!use_loop_restoration)
  421. return;
  422. static_assert(libgav1::kPlaneY == 0u && libgav1::kPlaneU == 1u,
  423. "Invalid plane index");
  424. DCHECK_GE(loop_restoration.unit_size_log2[0], 6);
  425. DCHECK_GE(loop_restoration.unit_size_log2[0],
  426. loop_restoration.unit_size_log2[1]);
  427. DCHECK_LE(
  428. loop_restoration.unit_size_log2[0] - loop_restoration.unit_size_log2[1],
  429. 1);
  430. va_loop_restoration.lr_unit_shift = loop_restoration.unit_size_log2[0] - 6;
  431. va_loop_restoration.lr_uv_shift =
  432. loop_restoration.unit_size_log2[0] - loop_restoration.unit_size_log2[1];
  433. }
  434. bool FillAV1PictureParameter(const AV1Picture& pic,
  435. const libgav1::ObuSequenceHeader& sequence_header,
  436. const AV1ReferenceFrameVector& ref_frames,
  437. VADecPictureParameterBufferAV1& va_pic_param) {
  438. memset(&va_pic_param, 0, sizeof(VADecPictureParameterBufferAV1));
  439. DCHECK_LE(base::strict_cast<uint8_t>(sequence_header.profile), 2u)
  440. << "Unknown profile: " << base::strict_cast<int>(sequence_header.profile);
  441. va_pic_param.profile = base::strict_cast<uint8_t>(sequence_header.profile);
  442. if (sequence_header.enable_order_hint) {
  443. DCHECK_GT(sequence_header.order_hint_bits, 0);
  444. DCHECK_LE(sequence_header.order_hint_bits, 8);
  445. va_pic_param.order_hint_bits_minus_1 = sequence_header.order_hint_bits - 1;
  446. }
  447. switch (sequence_header.color_config.bitdepth) {
  448. case 8:
  449. va_pic_param.bit_depth_idx = 0;
  450. break;
  451. case 10:
  452. va_pic_param.bit_depth_idx = 1;
  453. break;
  454. case 12:
  455. va_pic_param.bit_depth_idx = 2;
  456. break;
  457. default:
  458. NOTREACHED() << "Unknown bit depth: "
  459. << base::strict_cast<int>(
  460. sequence_header.color_config.bitdepth);
  461. }
  462. switch (sequence_header.color_config.matrix_coefficients) {
  463. case libgav1::kMatrixCoefficientsIdentity:
  464. case libgav1::kMatrixCoefficientsBt709:
  465. case libgav1::kMatrixCoefficientsUnspecified:
  466. case libgav1::kMatrixCoefficientsFcc:
  467. case libgav1::kMatrixCoefficientsBt470BG:
  468. case libgav1::kMatrixCoefficientsBt601:
  469. case libgav1::kMatrixCoefficientsSmpte240:
  470. case libgav1::kMatrixCoefficientsSmpteYcgco:
  471. case libgav1::kMatrixCoefficientsBt2020Ncl:
  472. case libgav1::kMatrixCoefficientsBt2020Cl:
  473. case libgav1::kMatrixCoefficientsSmpte2085:
  474. case libgav1::kMatrixCoefficientsChromatNcl:
  475. case libgav1::kMatrixCoefficientsChromatCl:
  476. case libgav1::kMatrixCoefficientsIctcp:
  477. va_pic_param.matrix_coefficients = base::checked_cast<uint8_t>(
  478. sequence_header.color_config.matrix_coefficients);
  479. break;
  480. default:
  481. DLOG(ERROR) << "Invalid matrix coefficients: "
  482. << static_cast<int>(
  483. sequence_header.color_config.matrix_coefficients);
  484. return false;
  485. }
  486. DCHECK(!sequence_header.color_config.is_monochrome);
  487. #define COPY_SEQ_FIELD(a) \
  488. va_pic_param.seq_info_fields.fields.a = sequence_header.a
  489. #define COPY_SEQ_FIELD2(a, b) va_pic_param.seq_info_fields.fields.a = b
  490. COPY_SEQ_FIELD(still_picture);
  491. COPY_SEQ_FIELD(use_128x128_superblock);
  492. COPY_SEQ_FIELD(enable_filter_intra);
  493. COPY_SEQ_FIELD(enable_intra_edge_filter);
  494. COPY_SEQ_FIELD(enable_interintra_compound);
  495. COPY_SEQ_FIELD(enable_masked_compound);
  496. COPY_SEQ_FIELD(enable_dual_filter);
  497. COPY_SEQ_FIELD(enable_order_hint);
  498. COPY_SEQ_FIELD(enable_jnt_comp);
  499. COPY_SEQ_FIELD(enable_cdef);
  500. COPY_SEQ_FIELD2(mono_chrome, sequence_header.color_config.is_monochrome);
  501. COPY_SEQ_FIELD2(subsampling_x, sequence_header.color_config.subsampling_x);
  502. COPY_SEQ_FIELD2(subsampling_y, sequence_header.color_config.subsampling_y);
  503. COPY_SEQ_FIELD(film_grain_params_present);
  504. #undef COPY_SEQ_FIELD
  505. switch (sequence_header.color_config.color_range) {
  506. case libgav1::kColorRangeStudio:
  507. case libgav1::kColorRangeFull:
  508. COPY_SEQ_FIELD2(color_range,
  509. base::strict_cast<uint32_t>(
  510. sequence_header.color_config.color_range));
  511. break;
  512. default:
  513. NOTREACHED() << "Unknown color range: "
  514. << static_cast<int>(
  515. sequence_header.color_config.color_range);
  516. }
  517. #undef COPY_SEQ_FILED2
  518. const libgav1::ObuFrameHeader& frame_header = pic.frame_header;
  519. const auto* vaapi_pic = static_cast<const VaapiAV1Picture*>(&pic);
  520. DCHECK(!!vaapi_pic->display_va_surface() &&
  521. !!vaapi_pic->reconstruct_va_surface());
  522. if (frame_header.film_grain_params.apply_grain) {
  523. DCHECK_NE(vaapi_pic->display_va_surface()->id(),
  524. vaapi_pic->reconstruct_va_surface()->id())
  525. << "When using film grain synthesis, the display and reconstruct "
  526. "surfaces"
  527. << " should be different.";
  528. va_pic_param.current_frame = vaapi_pic->reconstruct_va_surface()->id();
  529. va_pic_param.current_display_picture =
  530. vaapi_pic->display_va_surface()->id();
  531. } else {
  532. DCHECK_EQ(vaapi_pic->display_va_surface()->id(),
  533. vaapi_pic->reconstruct_va_surface()->id())
  534. << "When not using film grain synthesis, the display and reconstruct"
  535. << " surfaces should be the same.";
  536. va_pic_param.current_frame = vaapi_pic->display_va_surface()->id();
  537. va_pic_param.current_display_picture = VA_INVALID_SURFACE;
  538. }
  539. if (!base::CheckSub<int32_t>(frame_header.width, 1)
  540. .AssignIfValid(&va_pic_param.frame_width_minus1) ||
  541. !base::CheckSub<int32_t>(frame_header.height, 1)
  542. .AssignIfValid(&va_pic_param.frame_height_minus1)) {
  543. DLOG(ERROR) << "Invalid frame width and height"
  544. << ", width=" << frame_header.width
  545. << ", height=" << frame_header.height;
  546. return false;
  547. }
  548. static_assert(libgav1::kNumReferenceFrameTypes == 8 &&
  549. ARRAY_SIZE(va_pic_param.ref_frame_map) ==
  550. libgav1::kNumReferenceFrameTypes,
  551. "Invalid size of reference frames");
  552. static_assert(libgav1::kNumInterReferenceFrameTypes == 7 &&
  553. ARRAY_SIZE(frame_header.reference_frame_index) ==
  554. libgav1::kNumInterReferenceFrameTypes &&
  555. ARRAY_SIZE(va_pic_param.ref_frame_idx) ==
  556. libgav1::kNumInterReferenceFrameTypes,
  557. "Invalid size of reference frame indices");
  558. for (size_t i = 0; i < libgav1::kNumReferenceFrameTypes; ++i) {
  559. const auto* ref_pic =
  560. static_cast<const VaapiAV1Picture*>(ref_frames[i].get());
  561. va_pic_param.ref_frame_map[i] =
  562. ref_pic ? ref_pic->reconstruct_va_surface()->id() : VA_INVALID_SURFACE;
  563. }
  564. // |va_pic_param.ref_frame_idx| doesn't need to be filled in for intra frames
  565. // (it can be left zero initialized).
  566. if (!libgav1::IsIntraFrame(frame_header.frame_type)) {
  567. for (size_t i = 0; i < libgav1::kNumInterReferenceFrameTypes; ++i) {
  568. const int8_t index = frame_header.reference_frame_index[i];
  569. CHECK_GE(index, 0);
  570. CHECK_LT(index, libgav1::kNumReferenceFrameTypes);
  571. // AV1Decoder::CheckAndCleanUpReferenceFrames() ensures that
  572. // |ref_frames[index]| is valid for all the reference frames needed by the
  573. // current frame.
  574. DCHECK_NE(va_pic_param.ref_frame_map[index], VA_INVALID_SURFACE);
  575. va_pic_param.ref_frame_idx[i] = base::checked_cast<uint8_t>(index);
  576. }
  577. }
  578. va_pic_param.primary_ref_frame =
  579. base::checked_cast<uint8_t>(frame_header.primary_reference_frame);
  580. va_pic_param.order_hint = frame_header.order_hint;
  581. FillSegmentInfo(va_pic_param.seg_info, frame_header.segmentation);
  582. FillFilmGrainInfo(va_pic_param.film_grain_info,
  583. frame_header.film_grain_params);
  584. if (!FillTileInfo(va_pic_param, frame_header.tile_info))
  585. return false;
  586. if (frame_header.use_superres) {
  587. DVLOG(2) << "Upscaling (use_superres=1) is not supported";
  588. return false;
  589. }
  590. auto& va_pic_info_fields = va_pic_param.pic_info_fields.bits;
  591. va_pic_info_fields.uniform_tile_spacing_flag =
  592. frame_header.tile_info.uniform_spacing;
  593. #define COPY_PIC_FIELD(a) va_pic_info_fields.a = frame_header.a
  594. COPY_PIC_FIELD(show_frame);
  595. COPY_PIC_FIELD(showable_frame);
  596. COPY_PIC_FIELD(error_resilient_mode);
  597. COPY_PIC_FIELD(allow_screen_content_tools);
  598. COPY_PIC_FIELD(force_integer_mv);
  599. COPY_PIC_FIELD(allow_intrabc);
  600. COPY_PIC_FIELD(use_superres);
  601. COPY_PIC_FIELD(allow_high_precision_mv);
  602. COPY_PIC_FIELD(is_motion_mode_switchable);
  603. COPY_PIC_FIELD(use_ref_frame_mvs);
  604. COPY_PIC_FIELD(allow_warped_motion);
  605. #undef COPY_PIC_FIELD
  606. switch (frame_header.frame_type) {
  607. case libgav1::FrameType::kFrameKey:
  608. case libgav1::FrameType::kFrameInter:
  609. case libgav1::FrameType::kFrameIntraOnly:
  610. case libgav1::FrameType::kFrameSwitch:
  611. va_pic_info_fields.frame_type =
  612. base::strict_cast<uint32_t>(frame_header.frame_type);
  613. break;
  614. default:
  615. NOTREACHED() << "Unknown frame type: "
  616. << base::strict_cast<int>(frame_header.frame_type);
  617. }
  618. va_pic_info_fields.disable_cdf_update = !frame_header.enable_cdf_update;
  619. va_pic_info_fields.disable_frame_end_update_cdf =
  620. !frame_header.enable_frame_end_update_cdf;
  621. static_assert(libgav1::kSuperResScaleNumerator == 8,
  622. "Invalid libgav1::kSuperResScaleNumerator value");
  623. CHECK_EQ(frame_header.superres_scale_denominator,
  624. libgav1::kSuperResScaleNumerator);
  625. va_pic_param.superres_scale_denominator =
  626. frame_header.superres_scale_denominator;
  627. DCHECK_LE(base::strict_cast<uint8_t>(frame_header.interpolation_filter), 4u)
  628. << "Unknown interpolation filter: "
  629. << base::strict_cast<int>(frame_header.interpolation_filter);
  630. va_pic_param.interp_filter =
  631. base::strict_cast<uint8_t>(frame_header.interpolation_filter);
  632. FillQuantizationInfo(va_pic_param, frame_header.quantizer);
  633. FillLoopFilterInfo(va_pic_param, frame_header.loop_filter);
  634. FillModeControlInfo(va_pic_param, frame_header);
  635. FillLoopRestorationInfo(va_pic_param, frame_header.loop_restoration);
  636. FillGlobalMotionInfo(va_pic_param.wm, frame_header.global_motion);
  637. FillCdefInfo(
  638. va_pic_param, frame_header.cdef,
  639. base::checked_cast<uint8_t>(sequence_header.color_config.bitdepth));
  640. return true;
  641. }
  642. bool FillAV1SliceParameters(
  643. const libgav1::Vector<libgav1::TileBuffer>& tile_buffers,
  644. const size_t tile_columns,
  645. base::span<const uint8_t> data,
  646. std::vector<VASliceParameterBufferAV1>& va_slice_params) {
  647. CHECK_GT(tile_columns, 0u);
  648. const uint16_t num_tiles = base::checked_cast<uint16_t>(tile_buffers.size());
  649. va_slice_params.resize(num_tiles);
  650. for (uint16_t tile = 0; tile < num_tiles; ++tile) {
  651. VASliceParameterBufferAV1& va_tile_param = va_slice_params[tile];
  652. memset(&va_tile_param, 0, sizeof(VASliceParameterBufferAV1));
  653. va_tile_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
  654. va_tile_param.tile_row = tile / base::checked_cast<uint16_t>(tile_columns);
  655. va_tile_param.tile_column =
  656. tile % base::checked_cast<uint16_t>(tile_columns);
  657. if (!base::CheckedNumeric<size_t>(tile_buffers[tile].size)
  658. .AssignIfValid(&va_tile_param.slice_data_size)) {
  659. return false;
  660. }
  661. CHECK(tile_buffers[tile].data >= data.data());
  662. va_tile_param.slice_data_offset =
  663. base::checked_cast<uint32_t>(tile_buffers[tile].data - data.data());
  664. base::CheckedNumeric<uint32_t> safe_va_slice_data_end(
  665. va_tile_param.slice_data_offset);
  666. safe_va_slice_data_end += va_tile_param.slice_data_size;
  667. size_t va_slice_data_end;
  668. if (!safe_va_slice_data_end.AssignIfValid(&va_slice_data_end) ||
  669. va_slice_data_end > data.size()) {
  670. DLOG(ERROR) << "Invalid tile offset and size"
  671. << ", offset=" << va_tile_param.slice_data_size
  672. << ", size=" << va_tile_param.slice_data_offset
  673. << ", entire data size=" << data.size();
  674. return false;
  675. }
  676. }
  677. return true;
  678. }
  679. } // namespace
  680. AV1VaapiVideoDecoderDelegate::AV1VaapiVideoDecoderDelegate(
  681. DecodeSurfaceHandler<VASurface>* const vaapi_dec,
  682. scoped_refptr<VaapiWrapper> vaapi_wrapper,
  683. ProtectedSessionUpdateCB on_protected_session_update_cb,
  684. CdmContext* cdm_context,
  685. EncryptionScheme encryption_scheme)
  686. : VaapiVideoDecoderDelegate(vaapi_dec,
  687. std::move(vaapi_wrapper),
  688. std::move(on_protected_session_update_cb),
  689. cdm_context,
  690. encryption_scheme) {}
  691. AV1VaapiVideoDecoderDelegate::~AV1VaapiVideoDecoderDelegate() {
  692. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  693. DCHECK(!picture_params_);
  694. DCHECK(!crypto_params_);
  695. }
  696. scoped_refptr<AV1Picture> AV1VaapiVideoDecoderDelegate::CreateAV1Picture(
  697. bool apply_grain) {
  698. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  699. const auto display_va_surface = vaapi_dec_->CreateSurface();
  700. if (!display_va_surface)
  701. return nullptr;
  702. auto reconstruct_va_surface = display_va_surface;
  703. if (apply_grain) {
  704. // TODO(hiroh): When no surface is available here, this returns nullptr and
  705. // |display_va_surface| is released. Since the surface is back to the pool,
  706. // VaapiVideoDecoder will detect that there are surfaces available and will
  707. // start another decode task which means that CreateSurface() might fail
  708. // again for |reconstruct_va_surface| since only one surface might have gone
  709. // back to the pool (the one for |display_va_surface|). We should avoid this
  710. // loop for the sake of efficiency.
  711. reconstruct_va_surface = vaapi_dec_->CreateSurface();
  712. if (!reconstruct_va_surface)
  713. return nullptr;
  714. }
  715. return base::MakeRefCounted<VaapiAV1Picture>(
  716. std::move(display_va_surface), std::move(reconstruct_va_surface));
  717. }
  718. bool AV1VaapiVideoDecoderDelegate::OutputPicture(const AV1Picture& pic) {
  719. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  720. const auto* vaapi_pic = static_cast<const VaapiAV1Picture*>(&pic);
  721. vaapi_dec_->SurfaceReady(vaapi_pic->display_va_surface(),
  722. vaapi_pic->bitstream_id(), vaapi_pic->visible_rect(),
  723. vaapi_pic->get_colorspace());
  724. return true;
  725. }
  726. DecodeStatus AV1VaapiVideoDecoderDelegate::SubmitDecode(
  727. const AV1Picture& pic,
  728. const libgav1::ObuSequenceHeader& seq_header,
  729. const AV1ReferenceFrameVector& ref_frames,
  730. const libgav1::Vector<libgav1::TileBuffer>& tile_buffers,
  731. base::span<const uint8_t> data) {
  732. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  733. #if BUILDFLAG(IS_CHROMEOS_ASH)
  734. const DecryptConfig* decrypt_config = pic.decrypt_config();
  735. if (decrypt_config && !SetDecryptConfig(decrypt_config->Clone()))
  736. return DecodeStatus::kFail;
  737. bool uses_crypto = false;
  738. std::vector<VAEncryptionSegmentInfo> encryption_segment_info;
  739. VAEncryptionParameters crypto_param{};
  740. if (IsEncryptedSession()) {
  741. const ProtectedSessionState state = SetupDecryptDecode(
  742. /*full_sample=*/false, data.size_bytes(), &crypto_param,
  743. &encryption_segment_info,
  744. decrypt_config ? decrypt_config->subsamples()
  745. : std::vector<SubsampleEntry>());
  746. if (state == ProtectedSessionState::kFailed) {
  747. LOG(ERROR)
  748. << "SubmitDecode fails because we couldn't setup the protected "
  749. "session";
  750. return DecodeStatus::kFail;
  751. } else if (state != ProtectedSessionState::kCreated) {
  752. return DecodeStatus::kTryAgain;
  753. }
  754. uses_crypto = true;
  755. if (!crypto_params_) {
  756. crypto_params_ = vaapi_wrapper_->CreateVABuffer(
  757. VAEncryptionParameterBufferType, sizeof(crypto_param));
  758. if (!crypto_params_)
  759. return DecodeStatus::kFail;
  760. }
  761. }
  762. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  763. // libgav1 ensures that tile_columns is >= 0 and <= MAX_TILE_COLS.
  764. DCHECK_LE(0, pic.frame_header.tile_info.tile_columns);
  765. DCHECK_LE(pic.frame_header.tile_info.tile_columns, libgav1::kMaxTileColumns);
  766. const size_t tile_columns =
  767. base::checked_cast<size_t>(pic.frame_header.tile_info.tile_columns);
  768. VADecPictureParameterBufferAV1 pic_param;
  769. std::vector<VASliceParameterBufferAV1> slice_params;
  770. if (!FillAV1PictureParameter(pic, seq_header, ref_frames, pic_param) ||
  771. !FillAV1SliceParameters(tile_buffers, tile_columns, data, slice_params)) {
  772. return DecodeStatus::kFail;
  773. }
  774. if (!picture_params_) {
  775. picture_params_ = vaapi_wrapper_->CreateVABuffer(
  776. VAPictureParameterBufferType, sizeof(pic_param));
  777. if (!picture_params_)
  778. return DecodeStatus::kFail;
  779. }
  780. // TODO(b/235138734): Once the driver is fixed, re-use the
  781. // VASliceParameterBufferAV1 buffers across frames instead of creating new
  782. // ones every time. Alternatively, consider recreating these buffers only if
  783. // |slice_params| changes from frame to frame.
  784. std::vector<std::unique_ptr<ScopedVABuffer>> slice_params_va_buffers;
  785. for (size_t i = 0; i < slice_params.size(); i++) {
  786. slice_params_va_buffers.push_back(vaapi_wrapper_->CreateVABuffer(
  787. VASliceParameterBufferType, sizeof(VASliceParameterBufferAV1)));
  788. if (!slice_params_va_buffers.back())
  789. return DecodeStatus::kFail;
  790. }
  791. // TODO(hiroh): Don't submit the entire coded data to the buffer. Instead,
  792. // only pass the data starting from the tile list OBU to reduce the size of
  793. // the VA buffer. When this is changed, the encrypted subsample ranges must
  794. // also be adjusted.
  795. // Create VASliceData buffer |encoded_data| every frame so that decoding can
  796. // be more asynchronous than reusing the buffer.
  797. auto encoded_data =
  798. vaapi_wrapper_->CreateVABuffer(VASliceDataBufferType, data.size_bytes());
  799. if (!encoded_data)
  800. return DecodeStatus::kFail;
  801. std::vector<std::pair<VABufferID, VaapiWrapper::VABufferDescriptor>> buffers =
  802. {{picture_params_->id(),
  803. {picture_params_->type(), picture_params_->size(), &pic_param}},
  804. {encoded_data->id(),
  805. {encoded_data->type(), encoded_data->size(), data.data()}}};
  806. for (size_t i = 0; i < slice_params.size(); ++i) {
  807. buffers.push_back({slice_params_va_buffers[i]->id(),
  808. {slice_params_va_buffers[i]->type(),
  809. slice_params_va_buffers[i]->size(), &slice_params[i]}});
  810. }
  811. #if BUILDFLAG(IS_CHROMEOS_ASH)
  812. if (uses_crypto) {
  813. buffers.push_back(
  814. {crypto_params_->id(),
  815. {crypto_params_->type(), crypto_params_->size(), &crypto_param}});
  816. }
  817. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  818. const auto* vaapi_pic = static_cast<const VaapiAV1Picture*>(&pic);
  819. const bool success = vaapi_wrapper_->MapAndCopyAndExecute(
  820. vaapi_pic->reconstruct_va_surface()->id(), buffers);
  821. if (!success && NeedsProtectedSessionRecovery())
  822. return DecodeStatus::kTryAgain;
  823. if (success && IsEncryptedSession())
  824. ProtectedDecodedSucceeded();
  825. return success ? DecodeStatus::kOk : DecodeStatus::kFail;
  826. }
  827. void AV1VaapiVideoDecoderDelegate::OnVAContextDestructionSoon() {
  828. // Destroy the member ScopedVABuffers below since they refer to a VAContextID
  829. // that will be destroyed soon.
  830. picture_params_.reset();
  831. crypto_params_.reset();
  832. }
  833. } // namespace media