vp9_vaapi_video_decoder_delegate.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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/vp9_vaapi_video_decoder_delegate.h"
  5. #include <type_traits>
  6. #include "base/numerics/checked_math.h"
  7. #include "base/trace_event/trace_event.h"
  8. #include "build/chromeos_buildflags.h"
  9. #include "media/gpu/decode_surface_handler.h"
  10. #include "media/gpu/macros.h"
  11. #include "media/gpu/vaapi/va_surface.h"
  12. #include "media/gpu/vaapi/vaapi_common.h"
  13. #include "media/gpu/vaapi/vaapi_wrapper.h"
  14. namespace media {
  15. using DecodeStatus = VP9Decoder::VP9Accelerator::Status;
  16. VP9VaapiVideoDecoderDelegate::VP9VaapiVideoDecoderDelegate(
  17. DecodeSurfaceHandler<VASurface>* const vaapi_dec,
  18. scoped_refptr<VaapiWrapper> vaapi_wrapper,
  19. ProtectedSessionUpdateCB on_protected_session_update_cb,
  20. CdmContext* cdm_context,
  21. EncryptionScheme encryption_scheme)
  22. : VaapiVideoDecoderDelegate(vaapi_dec,
  23. std::move(vaapi_wrapper),
  24. std::move(on_protected_session_update_cb),
  25. cdm_context,
  26. encryption_scheme) {}
  27. VP9VaapiVideoDecoderDelegate::~VP9VaapiVideoDecoderDelegate() {
  28. DCHECK(!picture_params_);
  29. DCHECK(!slice_params_);
  30. DCHECK(!crypto_params_);
  31. DCHECK(!protected_params_);
  32. }
  33. scoped_refptr<VP9Picture> VP9VaapiVideoDecoderDelegate::CreateVP9Picture() {
  34. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  35. const auto va_surface = vaapi_dec_->CreateSurface();
  36. if (!va_surface)
  37. return nullptr;
  38. return new VaapiVP9Picture(std::move(va_surface));
  39. }
  40. DecodeStatus VP9VaapiVideoDecoderDelegate::SubmitDecode(
  41. scoped_refptr<VP9Picture> pic,
  42. const Vp9SegmentationParams& seg,
  43. const Vp9LoopFilterParams& lf,
  44. const Vp9ReferenceFrameVector& ref_frames,
  45. base::OnceClosure done_cb) {
  46. TRACE_EVENT0("media,gpu", "VP9VaapiVideoDecoderDelegate::SubmitDecode");
  47. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  48. // |done_cb| should be null as we return false from
  49. // NeedsCompressedHeaderParsed().
  50. DCHECK(!done_cb);
  51. const Vp9FrameHeader* frame_hdr = pic->frame_hdr.get();
  52. DCHECK(frame_hdr);
  53. VADecPictureParameterBufferVP9 pic_param{};
  54. VASliceParameterBufferVP9 slice_param{};
  55. if (!picture_params_) {
  56. picture_params_ = vaapi_wrapper_->CreateVABuffer(
  57. VAPictureParameterBufferType, sizeof(pic_param));
  58. if (!picture_params_)
  59. return DecodeStatus::kFail;
  60. }
  61. if (!slice_params_) {
  62. slice_params_ = vaapi_wrapper_->CreateVABuffer(VASliceParameterBufferType,
  63. sizeof(slice_param));
  64. if (!slice_params_)
  65. return DecodeStatus::kFail;
  66. }
  67. #if BUILDFLAG(IS_CHROMEOS_ASH)
  68. const DecryptConfig* decrypt_config = pic->decrypt_config();
  69. if (decrypt_config && !SetDecryptConfig(decrypt_config->Clone()))
  70. return DecodeStatus::kFail;
  71. bool uses_crypto = false;
  72. std::vector<VAEncryptionSegmentInfo> encryption_segment_info;
  73. VAEncryptionParameters crypto_param{};
  74. if (IsEncryptedSession()) {
  75. const ProtectedSessionState state = SetupDecryptDecode(
  76. /*full_sample=*/false, frame_hdr->frame_size, &crypto_param,
  77. &encryption_segment_info,
  78. decrypt_config ? decrypt_config->subsamples()
  79. : std::vector<SubsampleEntry>());
  80. if (state == ProtectedSessionState::kFailed) {
  81. LOG(ERROR)
  82. << "SubmitDecode fails because we couldn't setup the protected "
  83. "session";
  84. return DecodeStatus::kFail;
  85. } else if (state != ProtectedSessionState::kCreated) {
  86. return DecodeStatus::kTryAgain;
  87. }
  88. uses_crypto = true;
  89. if (!crypto_params_) {
  90. crypto_params_ = vaapi_wrapper_->CreateVABuffer(
  91. VAEncryptionParameterBufferType, sizeof(crypto_param));
  92. if (!crypto_params_)
  93. return DecodeStatus::kFail;
  94. }
  95. }
  96. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  97. pic_param.frame_width = base::checked_cast<uint16_t>(frame_hdr->frame_width);
  98. pic_param.frame_height =
  99. base::checked_cast<uint16_t>(frame_hdr->frame_height);
  100. CHECK_EQ(kVp9NumRefFrames, std::size(pic_param.reference_frames));
  101. for (size_t i = 0; i < std::size(pic_param.reference_frames); ++i) {
  102. auto ref_pic = ref_frames.GetFrame(i);
  103. if (ref_pic) {
  104. pic_param.reference_frames[i] =
  105. ref_pic->AsVaapiVP9Picture()->GetVASurfaceID();
  106. } else {
  107. pic_param.reference_frames[i] = VA_INVALID_SURFACE;
  108. }
  109. }
  110. #define FHDR_TO_PP_PF1(a) pic_param.pic_fields.bits.a = frame_hdr->a
  111. #define FHDR_TO_PP_PF2(a, b) pic_param.pic_fields.bits.a = b
  112. FHDR_TO_PP_PF2(subsampling_x, frame_hdr->subsampling_x == 1);
  113. FHDR_TO_PP_PF2(subsampling_y, frame_hdr->subsampling_y == 1);
  114. FHDR_TO_PP_PF2(frame_type, frame_hdr->IsKeyframe() ? 0 : 1);
  115. FHDR_TO_PP_PF1(show_frame);
  116. FHDR_TO_PP_PF1(error_resilient_mode);
  117. FHDR_TO_PP_PF1(intra_only);
  118. FHDR_TO_PP_PF1(allow_high_precision_mv);
  119. FHDR_TO_PP_PF2(mcomp_filter_type, frame_hdr->interpolation_filter);
  120. FHDR_TO_PP_PF1(frame_parallel_decoding_mode);
  121. FHDR_TO_PP_PF1(reset_frame_context);
  122. FHDR_TO_PP_PF1(refresh_frame_context);
  123. FHDR_TO_PP_PF2(frame_context_idx, frame_hdr->frame_context_idx_to_save_probs);
  124. FHDR_TO_PP_PF2(segmentation_enabled, seg.enabled);
  125. FHDR_TO_PP_PF2(segmentation_temporal_update, seg.temporal_update);
  126. FHDR_TO_PP_PF2(segmentation_update_map, seg.update_map);
  127. FHDR_TO_PP_PF2(last_ref_frame, frame_hdr->ref_frame_idx[0]);
  128. FHDR_TO_PP_PF2(last_ref_frame_sign_bias,
  129. frame_hdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_LAST]);
  130. FHDR_TO_PP_PF2(golden_ref_frame, frame_hdr->ref_frame_idx[1]);
  131. FHDR_TO_PP_PF2(golden_ref_frame_sign_bias,
  132. frame_hdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_GOLDEN]);
  133. FHDR_TO_PP_PF2(alt_ref_frame, frame_hdr->ref_frame_idx[2]);
  134. FHDR_TO_PP_PF2(alt_ref_frame_sign_bias,
  135. frame_hdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_ALTREF]);
  136. FHDR_TO_PP_PF2(lossless_flag, frame_hdr->quant_params.IsLossless());
  137. #undef FHDR_TO_PP_PF2
  138. #undef FHDR_TO_PP_PF1
  139. pic_param.filter_level = lf.level;
  140. pic_param.sharpness_level = lf.sharpness;
  141. pic_param.log2_tile_rows = frame_hdr->tile_rows_log2;
  142. pic_param.log2_tile_columns = frame_hdr->tile_cols_log2;
  143. pic_param.frame_header_length_in_bytes = frame_hdr->uncompressed_header_size;
  144. pic_param.first_partition_size = frame_hdr->header_size_in_bytes;
  145. SafeArrayMemcpy(pic_param.mb_segment_tree_probs, seg.tree_probs);
  146. SafeArrayMemcpy(pic_param.segment_pred_probs, seg.pred_probs);
  147. pic_param.profile = frame_hdr->profile;
  148. pic_param.bit_depth = frame_hdr->bit_depth;
  149. DCHECK((pic_param.profile == 0 && pic_param.bit_depth == 8) ||
  150. (pic_param.profile == 2 && pic_param.bit_depth == 10));
  151. slice_param.slice_data_size = frame_hdr->frame_size;
  152. slice_param.slice_data_offset = 0;
  153. slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
  154. static_assert(
  155. std::extent<decltype(Vp9SegmentationParams::feature_enabled)>() ==
  156. std::extent<decltype(slice_param.seg_param)>(),
  157. "seg_param array of incorrect size");
  158. for (size_t i = 0; i < std::size(slice_param.seg_param); ++i) {
  159. VASegmentParameterVP9& seg_param = slice_param.seg_param[i];
  160. #define SEG_TO_SP_SF(a, b) seg_param.segment_flags.fields.a = b
  161. SEG_TO_SP_SF(
  162. segment_reference_enabled,
  163. seg.FeatureEnabled(i, Vp9SegmentationParams::SEG_LVL_REF_FRAME));
  164. SEG_TO_SP_SF(segment_reference,
  165. seg.FeatureData(i, Vp9SegmentationParams::SEG_LVL_REF_FRAME));
  166. SEG_TO_SP_SF(segment_reference_skipped,
  167. seg.FeatureEnabled(i, Vp9SegmentationParams::SEG_LVL_SKIP));
  168. #undef SEG_TO_SP_SF
  169. SafeArrayMemcpy(seg_param.filter_level, lf.lvl[i]);
  170. seg_param.luma_dc_quant_scale = seg.y_dequant[i][0];
  171. seg_param.luma_ac_quant_scale = seg.y_dequant[i][1];
  172. seg_param.chroma_dc_quant_scale = seg.uv_dequant[i][0];
  173. seg_param.chroma_ac_quant_scale = seg.uv_dequant[i][1];
  174. }
  175. // Create VASliceData buffer |encoded_data| every frame so that decoding can
  176. // be more asynchronous than reusing the buffer.
  177. std::unique_ptr<ScopedVABuffer> encoded_data;
  178. std::vector<std::pair<VABufferID, VaapiWrapper::VABufferDescriptor>> buffers =
  179. {{picture_params_->id(),
  180. {picture_params_->type(), picture_params_->size(), &pic_param}},
  181. {slice_params_->id(),
  182. {slice_params_->type(), slice_params_->size(), &slice_param}}};
  183. #if BUILDFLAG(IS_CHROMEOS_ASH)
  184. std::unique_ptr<uint8_t[]> protected_vp9_data;
  185. std::string amd_decrypt_params;
  186. if (IsTranscrypted()) {
  187. CHECK(decrypt_config);
  188. CHECK_EQ(decrypt_config->subsamples().size(), 1u);
  189. if (!protected_params_) {
  190. protected_params_ = vaapi_wrapper_->CreateVABuffer(
  191. VAProtectedSliceDataBufferType, decrypt_config->key_id().length());
  192. if (!protected_params_)
  193. return DecodeStatus::kFail;
  194. }
  195. DCHECK_EQ(decrypt_config->key_id().length(), protected_params_->size());
  196. // For VP9 superframes, the IV may have been incremented, so copy that
  197. // back into the decryption parameters. The decryption parameters struct has
  198. // a uint32_t for the first parameter, and the second is the 128-bit IV and
  199. // then various other fields. Total max structure size is 128 bytes. The
  200. // structure definition is in ChromeOS internal code so we do not reference
  201. // it directly here.
  202. constexpr uint32_t dp_iv_offset = sizeof(uint32_t);
  203. amd_decrypt_params = decrypt_config->key_id();
  204. memcpy(&amd_decrypt_params[dp_iv_offset], decrypt_config->iv().data(),
  205. DecryptConfig::kDecryptionKeySize);
  206. buffers.push_back({protected_params_->id(),
  207. {protected_params_->type(), protected_params_->size(),
  208. amd_decrypt_params.data()}});
  209. encoded_data = vaapi_wrapper_->CreateVABuffer(
  210. VASliceDataBufferType,
  211. base::strict_cast<size_t>(
  212. decrypt_config->subsamples()[0].cypher_bytes));
  213. if (!encoded_data)
  214. return DecodeStatus::kFail;
  215. buffers.push_back(
  216. {encoded_data->id(),
  217. {encoded_data->type(), encoded_data->size(),
  218. frame_hdr->data + decrypt_config->subsamples()[0].clear_bytes}});
  219. } else {
  220. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  221. encoded_data = vaapi_wrapper_->CreateVABuffer(VASliceDataBufferType,
  222. frame_hdr->frame_size);
  223. if (!encoded_data)
  224. return DecodeStatus::kFail;
  225. buffers.push_back(
  226. {encoded_data->id(),
  227. {encoded_data->type(), encoded_data->size(), frame_hdr->data}});
  228. #if BUILDFLAG(IS_CHROMEOS_ASH)
  229. }
  230. if (uses_crypto) {
  231. buffers.push_back(
  232. {crypto_params_->id(),
  233. {crypto_params_->type(), crypto_params_->size(), &crypto_param}});
  234. }
  235. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  236. const VaapiVP9Picture* vaapi_pic = pic->AsVaapiVP9Picture();
  237. CHECK(
  238. gfx::Rect(vaapi_pic->va_surface()->size()).Contains(pic->visible_rect()));
  239. bool success = vaapi_wrapper_->MapAndCopyAndExecute(
  240. vaapi_pic->GetVASurfaceID(), buffers);
  241. if (!success && NeedsProtectedSessionRecovery())
  242. return DecodeStatus::kTryAgain;
  243. if (success && IsEncryptedSession())
  244. ProtectedDecodedSucceeded();
  245. return success ? DecodeStatus::kOk : DecodeStatus::kFail;
  246. }
  247. bool VP9VaapiVideoDecoderDelegate::OutputPicture(
  248. scoped_refptr<VP9Picture> pic) {
  249. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  250. const VaapiVP9Picture* vaapi_pic = pic->AsVaapiVP9Picture();
  251. vaapi_dec_->SurfaceReady(vaapi_pic->va_surface(), vaapi_pic->bitstream_id(),
  252. vaapi_pic->visible_rect(),
  253. vaapi_pic->get_colorspace());
  254. return true;
  255. }
  256. bool VP9VaapiVideoDecoderDelegate::NeedsCompressedHeaderParsed() const {
  257. return false;
  258. }
  259. bool VP9VaapiVideoDecoderDelegate::GetFrameContext(
  260. scoped_refptr<VP9Picture> pic,
  261. Vp9FrameContext* frame_ctx) {
  262. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  263. NOTIMPLEMENTED() << "Frame context update not supported";
  264. return false;
  265. }
  266. void VP9VaapiVideoDecoderDelegate::OnVAContextDestructionSoon() {
  267. // Destroy the member ScopedVABuffers below since they refer to a VAContextID
  268. // that will be destroyed soon.
  269. picture_params_.reset();
  270. slice_params_.reset();
  271. crypto_params_.reset();
  272. protected_params_.reset();
  273. }
  274. } // namespace media