h264_vaapi_video_decoder_delegate.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. // Copyright 2018 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/h264_vaapi_video_decoder_delegate.h"
  5. #include <va/va.h>
  6. #include "base/memory/aligned_memory.h"
  7. #include "base/trace_event/trace_event.h"
  8. #include "media/base/cdm_context.h"
  9. #include "media/gpu/decode_surface_handler.h"
  10. #include "media/gpu/h264_dpb.h"
  11. #include "media/gpu/macros.h"
  12. #include "media/gpu/vaapi/vaapi_common.h"
  13. #include "media/gpu/vaapi/vaapi_wrapper.h"
  14. namespace media {
  15. using DecodeStatus = H264Decoder::H264Accelerator::Status;
  16. namespace {
  17. // from ITU-T REC H.264 spec
  18. // section 8.5.6
  19. // "Inverse scanning process for 4x4 transform coefficients and scaling lists"
  20. static constexpr int kZigzagScan4x4[16] = {0, 1, 4, 8, 5, 2, 3, 6,
  21. 9, 12, 13, 10, 7, 11, 14, 15};
  22. // section 8.5.7
  23. // "Inverse scanning process for 8x8 transform coefficients and scaling lists"
  24. static constexpr uint8_t kZigzagScan8x8[64] = {
  25. 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
  26. 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
  27. 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  28. 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  29. int GetSliceHeaderCounter() {
  30. // Needs to be static in case there are multiple active at once, in which case
  31. // they all need unique values.
  32. static base::AtomicSequenceNumber parsed_slice_hdr_counter;
  33. return parsed_slice_hdr_counter.GetNext();
  34. }
  35. } // namespace
  36. // This is the size of the data block which the AMD_SLICE_PARAMS is stored in.
  37. constexpr size_t kAmdEncryptedSliceHeaderSize = 1024;
  38. #if BUILDFLAG(IS_CHROMEOS_ASH)
  39. // These structures match what AMD uses to pass back the extra slice header
  40. // parameters we need for CENCv1. This is stored in the first 1KB of the
  41. // encrypted subsample returned by the cdm-oemcrypto daemon on ChromeOS.
  42. typedef struct AMD_EXTRA_SLICE_PARAMS {
  43. uint8_t bottom_field_flag;
  44. uint8_t num_ref_idx_l0_active_minus1;
  45. uint8_t num_ref_idx_l1_active_minus1;
  46. } AMD_EXTRA_SLICE_PARAMS;
  47. typedef struct AMD_SLICE_PARAMS {
  48. AMD_EXTRA_SLICE_PARAMS va_param;
  49. uint8_t reserved[64 - sizeof(AMD_EXTRA_SLICE_PARAMS)];
  50. VACencSliceParameterBufferH264 cenc_param;
  51. } AMD_SLICE_PARAMS;
  52. static_assert(sizeof(AMD_SLICE_PARAMS) <= kAmdEncryptedSliceHeaderSize,
  53. "Invalid size for AMD_SLICE_PARAMS");
  54. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  55. H264VaapiVideoDecoderDelegate::H264VaapiVideoDecoderDelegate(
  56. DecodeSurfaceHandler<VASurface>* const vaapi_dec,
  57. scoped_refptr<VaapiWrapper> vaapi_wrapper,
  58. ProtectedSessionUpdateCB on_protected_session_update_cb,
  59. CdmContext* cdm_context,
  60. EncryptionScheme encryption_scheme)
  61. : VaapiVideoDecoderDelegate(vaapi_dec,
  62. std::move(vaapi_wrapper),
  63. std::move(on_protected_session_update_cb),
  64. cdm_context,
  65. encryption_scheme) {}
  66. H264VaapiVideoDecoderDelegate::~H264VaapiVideoDecoderDelegate() = default;
  67. scoped_refptr<H264Picture> H264VaapiVideoDecoderDelegate::CreateH264Picture() {
  68. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  69. const auto va_surface = vaapi_dec_->CreateSurface();
  70. if (!va_surface)
  71. return nullptr;
  72. return new VaapiH264Picture(std::move(va_surface));
  73. }
  74. // Fill |va_pic| with default/neutral values.
  75. static void InitVAPicture(VAPictureH264* va_pic) {
  76. memset(va_pic, 0, sizeof(*va_pic));
  77. va_pic->picture_id = VA_INVALID_ID;
  78. va_pic->flags = VA_PICTURE_H264_INVALID;
  79. }
  80. void H264VaapiVideoDecoderDelegate::ProcessSPS(
  81. const H264SPS* sps,
  82. base::span<const uint8_t> sps_nalu_data) {
  83. last_sps_nalu_data_.assign(sps_nalu_data.begin(), sps_nalu_data.end());
  84. }
  85. void H264VaapiVideoDecoderDelegate::ProcessPPS(
  86. const H264PPS* pps,
  87. base::span<const uint8_t> pps_nalu_data) {
  88. last_pps_nalu_data_.assign(pps_nalu_data.begin(), pps_nalu_data.end());
  89. }
  90. DecodeStatus H264VaapiVideoDecoderDelegate::SubmitFrameMetadata(
  91. const H264SPS* sps,
  92. const H264PPS* pps,
  93. const H264DPB& dpb,
  94. const H264Picture::Vector& ref_pic_listp0,
  95. const H264Picture::Vector& ref_pic_listb0,
  96. const H264Picture::Vector& ref_pic_listb1,
  97. scoped_refptr<H264Picture> pic) {
  98. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  99. TRACE_EVENT0("media,gpu",
  100. "H264VaapiVideoDecoderDelegate::SubmitFrameMetadata");
  101. VAPictureParameterBufferH264 pic_param;
  102. memset(&pic_param, 0, sizeof(pic_param));
  103. #if BUILDFLAG(IS_CHROMEOS_ASH)
  104. memset(&crypto_params_, 0, sizeof(crypto_params_));
  105. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  106. full_sample_ = false;
  107. #define FROM_SPS_TO_PP(a) pic_param.a = sps->a
  108. #define FROM_SPS_TO_PP2(a, b) pic_param.b = sps->a
  109. FROM_SPS_TO_PP2(pic_width_in_mbs_minus1, picture_width_in_mbs_minus1);
  110. // This assumes non-interlaced video
  111. FROM_SPS_TO_PP2(pic_height_in_map_units_minus1, picture_height_in_mbs_minus1);
  112. FROM_SPS_TO_PP(bit_depth_luma_minus8);
  113. FROM_SPS_TO_PP(bit_depth_chroma_minus8);
  114. #undef FROM_SPS_TO_PP
  115. #undef FROM_SPS_TO_PP2
  116. #define FROM_SPS_TO_PP_SF(a) pic_param.seq_fields.bits.a = sps->a
  117. #define FROM_SPS_TO_PP_SF2(a, b) pic_param.seq_fields.bits.b = sps->a
  118. FROM_SPS_TO_PP_SF(chroma_format_idc);
  119. FROM_SPS_TO_PP_SF2(separate_colour_plane_flag,
  120. residual_colour_transform_flag);
  121. FROM_SPS_TO_PP_SF(gaps_in_frame_num_value_allowed_flag);
  122. FROM_SPS_TO_PP_SF(frame_mbs_only_flag);
  123. FROM_SPS_TO_PP_SF(mb_adaptive_frame_field_flag);
  124. FROM_SPS_TO_PP_SF(direct_8x8_inference_flag);
  125. pic_param.seq_fields.bits.MinLumaBiPredSize8x8 = (sps->level_idc >= 31);
  126. FROM_SPS_TO_PP_SF(log2_max_frame_num_minus4);
  127. FROM_SPS_TO_PP_SF(pic_order_cnt_type);
  128. FROM_SPS_TO_PP_SF(log2_max_pic_order_cnt_lsb_minus4);
  129. FROM_SPS_TO_PP_SF(delta_pic_order_always_zero_flag);
  130. #undef FROM_SPS_TO_PP_SF
  131. #undef FROM_SPS_TO_PP_SF2
  132. #define FROM_PPS_TO_PP(a) pic_param.a = pps->a
  133. FROM_PPS_TO_PP(pic_init_qp_minus26);
  134. FROM_PPS_TO_PP(pic_init_qs_minus26);
  135. FROM_PPS_TO_PP(chroma_qp_index_offset);
  136. FROM_PPS_TO_PP(second_chroma_qp_index_offset);
  137. #undef FROM_PPS_TO_PP
  138. #define FROM_PPS_TO_PP_PF(a) pic_param.pic_fields.bits.a = pps->a
  139. #define FROM_PPS_TO_PP_PF2(a, b) pic_param.pic_fields.bits.b = pps->a
  140. FROM_PPS_TO_PP_PF(entropy_coding_mode_flag);
  141. FROM_PPS_TO_PP_PF(weighted_pred_flag);
  142. FROM_PPS_TO_PP_PF(weighted_bipred_idc);
  143. FROM_PPS_TO_PP_PF(transform_8x8_mode_flag);
  144. pic_param.pic_fields.bits.field_pic_flag = 0;
  145. FROM_PPS_TO_PP_PF(constrained_intra_pred_flag);
  146. FROM_PPS_TO_PP_PF2(bottom_field_pic_order_in_frame_present_flag,
  147. pic_order_present_flag);
  148. FROM_PPS_TO_PP_PF(deblocking_filter_control_present_flag);
  149. FROM_PPS_TO_PP_PF(redundant_pic_cnt_present_flag);
  150. pic_param.pic_fields.bits.reference_pic_flag = pic->ref;
  151. #undef FROM_PPS_TO_PP_PF
  152. #undef FROM_PPS_TO_PP_PF2
  153. pic_param.frame_num = pic->frame_num;
  154. InitVAPicture(&pic_param.CurrPic);
  155. FillVAPicture(&pic_param.CurrPic, std::move(pic));
  156. // Init reference pictures' array.
  157. for (int i = 0; i < 16; ++i)
  158. InitVAPicture(&pic_param.ReferenceFrames[i]);
  159. // And fill it with picture info from DPB.
  160. FillVARefFramesFromDPB(dpb, pic_param.ReferenceFrames,
  161. std::size(pic_param.ReferenceFrames));
  162. pic_param.num_ref_frames = sps->max_num_ref_frames;
  163. VAIQMatrixBufferH264 iq_matrix_buf;
  164. memset(&iq_matrix_buf, 0, sizeof(iq_matrix_buf));
  165. if (pps->pic_scaling_matrix_present_flag) {
  166. for (int i = 0; i < 6; ++i) {
  167. for (int j = 0; j < 16; ++j)
  168. iq_matrix_buf.ScalingList4x4[i][kZigzagScan4x4[j]] =
  169. pps->scaling_list4x4[i][j];
  170. }
  171. for (int i = 0; i < 2; ++i) {
  172. for (int j = 0; j < 64; ++j)
  173. iq_matrix_buf.ScalingList8x8[i][kZigzagScan8x8[j]] =
  174. pps->scaling_list8x8[i][j];
  175. }
  176. } else {
  177. for (int i = 0; i < 6; ++i) {
  178. for (int j = 0; j < 16; ++j)
  179. iq_matrix_buf.ScalingList4x4[i][kZigzagScan4x4[j]] =
  180. sps->scaling_list4x4[i][j];
  181. }
  182. for (int i = 0; i < 2; ++i) {
  183. for (int j = 0; j < 64; ++j)
  184. iq_matrix_buf.ScalingList8x8[i][kZigzagScan8x8[j]] =
  185. sps->scaling_list8x8[i][j];
  186. }
  187. }
  188. const bool success = vaapi_wrapper_->SubmitBuffers(
  189. {{VAPictureParameterBufferType, sizeof(pic_param), &pic_param},
  190. {VAIQMatrixBufferType, sizeof(iq_matrix_buf), &iq_matrix_buf}});
  191. return success ? DecodeStatus::kOk : DecodeStatus::kFail;
  192. }
  193. DecodeStatus H264VaapiVideoDecoderDelegate::ParseEncryptedSliceHeader(
  194. const std::vector<base::span<const uint8_t>>& data,
  195. const std::vector<SubsampleEntry>& subsamples,
  196. H264SliceHeader* slice_header_out) {
  197. DCHECK(slice_header_out);
  198. DCHECK(!subsamples.empty());
  199. DCHECK(!data.empty());
  200. #if BUILDFLAG(IS_CHROMEOS_ASH)
  201. auto slice_param_buf = std::make_unique<VACencSliceParameterBufferH264>();
  202. // For AMD, we get the slice parameters as structures in the last encrypted
  203. // range.
  204. if (IsTranscrypted()) {
  205. if (subsamples.back().cypher_bytes < kAmdEncryptedSliceHeaderSize) {
  206. DLOG(ERROR) << "AMD CENCv1 data is wrong size: "
  207. << subsamples.back().cypher_bytes;
  208. return DecodeStatus::kFail;
  209. }
  210. const AMD_SLICE_PARAMS* amd_slice_params =
  211. reinterpret_cast<const AMD_SLICE_PARAMS*>(
  212. data.back().data() + subsamples.back().clear_bytes);
  213. // Fill in the AMD specific params.
  214. slice_header_out->bottom_field_flag =
  215. amd_slice_params->va_param.bottom_field_flag;
  216. slice_header_out->num_ref_idx_l0_active_minus1 =
  217. amd_slice_params->va_param.num_ref_idx_l0_active_minus1;
  218. slice_header_out->num_ref_idx_l1_active_minus1 =
  219. amd_slice_params->va_param.num_ref_idx_l1_active_minus1;
  220. // Copy the common parameters that we will fill in below.
  221. memcpy(slice_param_buf.get(), &amd_slice_params->cenc_param,
  222. sizeof(VACencSliceParameterBufferH264));
  223. } else {
  224. // For Intel, this is done by sending in the encryption parameters and the
  225. // encrypted slice header. Then the vaEndPicture call is blocking while it
  226. // decrypts and parses the header parameters. We use VACencStatusBuf which
  227. // allows us to extract the slice header parameters of interest and return
  228. // them to the caller.
  229. VAEncryptionParameters crypto_params = {};
  230. // Don't use the VAEncryptionSegmentInfo vector in the class since we do not
  231. // need to hold this data across calls.
  232. std::vector<VAEncryptionSegmentInfo> segment_info;
  233. ProtectedSessionState state =
  234. SetupDecryptDecode(true /* full sample */, data[0].size(),
  235. &crypto_params, &segment_info, subsamples);
  236. if (state == ProtectedSessionState::kFailed) {
  237. LOG(ERROR) << "ParseEncryptedSliceHeader fails because we couldn't setup "
  238. "the protected session";
  239. return DecodeStatus::kFail;
  240. } else if (state != ProtectedSessionState::kCreated) {
  241. return DecodeStatus::kTryAgain;
  242. }
  243. // For encrypted header parsing, we need to also send the SPS and PPS. Both
  244. // of those and the slice NALU need to be prefixed with the 0x000001 start
  245. // code.
  246. constexpr size_t kStartCodeSize = 3;
  247. constexpr size_t kExtraDataBytes = 3 * kStartCodeSize;
  248. // Adjust the first segment length and init length to compensate for
  249. // inserting the SPS, PPS and 3 start codes.
  250. size_t size_adjustment = last_sps_nalu_data_.size() +
  251. last_pps_nalu_data_.size() + kExtraDataBytes;
  252. size_t total_size = 0;
  253. size_t offset_adjustment = 0;
  254. for (auto& segment : segment_info) {
  255. segment.segment_length += size_adjustment;
  256. segment.init_byte_length += size_adjustment;
  257. segment.segment_start_offset += offset_adjustment;
  258. offset_adjustment += size_adjustment;
  259. // Any additional segments are only adjusted by the start code size;
  260. size_adjustment = kStartCodeSize;
  261. total_size += segment.segment_length;
  262. }
  263. crypto_params.status_report_index = GetSliceHeaderCounter();
  264. // This is based on a sample from Intel for how to use this API.
  265. constexpr size_t kDecryptQuerySizeAndAlignment = 4096;
  266. std::unique_ptr<void, base::AlignedFreeDeleter> surface_memory(
  267. base::AlignedAlloc(kDecryptQuerySizeAndAlignment,
  268. kDecryptQuerySizeAndAlignment));
  269. constexpr size_t kVaQueryCencBufferSize = 2048;
  270. auto back_buffer_mem = std::make_unique<uint8_t[]>(kVaQueryCencBufferSize);
  271. VACencStatusBuf* status_buf =
  272. reinterpret_cast<VACencStatusBuf*>(surface_memory.get());
  273. status_buf->status = VA_ENCRYPTION_STATUS_INCOMPLETE;
  274. status_buf->buf = back_buffer_mem.get();
  275. status_buf->buf_size = kVaQueryCencBufferSize;
  276. status_buf->slice_buf_type = VaCencSliceBufParamter;
  277. status_buf->slice_buf_size = sizeof(VACencSliceParameterBufferH264);
  278. status_buf->slice_buf = slice_param_buf.get();
  279. constexpr int kCencStatusSurfaceDimension = 64;
  280. auto buffer_ptr_alloc = std::make_unique<uintptr_t>();
  281. uintptr_t* buffer_ptr =
  282. reinterpret_cast<uintptr_t*>(buffer_ptr_alloc.get());
  283. buffer_ptr[0] = reinterpret_cast<uintptr_t>(surface_memory.get());
  284. auto surface = vaapi_wrapper_->CreateVASurfaceForUserPtr(
  285. gfx::Size(kCencStatusSurfaceDimension, kCencStatusSurfaceDimension),
  286. buffer_ptr,
  287. 3 * kCencStatusSurfaceDimension * kCencStatusSurfaceDimension);
  288. if (!surface) {
  289. DVLOG(1) << "Failed allocating surface for decrypt status";
  290. return DecodeStatus::kFail;
  291. }
  292. // Assembles the 'slice data' which is the SPS, PPS, encrypted SEIS and
  293. // encrypted slice data, each of which is also prefixed by the 0x000001
  294. // start code.
  295. std::vector<uint8_t> full_data;
  296. const std::vector<uint8_t> start_code = {0u, 0u, 1u};
  297. full_data.reserve(total_size);
  298. full_data.insert(full_data.end(), start_code.begin(), start_code.end());
  299. full_data.insert(full_data.end(), last_sps_nalu_data_.begin(),
  300. last_sps_nalu_data_.end());
  301. full_data.insert(full_data.end(), start_code.begin(), start_code.end());
  302. full_data.insert(full_data.end(), last_pps_nalu_data_.begin(),
  303. last_pps_nalu_data_.end());
  304. for (auto& nalu : data) {
  305. full_data.insert(full_data.end(), start_code.begin(), start_code.end());
  306. full_data.insert(full_data.end(), nalu.begin(), nalu.end());
  307. }
  308. if (!vaapi_wrapper_->SubmitBuffers(
  309. {{VAEncryptionParameterBufferType, sizeof(crypto_params),
  310. &crypto_params},
  311. {VAProtectedSliceDataBufferType, full_data.size(),
  312. full_data.data()}})) {
  313. DVLOG(1) << "Failure submitting encrypted slice header buffers";
  314. return DecodeStatus::kFail;
  315. }
  316. if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(surface->id())) {
  317. LOG(ERROR) << "Failed executing for slice header decrypt";
  318. return DecodeStatus::kFail;
  319. }
  320. if (status_buf->status != VA_ENCRYPTION_STATUS_SUCCESSFUL) {
  321. LOG(ERROR) << "Failure status in encrypted header parsing: "
  322. << static_cast<int>(status_buf->status);
  323. return DecodeStatus::kFail;
  324. }
  325. slice_header_out->full_sample_index =
  326. status_buf->status_report_index_feedback;
  327. }
  328. // Read the parsed slice header data back and populate the structure with it.
  329. slice_header_out->idr_pic_flag = !!slice_param_buf->idr_pic_flag;
  330. slice_header_out->nal_ref_idc = slice_param_buf->nal_ref_idc;
  331. // The last span in |data| will be the slice header NALU.
  332. slice_header_out->nalu_data = data.back().data();
  333. slice_header_out->nalu_size = data.back().size();
  334. slice_header_out->slice_type = slice_param_buf->slice_type;
  335. slice_header_out->frame_num = slice_param_buf->frame_number;
  336. slice_header_out->idr_pic_id = slice_param_buf->idr_pic_id;
  337. slice_header_out->pic_order_cnt_lsb = slice_param_buf->pic_order_cnt_lsb;
  338. slice_header_out->delta_pic_order_cnt_bottom =
  339. slice_param_buf->delta_pic_order_cnt_bottom;
  340. slice_header_out->delta_pic_order_cnt0 =
  341. slice_param_buf->delta_pic_order_cnt[0];
  342. slice_header_out->delta_pic_order_cnt1 =
  343. slice_param_buf->delta_pic_order_cnt[1];
  344. slice_header_out->no_output_of_prior_pics_flag =
  345. slice_param_buf->ref_pic_fields.bits.no_output_of_prior_pics_flag;
  346. slice_header_out->long_term_reference_flag =
  347. slice_param_buf->ref_pic_fields.bits.long_term_reference_flag;
  348. slice_header_out->adaptive_ref_pic_marking_mode_flag =
  349. slice_param_buf->ref_pic_fields.bits.adaptive_ref_pic_marking_mode_flag;
  350. const size_t num_dec_ref_pics =
  351. slice_param_buf->ref_pic_fields.bits.dec_ref_pic_marking_count;
  352. if (num_dec_ref_pics > H264SliceHeader::kRefListSize) {
  353. DVLOG(1) << "Invalid number of dec_ref_pics: " << num_dec_ref_pics;
  354. return DecodeStatus::kFail;
  355. }
  356. for (size_t i = 0; i < num_dec_ref_pics; ++i) {
  357. slice_header_out->ref_pic_marking[i].memory_mgmnt_control_operation =
  358. slice_param_buf->memory_management_control_operation[i];
  359. slice_header_out->ref_pic_marking[i].difference_of_pic_nums_minus1 =
  360. slice_param_buf->difference_of_pic_nums_minus1[i];
  361. slice_header_out->ref_pic_marking[i].long_term_pic_num =
  362. slice_param_buf->long_term_pic_num[i];
  363. slice_header_out->ref_pic_marking[i].long_term_frame_idx =
  364. slice_param_buf->long_term_frame_idx[i];
  365. slice_header_out->ref_pic_marking[i].max_long_term_frame_idx_plus1 =
  366. slice_param_buf->max_long_term_frame_idx_plus1[i];
  367. }
  368. slice_header_out->full_sample_encryption = true;
  369. return DecodeStatus::kOk;
  370. #else // BUILDFLAG(IS_CHROMEOS_ASH)
  371. return DecodeStatus::kFail;
  372. #endif
  373. }
  374. DecodeStatus H264VaapiVideoDecoderDelegate::SubmitSlice(
  375. const H264PPS* pps,
  376. const H264SliceHeader* slice_hdr,
  377. const H264Picture::Vector& ref_pic_list0,
  378. const H264Picture::Vector& ref_pic_list1,
  379. scoped_refptr<H264Picture> pic,
  380. const uint8_t* data,
  381. size_t size,
  382. const std::vector<SubsampleEntry>& subsamples) {
  383. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  384. TRACE_EVENT0("media,gpu", "H264VaapiVideoDecoderDelegate::SubmitSlice");
  385. if (slice_hdr->full_sample_encryption && !IsTranscrypted()) {
  386. // We do not need to submit all the slice data, instead we just submit the
  387. // index for what was already sent for parsing. The HW decoder already has
  388. // the full slice data from when we decrypted the header on Intel.
  389. full_sample_ = true;
  390. VACencStatusParameters cenc_status = {};
  391. cenc_status.status_report_index_feedback = slice_hdr->full_sample_index;
  392. return vaapi_wrapper_->SubmitBuffer(VACencStatusParameterBufferType,
  393. sizeof(VACencStatusParameters),
  394. &cenc_status)
  395. ? DecodeStatus::kOk
  396. : DecodeStatus::kFail;
  397. }
  398. #if BUILDFLAG(IS_CHROMEOS_ASH)
  399. if (IsEncryptedSession()) {
  400. const ProtectedSessionState state = SetupDecryptDecode(
  401. /*full_sample=*/false, size, &crypto_params_, &encryption_segment_info_,
  402. subsamples);
  403. if (state == ProtectedSessionState::kFailed) {
  404. LOG(ERROR) << "SubmitSlice fails because we couldn't setup the protected "
  405. "session";
  406. return DecodeStatus::kFail;
  407. } else if (state != ProtectedSessionState::kCreated) {
  408. return DecodeStatus::kTryAgain;
  409. }
  410. }
  411. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  412. VASliceParameterBufferH264 slice_param;
  413. memset(&slice_param, 0, sizeof(slice_param));
  414. slice_param.slice_data_size = slice_hdr->nalu_size;
  415. slice_param.slice_data_offset = 0;
  416. slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
  417. slice_param.slice_data_bit_offset = slice_hdr->header_bit_size;
  418. #define SHDRToSP(a) slice_param.a = slice_hdr->a
  419. SHDRToSP(first_mb_in_slice);
  420. slice_param.slice_type = slice_hdr->slice_type % 5;
  421. SHDRToSP(direct_spatial_mv_pred_flag);
  422. // TODO posciak: make sure parser sets those even when override flags
  423. // in slice header is off.
  424. SHDRToSP(num_ref_idx_l0_active_minus1);
  425. SHDRToSP(num_ref_idx_l1_active_minus1);
  426. SHDRToSP(cabac_init_idc);
  427. SHDRToSP(slice_qp_delta);
  428. SHDRToSP(disable_deblocking_filter_idc);
  429. SHDRToSP(slice_alpha_c0_offset_div2);
  430. SHDRToSP(slice_beta_offset_div2);
  431. if (((slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) &&
  432. pps->weighted_pred_flag) ||
  433. (slice_hdr->IsBSlice() && pps->weighted_bipred_idc == 1)) {
  434. SHDRToSP(luma_log2_weight_denom);
  435. SHDRToSP(chroma_log2_weight_denom);
  436. SHDRToSP(luma_weight_l0_flag);
  437. SHDRToSP(luma_weight_l1_flag);
  438. SHDRToSP(chroma_weight_l0_flag);
  439. SHDRToSP(chroma_weight_l1_flag);
  440. for (int i = 0; i <= slice_param.num_ref_idx_l0_active_minus1; ++i) {
  441. slice_param.luma_weight_l0[i] =
  442. slice_hdr->pred_weight_table_l0.luma_weight[i];
  443. slice_param.luma_offset_l0[i] =
  444. slice_hdr->pred_weight_table_l0.luma_offset[i];
  445. for (int j = 0; j < 2; ++j) {
  446. slice_param.chroma_weight_l0[i][j] =
  447. slice_hdr->pred_weight_table_l0.chroma_weight[i][j];
  448. slice_param.chroma_offset_l0[i][j] =
  449. slice_hdr->pred_weight_table_l0.chroma_offset[i][j];
  450. }
  451. }
  452. if (slice_hdr->IsBSlice()) {
  453. for (int i = 0; i <= slice_param.num_ref_idx_l1_active_minus1; ++i) {
  454. slice_param.luma_weight_l1[i] =
  455. slice_hdr->pred_weight_table_l1.luma_weight[i];
  456. slice_param.luma_offset_l1[i] =
  457. slice_hdr->pred_weight_table_l1.luma_offset[i];
  458. for (int j = 0; j < 2; ++j) {
  459. slice_param.chroma_weight_l1[i][j] =
  460. slice_hdr->pred_weight_table_l1.chroma_weight[i][j];
  461. slice_param.chroma_offset_l1[i][j] =
  462. slice_hdr->pred_weight_table_l1.chroma_offset[i][j];
  463. }
  464. }
  465. }
  466. }
  467. static_assert(
  468. std::size(slice_param.RefPicList0) == std::size(slice_param.RefPicList1),
  469. "Invalid RefPicList sizes");
  470. for (size_t i = 0; i < std::size(slice_param.RefPicList0); ++i) {
  471. InitVAPicture(&slice_param.RefPicList0[i]);
  472. InitVAPicture(&slice_param.RefPicList1[i]);
  473. }
  474. for (size_t i = 0;
  475. i < ref_pic_list0.size() && i < std::size(slice_param.RefPicList0);
  476. ++i) {
  477. if (ref_pic_list0[i])
  478. FillVAPicture(&slice_param.RefPicList0[i], ref_pic_list0[i]);
  479. }
  480. for (size_t i = 0;
  481. i < ref_pic_list1.size() && i < std::size(slice_param.RefPicList1);
  482. ++i) {
  483. if (ref_pic_list1[i])
  484. FillVAPicture(&slice_param.RefPicList1[i], ref_pic_list1[i]);
  485. }
  486. if (IsTranscrypted()) {
  487. CHECK_EQ(subsamples.size(), 1u);
  488. uint32_t cypher_skip =
  489. slice_hdr->full_sample_encryption ? kAmdEncryptedSliceHeaderSize : 0;
  490. return vaapi_wrapper_->SubmitBuffers(
  491. {{VAProtectedSliceDataBufferType, GetDecryptKeyId().length(),
  492. GetDecryptKeyId().data()},
  493. {VASliceParameterBufferType, sizeof(slice_param), &slice_param},
  494. {VASliceDataBufferType,
  495. subsamples[0].cypher_bytes - cypher_skip,
  496. data + subsamples[0].clear_bytes + cypher_skip}})
  497. ? DecodeStatus::kOk
  498. : DecodeStatus::kFail;
  499. }
  500. return vaapi_wrapper_->SubmitBuffers(
  501. {{VASliceParameterBufferType, sizeof(slice_param), &slice_param},
  502. {VASliceDataBufferType, size, data}})
  503. ? DecodeStatus::kOk
  504. : DecodeStatus::kFail;
  505. }
  506. DecodeStatus H264VaapiVideoDecoderDelegate::SubmitDecode(
  507. scoped_refptr<H264Picture> pic) {
  508. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  509. TRACE_EVENT0("media,gpu", "H264VaapiVideoDecoderDelegate::SubmitDecode");
  510. #if BUILDFLAG(IS_CHROMEOS_ASH)
  511. if (IsEncryptedSession() && !full_sample_ &&
  512. !vaapi_wrapper_->SubmitBuffer(VAEncryptionParameterBufferType,
  513. sizeof(crypto_params_), &crypto_params_)) {
  514. return DecodeStatus::kFail;
  515. }
  516. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  517. const VaapiH264Picture* vaapi_pic = pic->AsVaapiH264Picture();
  518. CHECK(
  519. gfx::Rect(vaapi_pic->va_surface()->size()).Contains(pic->visible_rect()));
  520. const bool success = vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
  521. vaapi_pic->GetVASurfaceID());
  522. #if BUILDFLAG(IS_CHROMEOS_ASH)
  523. encryption_segment_info_.clear();
  524. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  525. if (!success && NeedsProtectedSessionRecovery())
  526. return DecodeStatus::kTryAgain;
  527. if (success && IsEncryptedSession())
  528. ProtectedDecodedSucceeded();
  529. return success ? DecodeStatus::kOk : DecodeStatus::kFail;
  530. }
  531. bool H264VaapiVideoDecoderDelegate::OutputPicture(
  532. scoped_refptr<H264Picture> pic) {
  533. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  534. const VaapiH264Picture* vaapi_pic = pic->AsVaapiH264Picture();
  535. vaapi_dec_->SurfaceReady(vaapi_pic->va_surface(), vaapi_pic->bitstream_id(),
  536. vaapi_pic->visible_rect(),
  537. vaapi_pic->get_colorspace());
  538. return true;
  539. }
  540. void H264VaapiVideoDecoderDelegate::Reset() {
  541. DETACH_FROM_SEQUENCE(sequence_checker_);
  542. #if BUILDFLAG(IS_CHROMEOS_ASH)
  543. encryption_segment_info_.clear();
  544. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  545. vaapi_wrapper_->DestroyPendingBuffers();
  546. }
  547. DecodeStatus H264VaapiVideoDecoderDelegate::SetStream(
  548. base::span<const uint8_t> /*stream*/,
  549. const DecryptConfig* decrypt_config) {
  550. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  551. if (!decrypt_config)
  552. return Status::kOk;
  553. return SetDecryptConfig(decrypt_config->Clone()) ? Status::kOk
  554. : Status::kFail;
  555. }
  556. void H264VaapiVideoDecoderDelegate::FillVAPicture(
  557. VAPictureH264* va_pic,
  558. scoped_refptr<H264Picture> pic) {
  559. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  560. VASurfaceID va_surface_id = VA_INVALID_SURFACE;
  561. if (!pic->nonexisting)
  562. va_surface_id = pic->AsVaapiH264Picture()->GetVASurfaceID();
  563. va_pic->picture_id = va_surface_id;
  564. va_pic->frame_idx = pic->frame_num;
  565. va_pic->flags = 0;
  566. switch (pic->field) {
  567. case H264Picture::FIELD_NONE:
  568. break;
  569. case H264Picture::FIELD_TOP:
  570. va_pic->flags |= VA_PICTURE_H264_TOP_FIELD;
  571. break;
  572. case H264Picture::FIELD_BOTTOM:
  573. va_pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
  574. break;
  575. }
  576. if (pic->ref) {
  577. va_pic->flags |= pic->long_term ? VA_PICTURE_H264_LONG_TERM_REFERENCE
  578. : VA_PICTURE_H264_SHORT_TERM_REFERENCE;
  579. }
  580. va_pic->TopFieldOrderCnt = pic->top_field_order_cnt;
  581. va_pic->BottomFieldOrderCnt = pic->bottom_field_order_cnt;
  582. }
  583. int H264VaapiVideoDecoderDelegate::FillVARefFramesFromDPB(
  584. const H264DPB& dpb,
  585. VAPictureH264* va_pics,
  586. int num_pics) {
  587. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  588. H264Picture::Vector::const_reverse_iterator rit;
  589. int i;
  590. // Return reference frames in reverse order of insertion.
  591. // Libva does not document this, but other implementations (e.g. mplayer)
  592. // do it this way as well.
  593. for (rit = dpb.rbegin(), i = 0; rit != dpb.rend() && i < num_pics; ++rit) {
  594. if ((*rit)->ref)
  595. FillVAPicture(&va_pics[i++], *rit);
  596. }
  597. return i;
  598. }
  599. } // namespace media