d3d11_h264_accelerator.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. // Copyright 2016 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/windows/d3d11_h264_accelerator.h"
  5. #include <windows.h>
  6. #include "base/memory/ptr_util.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/metrics/histogram_functions.h"
  9. #include "base/strings/string_number_conversions.h"
  10. #include "base/trace_event/trace_event.h"
  11. #include "media/base/media_log.h"
  12. #include "media/base/win/mf_helpers.h"
  13. #include "media/gpu/h264_decoder.h"
  14. #include "media/gpu/h264_dpb.h"
  15. #include "media/gpu/windows/d3d11_picture_buffer.h"
  16. #include "third_party/angle/include/EGL/egl.h"
  17. #include "third_party/angle/include/EGL/eglext.h"
  18. #include "ui/gfx/color_space.h"
  19. #include "ui/gl/gl_bindings.h"
  20. #include "ui/gl/gl_context.h"
  21. #include "ui/gl/gl_image_dxgi.h"
  22. #include "ui/gl/gl_surface_egl.h"
  23. #include "ui/gl/scoped_binders.h"
  24. namespace media {
  25. using DecoderStatus = H264Decoder::H264Accelerator::Status;
  26. namespace {
  27. // Converts SubsampleEntry to D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK.
  28. void AppendSubsamples(
  29. const std::vector<SubsampleEntry>& from,
  30. std::vector<D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK>* to) {
  31. for (const auto& from_entry : from) {
  32. D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK subsample = {};
  33. subsample.ClearSize = from_entry.clear_bytes;
  34. subsample.EncryptedSize = from_entry.cypher_bytes;
  35. to->push_back(subsample);
  36. }
  37. }
  38. } // namespace
  39. class D3D11H264Picture : public H264Picture {
  40. public:
  41. D3D11H264Picture(D3D11PictureBuffer* picture)
  42. : picture(picture), picture_index_(picture->picture_index()) {
  43. picture->set_in_picture_use(true);
  44. }
  45. raw_ptr<D3D11PictureBuffer> picture;
  46. size_t picture_index_;
  47. D3D11H264Picture* AsD3D11H264Picture() override { return this; }
  48. protected:
  49. ~D3D11H264Picture() override;
  50. };
  51. D3D11H264Picture::~D3D11H264Picture() {
  52. picture->set_in_picture_use(false);
  53. }
  54. D3D11H264Accelerator::D3D11H264Accelerator(
  55. D3D11VideoDecoderClient* client,
  56. MediaLog* media_log,
  57. ComD3D11VideoDevice video_device,
  58. std::unique_ptr<VideoContextWrapper> video_context)
  59. : client_(client),
  60. media_log_(media_log),
  61. video_device_(video_device),
  62. video_context_(std::move(video_context)) {
  63. DCHECK(client);
  64. DCHECK(media_log_);
  65. client->SetDecoderCB(base::BindRepeating(
  66. &D3D11H264Accelerator::SetVideoDecoder, base::Unretained(this)));
  67. }
  68. D3D11H264Accelerator::~D3D11H264Accelerator() {}
  69. scoped_refptr<H264Picture> D3D11H264Accelerator::CreateH264Picture() {
  70. D3D11PictureBuffer* picture = client_->GetPicture();
  71. if (!picture) {
  72. return nullptr;
  73. }
  74. return base::MakeRefCounted<D3D11H264Picture>(picture);
  75. }
  76. DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
  77. const H264SPS* sps,
  78. const H264PPS* pps,
  79. const H264DPB& dpb,
  80. const H264Picture::Vector& ref_pic_listp0,
  81. const H264Picture::Vector& ref_pic_listb0,
  82. const H264Picture::Vector& ref_pic_listb1,
  83. scoped_refptr<H264Picture> pic) {
  84. const bool is_encrypted = pic->decrypt_config();
  85. if (is_encrypted) {
  86. RecordFailure("Cannot find decrypt context for the frame.",
  87. D3D11Status::Codes::kCryptoConfigFailed);
  88. return DecoderStatus::kFail;
  89. }
  90. HRESULT hr;
  91. for (;;) {
  92. D3D11H264Picture* d3d11_pic = pic->AsD3D11H264Picture();
  93. if (!d3d11_pic)
  94. return DecoderStatus::kFail;
  95. ID3D11VideoDecoderOutputView* output_view = nullptr;
  96. auto result = d3d11_pic->picture->AcquireOutputView();
  97. if (result.has_value()) {
  98. output_view = std::move(result).value();
  99. } else {
  100. RecordFailure(std::move(result).error());
  101. return DecoderStatus::kFail;
  102. }
  103. hr = video_context_->DecoderBeginFrame(video_decoder_.Get(), output_view, 0,
  104. nullptr);
  105. if (hr == E_PENDING || hr == D3DERR_WASSTILLDRAWING) {
  106. // Hardware is busy. We should make the call again.
  107. // TODO(liberato): For now, just busy wait.
  108. ;
  109. } else if (!SUCCEEDED(hr)) {
  110. RecordFailure("DecoderBeginFrame failed",
  111. D3D11Status::Codes::kDecoderBeginFrameFailed, hr);
  112. return DecoderStatus::kFail;
  113. } else {
  114. break;
  115. }
  116. }
  117. sps_ = *sps;
  118. for (size_t i = 0; i < media::kRefFrameMaxCount; i++) {
  119. ref_frame_list_[i].bPicEntry = 0xFF;
  120. field_order_cnt_list_[i][0] = 0;
  121. field_order_cnt_list_[i][1] = 0;
  122. frame_num_list_[i] = 0;
  123. }
  124. used_for_reference_flags_ = 0;
  125. non_existing_frame_flags_ = 0;
  126. // TODO(liberato): this is similar to H264Accelerator. can they share code?
  127. int i = 0;
  128. for (auto it = dpb.begin(); it != dpb.end(); i++, it++) {
  129. // The DPB is supposed to have a maximum of 16 pictures in it, but there's
  130. // nothing actually stopping it from having more. If we run into this case,
  131. // something is clearly wrong, and we should just fail decoding rather than
  132. // try to sort out which pictures really shouldn't be included.
  133. if (i >= media::kRefFrameMaxCount)
  134. return DecoderStatus::kFail;
  135. D3D11H264Picture* our_ref_pic = it->get()->AsD3D11H264Picture();
  136. // How does a non-d3d11 picture get here you might ask? The decoder
  137. // inserts blank H264Picture objects that we can't use as part of filling
  138. // gaps in frame numbers. If we see one, it's not a reference picture
  139. // anyway, so skip it.
  140. if (!our_ref_pic || !our_ref_pic->ref)
  141. continue;
  142. ref_frame_list_[i].Index7Bits = our_ref_pic->picture_index_;
  143. ref_frame_list_[i].AssociatedFlag = our_ref_pic->long_term;
  144. field_order_cnt_list_[i][0] = our_ref_pic->top_field_order_cnt;
  145. field_order_cnt_list_[i][1] = our_ref_pic->bottom_field_order_cnt;
  146. frame_num_list_[i] = ref_frame_list_[i].AssociatedFlag
  147. ? our_ref_pic->long_term_pic_num
  148. : our_ref_pic->frame_num;
  149. unsigned ref = 3;
  150. used_for_reference_flags_ |= ref << (2 * i);
  151. non_existing_frame_flags_ |= (our_ref_pic->nonexisting) << i;
  152. }
  153. slice_info_.clear();
  154. return RetrieveBitstreamBuffer() ? DecoderStatus::kOk : DecoderStatus::kFail;
  155. }
  156. bool D3D11H264Accelerator::RetrieveBitstreamBuffer() {
  157. DCHECK(!bitstream_buffer_bytes_);
  158. DCHECK(!bitstream_buffer_size_);
  159. current_offset_ = 0;
  160. void* buffer;
  161. UINT buffer_size;
  162. HRESULT hr = video_context_->GetDecoderBuffer(
  163. video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM, &buffer_size,
  164. &buffer);
  165. if (!SUCCEEDED(hr)) {
  166. RecordFailure("GetDecoderBuffer (Bitstream) failed",
  167. D3D11Status::Codes::kGetBitstreamBufferFailed, hr);
  168. return false;
  169. }
  170. bitstream_buffer_bytes_ = (uint8_t*)buffer;
  171. bitstream_buffer_size_ = buffer_size;
  172. return true;
  173. }
  174. void D3D11H264Accelerator::FillPicParamsWithConstants(
  175. DXVA_PicParams_H264* pic) {
  176. // From "DirectX Video Acceleration Specification for H.264/AVC Decoding":
  177. // "The value shall be 1 unless the restricted-mode profile in use
  178. // explicitly supports the value 0."
  179. pic->MbsConsecutiveFlag = 1;
  180. // The latest DXVA decoding guide says to set this to 3 if the software
  181. // decoder (this class) is following the guide.
  182. pic->Reserved16Bits = 3;
  183. // |ContinuationFlag| indicates that we've filled in the remaining fields.
  184. pic->ContinuationFlag = 1;
  185. // Must be zero unless bit 13 of ConfigDecoderSpecific is set.
  186. pic->Reserved8BitsA = 0;
  187. // Unused, should always be zero.
  188. pic->Reserved8BitsB = 0;
  189. // Should always be 1.
  190. pic->StatusReportFeedbackNumber = 1;
  191. // UNUSED: slice_group_map_type (undocumented)
  192. // UNUSED: slice_group_change_rate (undocumented)
  193. }
  194. #define ARG_SEL(_1, _2, NAME, ...) NAME
  195. #define SPS_TO_PP1(a) pic_param->a = sps->a;
  196. #define SPS_TO_PP2(a, b) pic_param->a = sps->b;
  197. #define SPS_TO_PP(...) ARG_SEL(__VA_ARGS__, SPS_TO_PP2, SPS_TO_PP1)(__VA_ARGS__)
  198. void D3D11H264Accelerator::PicParamsFromSPS(DXVA_PicParams_H264* pic_param,
  199. const H264SPS* sps,
  200. bool field_pic) {
  201. // The H.264 specification now calls this |max_num_ref_frames|, while
  202. // DXVA_PicParams_H264 continues to use the old name, |num_ref_frames|.
  203. // See DirectX Video Acceleration for H.264/MPEG-4 AVC Decoding (4.2).
  204. SPS_TO_PP(num_ref_frames, max_num_ref_frames);
  205. SPS_TO_PP(wFrameWidthInMbsMinus1, pic_width_in_mbs_minus1);
  206. SPS_TO_PP(wFrameHeightInMbsMinus1, pic_height_in_map_units_minus1);
  207. SPS_TO_PP(residual_colour_transform_flag, separate_colour_plane_flag);
  208. SPS_TO_PP(chroma_format_idc);
  209. SPS_TO_PP(frame_mbs_only_flag);
  210. SPS_TO_PP(bit_depth_luma_minus8);
  211. SPS_TO_PP(bit_depth_chroma_minus8);
  212. SPS_TO_PP(log2_max_frame_num_minus4);
  213. SPS_TO_PP(pic_order_cnt_type);
  214. SPS_TO_PP(log2_max_pic_order_cnt_lsb_minus4);
  215. SPS_TO_PP(delta_pic_order_always_zero_flag);
  216. SPS_TO_PP(direct_8x8_inference_flag);
  217. pic_param->MbaffFrameFlag = sps->mb_adaptive_frame_field_flag && field_pic;
  218. pic_param->field_pic_flag = field_pic;
  219. pic_param->MinLumaBipredSize8x8Flag = sps->level_idc >= 31;
  220. }
  221. #undef SPS_TO_PP
  222. #undef SPS_TO_PP2
  223. #undef SPS_TO_PP1
  224. #define PPS_TO_PP1(a) pic_param->a = pps->a;
  225. #define PPS_TO_PP2(a, b) pic_param->a = pps->b;
  226. #define PPS_TO_PP(...) ARG_SEL(__VA_ARGS__, PPS_TO_PP2, PPS_TO_PP1)(__VA_ARGS__)
  227. bool D3D11H264Accelerator::PicParamsFromPPS(DXVA_PicParams_H264* pic_param,
  228. const H264PPS* pps) {
  229. PPS_TO_PP(constrained_intra_pred_flag);
  230. PPS_TO_PP(weighted_pred_flag);
  231. PPS_TO_PP(weighted_bipred_idc);
  232. PPS_TO_PP(transform_8x8_mode_flag);
  233. PPS_TO_PP(pic_init_qs_minus26);
  234. PPS_TO_PP(chroma_qp_index_offset);
  235. PPS_TO_PP(second_chroma_qp_index_offset);
  236. PPS_TO_PP(pic_init_qp_minus26);
  237. PPS_TO_PP(num_ref_idx_l0_active_minus1, num_ref_idx_l0_default_active_minus1);
  238. PPS_TO_PP(num_ref_idx_l1_active_minus1, num_ref_idx_l1_default_active_minus1);
  239. PPS_TO_PP(entropy_coding_mode_flag);
  240. PPS_TO_PP(pic_order_present_flag,
  241. bottom_field_pic_order_in_frame_present_flag);
  242. PPS_TO_PP(deblocking_filter_control_present_flag);
  243. PPS_TO_PP(redundant_pic_cnt_present_flag);
  244. PPS_TO_PP(num_slice_groups_minus1);
  245. if (pic_param->num_slice_groups_minus1) {
  246. // TODO(liberato): UMA?
  247. // TODO(liberato): media log?
  248. LOG(ERROR) << "num_slice_groups_minus1 == "
  249. << pic_param->num_slice_groups_minus1;
  250. return false;
  251. }
  252. return true;
  253. }
  254. #undef PPS_TO_PP
  255. #undef PPS_TO_PP2
  256. #undef PPS_TO_PP1
  257. #undef ARG_SEL
  258. void D3D11H264Accelerator::PicParamsFromSliceHeader(
  259. DXVA_PicParams_H264* pic_param,
  260. const H264SliceHeader* slice_hdr) {
  261. pic_param->sp_for_switch_flag = slice_hdr->sp_for_switch_flag;
  262. pic_param->field_pic_flag = slice_hdr->field_pic_flag;
  263. pic_param->CurrPic.AssociatedFlag = slice_hdr->bottom_field_flag;
  264. pic_param->IntraPicFlag = slice_hdr->IsISlice();
  265. }
  266. void D3D11H264Accelerator::PicParamsFromPic(DXVA_PicParams_H264* pic_param,
  267. D3D11H264Picture* pic) {
  268. pic_param->CurrPic.Index7Bits = pic->picture_index_;
  269. pic_param->RefPicFlag = pic->ref;
  270. pic_param->frame_num = pic->frame_num;
  271. if (pic_param->field_pic_flag && pic_param->CurrPic.AssociatedFlag) {
  272. pic_param->CurrFieldOrderCnt[1] = pic->bottom_field_order_cnt;
  273. pic_param->CurrFieldOrderCnt[0] = 0;
  274. } else if (pic_param->field_pic_flag && !pic_param->CurrPic.AssociatedFlag) {
  275. pic_param->CurrFieldOrderCnt[0] = pic->top_field_order_cnt;
  276. pic_param->CurrFieldOrderCnt[1] = 0;
  277. } else {
  278. pic_param->CurrFieldOrderCnt[0] = pic->top_field_order_cnt;
  279. pic_param->CurrFieldOrderCnt[1] = pic->bottom_field_order_cnt;
  280. }
  281. }
  282. DecoderStatus D3D11H264Accelerator::SubmitSlice(
  283. const H264PPS* pps,
  284. const H264SliceHeader* slice_hdr,
  285. const H264Picture::Vector& ref_pic_list0,
  286. const H264Picture::Vector& ref_pic_list1,
  287. scoped_refptr<H264Picture> pic,
  288. const uint8_t* data,
  289. size_t size,
  290. const std::vector<SubsampleEntry>& subsamples) {
  291. const bool is_encrypted = pic->decrypt_config();
  292. DXVA_PicParams_H264 pic_param = {};
  293. FillPicParamsWithConstants(&pic_param);
  294. PicParamsFromSPS(&pic_param, &sps_, slice_hdr->field_pic_flag);
  295. if (!PicParamsFromPPS(&pic_param, pps))
  296. return DecoderStatus::kFail;
  297. PicParamsFromSliceHeader(&pic_param, slice_hdr);
  298. D3D11H264Picture* d3d11_pic = pic->AsD3D11H264Picture();
  299. if (!d3d11_pic)
  300. return DecoderStatus::kFail;
  301. PicParamsFromPic(&pic_param, d3d11_pic);
  302. memcpy(pic_param.RefFrameList, ref_frame_list_,
  303. sizeof pic_param.RefFrameList);
  304. memcpy(pic_param.FieldOrderCntList, field_order_cnt_list_,
  305. sizeof pic_param.FieldOrderCntList);
  306. memcpy(pic_param.FrameNumList, frame_num_list_,
  307. sizeof pic_param.FrameNumList);
  308. pic_param.UsedForReferenceFlags = used_for_reference_flags_;
  309. pic_param.NonExistingFrameFlags = non_existing_frame_flags_;
  310. UINT buffer_size;
  311. void* buffer;
  312. HRESULT hr = video_context_->GetDecoderBuffer(
  313. video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS,
  314. &buffer_size, &buffer);
  315. if (!SUCCEEDED(hr)) {
  316. RecordFailure("GetDecoderBuffer (PictureParams) failed",
  317. D3D11Status::Codes::kGetPicParamBufferFailed, hr);
  318. return DecoderStatus::kFail;
  319. }
  320. memcpy(buffer, &pic_param, sizeof(pic_param));
  321. hr = video_context_->ReleaseDecoderBuffer(
  322. video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS);
  323. if (!SUCCEEDED(hr)) {
  324. RecordFailure("ReleaseDecoderBuffer (PictureParams) failed",
  325. D3D11Status::Codes::kReleasePicParamBufferFailed, hr);
  326. return DecoderStatus::kFail;
  327. }
  328. DXVA_Qmatrix_H264 iq_matrix_buf = {};
  329. if (pps->pic_scaling_matrix_present_flag) {
  330. for (int i = 0; i < 6; ++i) {
  331. for (int j = 0; j < 16; ++j)
  332. iq_matrix_buf.bScalingLists4x4[i][j] = pps->scaling_list4x4[i][j];
  333. }
  334. for (int i = 0; i < 2; ++i) {
  335. for (int j = 0; j < 64; ++j)
  336. iq_matrix_buf.bScalingLists8x8[i][j] = pps->scaling_list8x8[i][j];
  337. }
  338. } else {
  339. for (int i = 0; i < 6; ++i) {
  340. for (int j = 0; j < 16; ++j)
  341. iq_matrix_buf.bScalingLists4x4[i][j] = sps_.scaling_list4x4[i][j];
  342. }
  343. for (int i = 0; i < 2; ++i) {
  344. for (int j = 0; j < 64; ++j)
  345. iq_matrix_buf.bScalingLists8x8[i][j] = sps_.scaling_list8x8[i][j];
  346. }
  347. }
  348. hr = video_context_->GetDecoderBuffer(
  349. video_decoder_.Get(),
  350. D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX, &buffer_size,
  351. &buffer);
  352. if (!SUCCEEDED(hr)) {
  353. RecordFailure("GetDecoderBuffer (QuantMatrix) failed",
  354. D3D11Status::Codes::kGetQuantBufferFailed, hr);
  355. return DecoderStatus::kFail;
  356. }
  357. memcpy(buffer, &iq_matrix_buf, sizeof(iq_matrix_buf));
  358. hr = video_context_->ReleaseDecoderBuffer(
  359. video_decoder_.Get(),
  360. D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX);
  361. if (!SUCCEEDED(hr)) {
  362. RecordFailure("ReleaseDecoderBuffer (QuantMatrix) failed",
  363. D3D11Status::Codes::kReleaseQuantBufferFailed, hr);
  364. return DecoderStatus::kFail;
  365. }
  366. // Ideally all slices in a frame are put in the same bitstream buffer.
  367. // However the bitstream buffer may not fit all the data, so split on the
  368. // necessary boundaries.
  369. size_t out_bitstream_size = size + 3;
  370. size_t remaining_bitstream = out_bitstream_size;
  371. size_t start_location = 0;
  372. if (is_encrypted) {
  373. // For now, the entire frame has to fit into the bitstream buffer. This way
  374. // the subsample ClearSize adjustment below should work.
  375. if (bitstream_buffer_size_ < remaining_bitstream) {
  376. RecordFailure("Input slice NALU (" + std::to_string(remaining_bitstream) +
  377. ") too big to fit in the bistream buffer (" +
  378. base::NumberToString(bitstream_buffer_size_) + ").",
  379. D3D11Status::Codes::kBitstreamBufferSliceTooBig);
  380. return DecoderStatus::kFail;
  381. }
  382. AppendSubsamples(subsamples, &subsamples_);
  383. if (!subsamples.empty()) {
  384. // 3 added to clear bytes because a start code is prepended to the slice
  385. // NALU.
  386. // TODO(rkuroiwa): This should be done right after the start code is
  387. // written to the buffer, but currently the start code is written in the
  388. // loop (which is not the right place, there's only one slice NALU passed
  389. // into this function) and it's not easy to identify where the subsample
  390. // starts in the buffer.
  391. subsamples_[subsamples_.size() - subsamples.size()].ClearSize += 3;
  392. }
  393. }
  394. while (remaining_bitstream > 0) {
  395. if (bitstream_buffer_size_ < remaining_bitstream &&
  396. slice_info_.size() > 0) {
  397. if (!SubmitSliceData())
  398. return DecoderStatus::kFail;
  399. if (!RetrieveBitstreamBuffer())
  400. return DecoderStatus::kFail;
  401. }
  402. size_t bytes_to_copy = remaining_bitstream;
  403. bool contains_end = true;
  404. if (bytes_to_copy > bitstream_buffer_size_) {
  405. bytes_to_copy = bitstream_buffer_size_;
  406. contains_end = false;
  407. }
  408. size_t real_bytes_to_copy = bytes_to_copy;
  409. // TODO(jbauman): fix hack
  410. uint8_t* out_start = bitstream_buffer_bytes_;
  411. if (bytes_to_copy >= 3 && start_location == 0) {
  412. *(out_start++) = 0;
  413. *(out_start++) = 0;
  414. *(out_start++) = 1;
  415. real_bytes_to_copy -= 3;
  416. }
  417. memcpy(out_start, data + start_location, real_bytes_to_copy);
  418. DXVA_Slice_H264_Short slice_info = {};
  419. slice_info.BSNALunitDataLocation = (UINT)current_offset_;
  420. slice_info.SliceBytesInBuffer = (UINT)bytes_to_copy;
  421. if (contains_end && start_location == 0)
  422. slice_info.wBadSliceChopping = 0;
  423. else if (!contains_end && start_location == 0)
  424. slice_info.wBadSliceChopping = 1;
  425. else if (contains_end && start_location != 0)
  426. slice_info.wBadSliceChopping = 2;
  427. else
  428. slice_info.wBadSliceChopping = 3;
  429. slice_info_.push_back(slice_info);
  430. bitstream_buffer_size_ -= bytes_to_copy;
  431. current_offset_ += bytes_to_copy;
  432. start_location += bytes_to_copy;
  433. remaining_bitstream -= bytes_to_copy;
  434. bitstream_buffer_bytes_ += bytes_to_copy;
  435. }
  436. return DecoderStatus::kOk;
  437. }
  438. bool D3D11H264Accelerator::SubmitSliceData() {
  439. CHECK(slice_info_.size() > 0);
  440. UINT buffer_size;
  441. void* buffer;
  442. // TODO(liberato): Should we release the other buffers on failure?
  443. HRESULT hr = video_context_->GetDecoderBuffer(
  444. video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL,
  445. &buffer_size, &buffer);
  446. if (!SUCCEEDED(hr)) {
  447. RecordFailure("GetDecoderBuffer (SliceControl) failed",
  448. D3D11Status::Codes::kGetSliceControlBufferFailed, hr);
  449. return false;
  450. }
  451. CHECK_LE(sizeof(slice_info_[0]) * slice_info_.size(), buffer_size);
  452. memcpy(buffer, &slice_info_[0], sizeof(slice_info_[0]) * slice_info_.size());
  453. hr = video_context_->ReleaseDecoderBuffer(
  454. video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL);
  455. if (!SUCCEEDED(hr)) {
  456. RecordFailure("ReleaseDecoderBuffer (SliceControl) failed",
  457. D3D11Status::Codes::kReleaseSliceControlBufferFailed, hr);
  458. return false;
  459. }
  460. hr = video_context_->ReleaseDecoderBuffer(
  461. video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM);
  462. if (!SUCCEEDED(hr)) {
  463. RecordFailure("ReleaseDecoderBuffer (BitStream) failed",
  464. D3D11Status::Codes::kReleaseBitstreamBufferFailed, hr);
  465. return false;
  466. }
  467. VideoContextWrapper::VideoBufferWrapper buffers[4] = {};
  468. buffers[0].BufferType = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
  469. buffers[0].DataOffset = 0;
  470. buffers[0].DataSize = sizeof(DXVA_PicParams_H264);
  471. buffers[1].BufferType =
  472. D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX;
  473. buffers[1].DataOffset = 0;
  474. buffers[1].DataSize = sizeof(DXVA_Qmatrix_H264);
  475. buffers[2].BufferType = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
  476. buffers[2].DataOffset = 0;
  477. buffers[2].DataSize = sizeof(slice_info_[0]) * slice_info_.size();
  478. buffers[3].BufferType = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
  479. buffers[3].DataOffset = 0;
  480. buffers[3].DataSize = current_offset_;
  481. if (!frame_iv_.empty()) {
  482. buffers[3].pIV = frame_iv_.data();
  483. buffers[3].IVSize = frame_iv_.size();
  484. // Subsmaples matter iff there is IV, for decryption.
  485. if (!subsamples_.empty()) {
  486. buffers[3].pSubSampleMappingBlock = subsamples_.data();
  487. buffers[3].SubSampleMappingCount = subsamples_.size();
  488. }
  489. }
  490. hr = video_context_->SubmitDecoderBuffers(video_decoder_.Get(),
  491. std::size(buffers), buffers);
  492. current_offset_ = 0;
  493. slice_info_.clear();
  494. bitstream_buffer_bytes_ = nullptr;
  495. bitstream_buffer_size_ = 0;
  496. frame_iv_.clear();
  497. subsamples_.clear();
  498. if (!SUCCEEDED(hr)) {
  499. RecordFailure("SubmitDecoderBuffers failed",
  500. D3D11Status::Codes::kSubmitDecoderBuffersFailed, hr);
  501. return false;
  502. }
  503. return true;
  504. }
  505. DecoderStatus D3D11H264Accelerator::SubmitDecode(
  506. scoped_refptr<H264Picture> pic) {
  507. if (!SubmitSliceData())
  508. return DecoderStatus::kFail;
  509. HRESULT hr = video_context_->DecoderEndFrame(video_decoder_.Get());
  510. if (!SUCCEEDED(hr)) {
  511. RecordFailure("DecoderEndFrame failed",
  512. D3D11Status::Codes::kDecoderEndFrameFailed, hr);
  513. return DecoderStatus::kFail;
  514. }
  515. return DecoderStatus::kOk;
  516. }
  517. void D3D11H264Accelerator::Reset() {
  518. if (!bitstream_buffer_bytes_)
  519. return;
  520. HRESULT hr = video_context_->ReleaseDecoderBuffer(
  521. video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM);
  522. bitstream_buffer_bytes_ = nullptr;
  523. bitstream_buffer_size_ = 0;
  524. current_offset_ = 0;
  525. CHECK(SUCCEEDED(hr));
  526. }
  527. bool D3D11H264Accelerator::OutputPicture(scoped_refptr<H264Picture> pic) {
  528. D3D11H264Picture* our_pic = pic->AsD3D11H264Picture();
  529. return our_pic && client_->OutputResult(our_pic, our_pic->picture);
  530. }
  531. void D3D11H264Accelerator::RecordFailure(const std::string& reason,
  532. D3D11Status::Codes code,
  533. HRESULT hr) const {
  534. std::string hr_string;
  535. if (!SUCCEEDED(hr))
  536. hr_string = ": " + logging::SystemErrorCodeToString(hr);
  537. DLOG(ERROR) << reason << hr_string;
  538. MEDIA_LOG(ERROR, media_log_) << hr_string << ": " << reason;
  539. }
  540. void D3D11H264Accelerator::RecordFailure(D3D11Status error) const {
  541. RecordFailure(error.message(), error.code());
  542. }
  543. void D3D11H264Accelerator::SetVideoDecoder(ComD3D11VideoDecoder video_decoder) {
  544. video_decoder_ = std::move(video_decoder);
  545. }
  546. } // namespace media