vd_video_decode_accelerator.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  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/chromeos/vd_video_decode_accelerator.h"
  5. #include <memory>
  6. #include <vector>
  7. #include "base/bind.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/location.h"
  10. #include "base/memory/unsafe_shared_memory_region.h"
  11. #include "gpu/ipc/common/gpu_memory_buffer_support.h"
  12. #include "media/base/format_utils.h"
  13. #include "media/base/media_util.h"
  14. #include "media/base/video_color_space.h"
  15. #include "media/base/video_decoder_config.h"
  16. #include "media/base/video_frame.h"
  17. #include "media/base/video_frame_metadata.h"
  18. #include "media/base/video_transformation.h"
  19. #include "media/base/video_types.h"
  20. #include "media/base/waiting.h"
  21. #include "media/gpu/buffer_validation.h"
  22. #include "media/gpu/chromeos/gpu_buffer_layout.h"
  23. #include "media/gpu/macros.h"
  24. #include "media/media_buildflags.h"
  25. #include "ui/gfx/buffer_format_util.h"
  26. #include "ui/gfx/gpu_memory_buffer.h"
  27. #include "ui/gl/gl_bindings.h"
  28. #if BUILDFLAG(IS_CHROMEOS_ASH)
  29. // gn check does not account for BUILDFLAG(), so including these headers will
  30. // make gn check fail for builds other than ash-chrome. See gn help nogncheck
  31. // for more information.
  32. #include "chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.h" // nogncheck
  33. #include "media/gpu/chromeos/secure_buffer.pb.h" // nogncheck
  34. #include "third_party/cros_system_api/constants/cdm_oemcrypto.h" // nogncheck
  35. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  36. namespace media {
  37. namespace {
  38. // VideoDecoder copies the timestamp from DecodeBuffer to its corresponding
  39. // VideoFrame. However, VideoDecodeAccelerator uses bitstream ID to find the
  40. // corresponding output picture. Therefore, we store bitstream ID at the
  41. // timestamp field. These two functions are used for converting between
  42. // bitstream ID and fake timestamp.
  43. base::TimeDelta BitstreamIdToFakeTimestamp(int32_t bitstream_id) {
  44. return base::Milliseconds(bitstream_id);
  45. }
  46. int32_t FakeTimestampToBitstreamId(base::TimeDelta timestamp) {
  47. return static_cast<int32_t>(timestamp.InMilliseconds());
  48. }
  49. std::vector<ColorPlaneLayout> ExtractColorPlaneLayout(
  50. const gfx::GpuMemoryBufferHandle& gmb_handle) {
  51. std::vector<ColorPlaneLayout> planes;
  52. for (const auto& plane : gmb_handle.native_pixmap_handle.planes)
  53. planes.emplace_back(plane.stride, plane.offset, plane.size);
  54. return planes;
  55. }
  56. // TODO(akahuang): Move this function to a utility file.
  57. template <class T>
  58. std::string VectorToString(const std::vector<T>& vec) {
  59. std::ostringstream result;
  60. std::string delim;
  61. result << "[";
  62. for (auto& v : vec) {
  63. result << delim << v;
  64. if (delim.size() == 0)
  65. delim = ", ";
  66. }
  67. result << "]";
  68. return result.str();
  69. }
  70. #if BUILDFLAG(IS_CHROMEOS_ASH)
  71. scoped_refptr<DecoderBuffer> DecryptBitstreamBuffer(
  72. BitstreamBuffer bitstream_buffer) {
  73. // Check to see if we have our secure buffer tag and then extract the
  74. // decrypt parameters.
  75. auto mem_region = bitstream_buffer.DuplicateRegion();
  76. if (!mem_region.IsValid()) {
  77. DVLOG(2) << "Invalid shared memory region";
  78. return nullptr;
  79. }
  80. const size_t available_size =
  81. mem_region.GetSize() -
  82. base::checked_cast<size_t>(bitstream_buffer.offset());
  83. auto mapping = mem_region.Map();
  84. if (!mapping.IsValid()) {
  85. DVLOG(2) << "Failed mapping shared memory";
  86. return nullptr;
  87. }
  88. // Checks if this buffer contains the details needed for HW protected video
  89. // decoding.
  90. // The header is 1KB in size (cdm_oemcrypto::kSecureBufferHeaderSize).
  91. // It consists of 3 components.
  92. // 1. Marker tag - cdm_oemcrypto::kSecureBufferTag
  93. // 2. unsigned 32-bit size of #3
  94. // 3. Serialized ArcSecureBufferForChrome proto
  95. uint8_t* data = mapping.GetMemoryAs<uint8_t>();
  96. if (!data) {
  97. DVLOG(2) << "Failed accessing shared memory";
  98. return nullptr;
  99. }
  100. // Apply the offset here so we don't need to worry about page alignment in the
  101. // mapping.
  102. data += bitstream_buffer.offset();
  103. if (available_size <= cdm_oemcrypto::kSecureBufferHeaderSize ||
  104. memcmp(data, cdm_oemcrypto::kSecureBufferTag,
  105. cdm_oemcrypto::kSecureBufferTagLen)) {
  106. // This occurs in Intel implementations when we are in a clear portion.
  107. return bitstream_buffer.ToDecoderBuffer();
  108. }
  109. VLOG(2) << "Detected secure buffer format in VDVDA";
  110. // Read the protobuf size.
  111. uint32_t proto_size = 0;
  112. memcpy(&proto_size, data + cdm_oemcrypto::kSecureBufferTagLen,
  113. sizeof(uint32_t));
  114. if (proto_size > cdm_oemcrypto::kSecureBufferHeaderSize -
  115. cdm_oemcrypto::kSecureBufferProtoOffset) {
  116. DVLOG(2) << "Proto size goes beyond header size";
  117. return nullptr;
  118. }
  119. // Read the serialized proto.
  120. std::string serialized_proto(
  121. data + cdm_oemcrypto::kSecureBufferProtoOffset,
  122. data + cdm_oemcrypto::kSecureBufferProtoOffset + proto_size);
  123. chromeos::cdm::ArcSecureBufferForChrome buffer_proto;
  124. if (!buffer_proto.ParseFromString(serialized_proto)) {
  125. DVLOG(2) << "Failed deserializing secure buffer proto";
  126. return nullptr;
  127. }
  128. // Now extract the DecryptConfig info from the protobuf.
  129. std::vector<media::SubsampleEntry> subsamples;
  130. size_t buffer_size = 0;
  131. for (const auto& subsample : buffer_proto.subsample()) {
  132. buffer_size += subsample.clear_bytes() + subsample.cypher_bytes();
  133. subsamples.emplace_back(subsample.clear_bytes(), subsample.cypher_bytes());
  134. }
  135. absl::optional<EncryptionPattern> pattern = absl::nullopt;
  136. if (buffer_proto.has_pattern()) {
  137. pattern.emplace(buffer_proto.pattern().cypher_bytes(),
  138. buffer_proto.pattern().clear_bytes());
  139. }
  140. // Now create the DecryptConfig and set it in the decoder buffer.
  141. scoped_refptr<DecoderBuffer> buffer = bitstream_buffer.ToDecoderBuffer(
  142. cdm_oemcrypto::kSecureBufferHeaderSize, buffer_size);
  143. if (!buffer) {
  144. DVLOG(2) << "Secure buffer data goes beyond shared memory size";
  145. return nullptr;
  146. }
  147. if (buffer_proto.encryption_scheme() !=
  148. chromeos::cdm::ArcSecureBufferForChrome::NONE) {
  149. buffer->set_decrypt_config(std::make_unique<DecryptConfig>(
  150. buffer_proto.encryption_scheme() ==
  151. chromeos::cdm::ArcSecureBufferForChrome::CBCS
  152. ? EncryptionScheme::kCbcs
  153. : EncryptionScheme::kCenc,
  154. buffer_proto.key_id(), buffer_proto.iv(), std::move(subsamples),
  155. std::move(pattern)));
  156. }
  157. return buffer;
  158. }
  159. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  160. } // namespace
  161. // static
  162. std::unique_ptr<VideoDecodeAccelerator> VdVideoDecodeAccelerator::Create(
  163. CreateVideoDecoderCb create_vd_cb,
  164. Client* client,
  165. const Config& config,
  166. scoped_refptr<base::SequencedTaskRunner> task_runner) {
  167. std::unique_ptr<VideoDecodeAccelerator> vda(new VdVideoDecodeAccelerator(
  168. std::move(create_vd_cb), std::move(task_runner)));
  169. if (!vda->Initialize(config, client))
  170. return nullptr;
  171. return vda;
  172. }
  173. VdVideoDecodeAccelerator::VdVideoDecodeAccelerator(
  174. CreateVideoDecoderCb create_vd_cb,
  175. scoped_refptr<base::SequencedTaskRunner> client_task_runner)
  176. : create_vd_cb_(std::move(create_vd_cb)),
  177. client_task_runner_(std::move(client_task_runner)) {
  178. VLOGF(2);
  179. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  180. weak_this_ = weak_this_factory_.GetWeakPtr();
  181. }
  182. void VdVideoDecodeAccelerator::Destroy() {
  183. VLOGF(2);
  184. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  185. weak_this_factory_.InvalidateWeakPtrs();
  186. // Because VdaVideoFramePool is blocked for this callback, we must call the
  187. // callback before destroying.
  188. if (notify_layout_changed_cb_)
  189. std::move(notify_layout_changed_cb_)
  190. .Run(CroStatus::Codes::kFailedToGetFrameLayout);
  191. client_ = nullptr;
  192. vd_.reset();
  193. delete this;
  194. }
  195. VdVideoDecodeAccelerator::~VdVideoDecodeAccelerator() {
  196. DVLOGF(3);
  197. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  198. }
  199. bool VdVideoDecodeAccelerator::Initialize(const Config& config,
  200. Client* client) {
  201. VLOGF(2) << "config: " << config.AsHumanReadableString();
  202. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  203. #if !BUILDFLAG(USE_ARC_PROTECTED_MEDIA)
  204. if (config.is_encrypted()) {
  205. VLOGF(1) << "Encrypted streams are not supported";
  206. return false;
  207. }
  208. #endif // !BUILDFLAG(USE_ARC_PROTECTED_MEDIA)
  209. if (config.output_mode != Config::OutputMode::IMPORT) {
  210. VLOGF(1) << "Only IMPORT OutputMode is supported.";
  211. return false;
  212. }
  213. if (!config.is_deferred_initialization_allowed) {
  214. VLOGF(1) << "Only is_deferred_initialization_allowed is supported.";
  215. return false;
  216. }
  217. // In case we are re-initializing for encrypted content.
  218. if (!vd_) {
  219. std::unique_ptr<VdaVideoFramePool> frame_pool =
  220. std::make_unique<VdaVideoFramePool>(weak_this_, client_task_runner_);
  221. vd_ = create_vd_cb_.Run(client_task_runner_, std::move(frame_pool),
  222. std::make_unique<VideoFrameConverter>(),
  223. std::make_unique<NullMediaLog>(),
  224. /*oop_video_decoder=*/{});
  225. if (!vd_)
  226. return false;
  227. client_ = client;
  228. }
  229. media::CdmContext* cdm_context = nullptr;
  230. #if BUILDFLAG(IS_CHROMEOS_ASH)
  231. is_encrypted_ = config.is_encrypted();
  232. if (is_encrypted_)
  233. cdm_context = chromeos::ChromeOsCdmFactory::GetArcCdmContext();
  234. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  235. VideoDecoderConfig vd_config(
  236. VideoCodecProfileToVideoCodec(config.profile), config.profile,
  237. VideoDecoderConfig::AlphaMode::kIsOpaque, config.container_color_space,
  238. VideoTransformation(), config.initial_expected_coded_size,
  239. gfx::Rect(config.initial_expected_coded_size),
  240. config.initial_expected_coded_size, std::vector<uint8_t>(),
  241. config.encryption_scheme);
  242. auto init_cb =
  243. base::BindOnce(&VdVideoDecodeAccelerator::OnInitializeDone, weak_this_);
  244. auto output_cb =
  245. base::BindRepeating(&VdVideoDecodeAccelerator::OnFrameReady, weak_this_);
  246. vd_->Initialize(std::move(vd_config), false /* low_delay */, cdm_context,
  247. std::move(init_cb), std::move(output_cb), base::DoNothing());
  248. return true;
  249. }
  250. void VdVideoDecodeAccelerator::OnInitializeDone(DecoderStatus status) {
  251. DVLOGF(3) << "success: " << status.is_ok();
  252. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  253. DCHECK(client_);
  254. client_->NotifyInitializationComplete(status);
  255. }
  256. void VdVideoDecodeAccelerator::Decode(BitstreamBuffer bitstream_buffer) {
  257. const int32_t bitstream_id = bitstream_buffer.id();
  258. #if BUILDFLAG(IS_CHROMEOS_ASH)
  259. if (is_encrypted_) {
  260. scoped_refptr<DecoderBuffer> buffer =
  261. DecryptBitstreamBuffer(std::move(bitstream_buffer));
  262. // This happens in the error case.
  263. if (!buffer) {
  264. OnError(FROM_HERE, PLATFORM_FAILURE);
  265. return;
  266. }
  267. Decode(std::move(buffer), bitstream_id);
  268. return;
  269. }
  270. #endif // BUILFLAG(IS_CHROMEOS_ASH)
  271. Decode(bitstream_buffer.ToDecoderBuffer(), bitstream_id);
  272. }
  273. void VdVideoDecodeAccelerator::Decode(scoped_refptr<DecoderBuffer> buffer,
  274. int32_t bitstream_id) {
  275. DVLOGF(4) << "bitstream_id:" << bitstream_id;
  276. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  277. DCHECK(vd_);
  278. // Set timestamp field as bitstream buffer id, because we can only use
  279. // timestamp field to find the corresponding output frames. Also, VDA doesn't
  280. // care about timestamp.
  281. buffer->set_timestamp(BitstreamIdToFakeTimestamp(bitstream_id));
  282. vd_->Decode(std::move(buffer),
  283. base::BindOnce(&VdVideoDecodeAccelerator::OnDecodeDone,
  284. weak_this_, bitstream_id));
  285. }
  286. void VdVideoDecodeAccelerator::OnDecodeDone(int32_t bitstream_buffer_id,
  287. DecoderStatus status) {
  288. DVLOGF(4) << "status: " << status.group() << ":"
  289. << static_cast<int>(status.code());
  290. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  291. DCHECK(client_);
  292. if (!status.is_ok() && status.code() != DecoderStatus::Codes::kAborted) {
  293. OnError(FROM_HERE, PLATFORM_FAILURE);
  294. return;
  295. }
  296. client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
  297. }
  298. void VdVideoDecodeAccelerator::OnFrameReady(scoped_refptr<VideoFrame> frame) {
  299. DVLOGF(4);
  300. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  301. DCHECK(frame);
  302. DCHECK(client_);
  303. absl::optional<Picture> picture = GetPicture(*frame);
  304. if (!picture) {
  305. VLOGF(1) << "Failed to get picture.";
  306. OnError(FROM_HERE, PLATFORM_FAILURE);
  307. return;
  308. }
  309. // Record that the picture is sent to the client.
  310. auto it = picture_at_client_.find(picture->picture_buffer_id());
  311. if (it == picture_at_client_.end()) {
  312. // We haven't sent the buffer to the client. Set |num_sent| = 1;
  313. picture_at_client_.emplace(picture->picture_buffer_id(),
  314. std::make_pair(std::move(frame), 1));
  315. } else {
  316. // We already sent the buffer to the client (only happen when using VP9
  317. // show_existing_frame feature). Increase |num_sent|;
  318. ++(it->second.second);
  319. }
  320. client_->PictureReady(*picture);
  321. }
  322. void VdVideoDecodeAccelerator::Flush() {
  323. DVLOGF(3);
  324. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  325. DCHECK(vd_);
  326. vd_->Decode(
  327. DecoderBuffer::CreateEOSBuffer(),
  328. base::BindOnce(&VdVideoDecodeAccelerator::OnFlushDone, weak_this_));
  329. }
  330. void VdVideoDecodeAccelerator::OnFlushDone(DecoderStatus status) {
  331. DVLOGF(3) << "status: " << static_cast<int>(status.code());
  332. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  333. DCHECK(client_);
  334. switch (status.code()) {
  335. case DecoderStatus::Codes::kOk:
  336. client_->NotifyFlushDone();
  337. break;
  338. case DecoderStatus::Codes::kAborted:
  339. // Do nothing.
  340. break;
  341. default:
  342. OnError(FROM_HERE, PLATFORM_FAILURE);
  343. break;
  344. }
  345. }
  346. void VdVideoDecodeAccelerator::Reset() {
  347. DVLOGF(3);
  348. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  349. DCHECK(vd_);
  350. if (is_resetting_) {
  351. VLOGF(1) << "The previous Reset() has not finished yet, aborted.";
  352. return;
  353. }
  354. is_resetting_ = true;
  355. if (notify_layout_changed_cb_) {
  356. std::move(notify_layout_changed_cb_).Run(CroStatus::Codes::kResetRequired);
  357. import_frame_cb_.Reset();
  358. }
  359. vd_->Reset(
  360. base::BindOnce(&VdVideoDecodeAccelerator::OnResetDone, weak_this_));
  361. }
  362. void VdVideoDecodeAccelerator::OnResetDone() {
  363. DVLOGF(3);
  364. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  365. DCHECK(client_);
  366. DCHECK(is_resetting_);
  367. is_resetting_ = false;
  368. client_->NotifyResetDone();
  369. }
  370. void VdVideoDecodeAccelerator::RequestFrames(
  371. const Fourcc& fourcc,
  372. const gfx::Size& coded_size,
  373. const gfx::Rect& visible_rect,
  374. size_t max_num_frames,
  375. NotifyLayoutChangedCb notify_layout_changed_cb,
  376. ImportFrameCb import_frame_cb) {
  377. VLOGF(2);
  378. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  379. DCHECK(client_);
  380. DCHECK(!notify_layout_changed_cb_);
  381. // Stop tracking currently-allocated pictures, otherwise the count will be
  382. // corrupted as we import new frames with the same IDs as the old ones.
  383. // The client should still have its own reference to the frame data, which
  384. // will keep it valid for as long as it needs it.
  385. picture_at_client_.clear();
  386. notify_layout_changed_cb_ = std::move(notify_layout_changed_cb);
  387. import_frame_cb_ = std::move(import_frame_cb);
  388. // We need to check if Reset() was received before RequestFrames() so that we
  389. // can unblock the frame pool in that case.
  390. if (is_resetting_) {
  391. std::move(notify_layout_changed_cb_).Run(CroStatus::Codes::kResetRequired);
  392. import_frame_cb_.Reset();
  393. return;
  394. }
  395. // After calling ProvidePictureBuffersWithVisibleRect(), the client might
  396. // still send buffers with old coded size. We temporarily store at
  397. // |pending_coded_size_|.
  398. pending_coded_size_ = coded_size;
  399. client_->ProvidePictureBuffersWithVisibleRect(
  400. max_num_frames, fourcc.ToVideoPixelFormat(), 1 /* textures_per_buffer */,
  401. coded_size, visible_rect, GL_TEXTURE_EXTERNAL_OES);
  402. }
  403. void VdVideoDecodeAccelerator::AssignPictureBuffers(
  404. const std::vector<PictureBuffer>& buffers) {
  405. VLOGF(2);
  406. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  407. // After AssignPictureBuffers() is called, the buffers sent from
  408. // ImportBufferForPicture() should be with new coded size. Now we can update
  409. // |coded_size_|.
  410. coded_size_ = pending_coded_size_;
  411. }
  412. void VdVideoDecodeAccelerator::ImportBufferForPicture(
  413. int32_t picture_buffer_id,
  414. VideoPixelFormat pixel_format,
  415. gfx::GpuMemoryBufferHandle gmb_handle) {
  416. DVLOGF(4) << "picture_buffer_id: " << picture_buffer_id;
  417. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  418. if (!import_frame_cb_)
  419. return;
  420. // The first imported picture after requesting buffers.
  421. // |notify_layout_changed_cb_| must be called in this clause because it blocks
  422. // VdaVideoFramePool.
  423. if (notify_layout_changed_cb_) {
  424. auto fourcc = Fourcc::FromVideoPixelFormat(pixel_format);
  425. if (!fourcc) {
  426. VLOGF(1) << "Failed to convert to Fourcc.";
  427. import_frame_cb_.Reset();
  428. std::move(notify_layout_changed_cb_)
  429. .Run(CroStatus::Codes::kFailedToChangeResolution);
  430. return;
  431. }
  432. CHECK(media::VerifyGpuMemoryBufferHandle(pixel_format, coded_size_,
  433. gmb_handle));
  434. const uint64_t modifier = gmb_handle.type == gfx::NATIVE_PIXMAP
  435. ? gmb_handle.native_pixmap_handle.modifier
  436. : gfx::NativePixmapHandle::kNoModifier;
  437. std::vector<ColorPlaneLayout> planes = ExtractColorPlaneLayout(gmb_handle);
  438. layout_ = VideoFrameLayout::CreateWithPlanes(
  439. pixel_format, coded_size_, planes,
  440. VideoFrameLayout::kBufferAddressAlignment, modifier);
  441. if (!layout_) {
  442. VLOGF(1) << "Failed to create VideoFrameLayout. format: "
  443. << VideoPixelFormatToString(pixel_format)
  444. << ", coded_size: " << coded_size_.ToString()
  445. << ", planes: " << VectorToString(planes)
  446. << ", modifier: " << std::hex << modifier;
  447. import_frame_cb_.Reset();
  448. std::move(notify_layout_changed_cb_)
  449. .Run(CroStatus::Codes::kFailedToChangeResolution);
  450. return;
  451. }
  452. auto gb_layout =
  453. GpuBufferLayout::Create(*fourcc, coded_size_, planes, modifier);
  454. if (!gb_layout) {
  455. VLOGF(1) << "Failed to create GpuBufferLayout. fourcc: "
  456. << fourcc->ToString()
  457. << ", coded_size: " << coded_size_.ToString()
  458. << ", planes: " << VectorToString(planes)
  459. << ", modifier: " << std::hex << modifier;
  460. layout_ = absl::nullopt;
  461. import_frame_cb_.Reset();
  462. std::move(notify_layout_changed_cb_)
  463. .Run(CroStatus::Codes::kFailedToChangeResolution);
  464. return;
  465. }
  466. std::move(notify_layout_changed_cb_).Run(*gb_layout);
  467. }
  468. if (!layout_)
  469. return;
  470. CHECK(media::VerifyGpuMemoryBufferHandle(pixel_format, layout_->coded_size(),
  471. gmb_handle));
  472. auto buffer_format = VideoPixelFormatToGfxBufferFormat(pixel_format);
  473. CHECK(buffer_format);
  474. // Usage is SCANOUT_VDA_WRITE because we are just wrapping the dmabuf in a
  475. // GpuMemoryBuffer. This buffer is just for decoding purposes, so having
  476. // the dmabufs mmapped is not necessary.
  477. std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
  478. gpu::GpuMemoryBufferSupport().CreateGpuMemoryBufferImplFromHandle(
  479. std::move(gmb_handle), layout_->coded_size(), *buffer_format,
  480. gfx::BufferUsage::SCANOUT_VDA_WRITE, base::NullCallback());
  481. if (!gpu_memory_buffer) {
  482. VLOGF(1) << "Failed to create GpuMemoryBuffer. format: "
  483. << gfx::BufferFormatToString(*buffer_format)
  484. << ", coded_size: " << layout_->coded_size().ToString();
  485. return;
  486. }
  487. const gpu::MailboxHolder mailbox_holder[VideoFrame::kMaxPlanes] = {};
  488. // VideoFrame::WrapVideoFrame() will check whether the updated visible_rect
  489. // is sub rect of the original visible_rect. Therefore we set visible_rect
  490. // as large as coded_size to guarantee this condition.
  491. scoped_refptr<VideoFrame> origin_frame =
  492. VideoFrame::WrapExternalGpuMemoryBuffer(
  493. gfx::Rect(layout_->coded_size()), layout_->coded_size(),
  494. std::move(gpu_memory_buffer), mailbox_holder, base::NullCallback(),
  495. base::TimeDelta());
  496. auto res = frame_id_to_picture_id_.emplace(
  497. origin_frame->GetGpuMemoryBuffer()->GetId(), picture_buffer_id);
  498. // The frame ID should not be inside the map before insertion.
  499. DCHECK(res.second);
  500. // |wrapped_frame| is used to keep |origin_frame| alive until everyone
  501. // released |wrapped_frame|. Then GpuMemoryBufferId will be available at
  502. // OnFrameReleased().
  503. scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame(
  504. origin_frame, origin_frame->format(), origin_frame->visible_rect(),
  505. origin_frame->natural_size());
  506. wrapped_frame->AddDestructionObserver(
  507. base::BindOnce(&VdVideoDecodeAccelerator::OnFrameReleasedThunk,
  508. weak_this_, client_task_runner_, std::move(origin_frame)));
  509. // This should not happen - picture_at_client_ should either be initially
  510. // empty, or be cleared as RequestFrames() is called. However for extra safety
  511. // let's make sure the slot for the picture buffer ID is free, otherwise we
  512. // might lose track of the reference count and keep frames out of the pool
  513. // forever.
  514. if (picture_at_client_.erase(picture_buffer_id) > 0) {
  515. VLOGF(1) << "Picture " << picture_buffer_id
  516. << " still referenced, dropping it.";
  517. }
  518. import_frame_cb_.Run(std::move(wrapped_frame));
  519. }
  520. absl::optional<Picture> VdVideoDecodeAccelerator::GetPicture(
  521. const VideoFrame& frame) {
  522. DVLOGF(4);
  523. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  524. auto it = frame_id_to_picture_id_.find(frame.GetGpuMemoryBuffer()->GetId());
  525. if (it == frame_id_to_picture_id_.end()) {
  526. VLOGF(1) << "Failed to find the picture buffer id.";
  527. return absl::nullopt;
  528. }
  529. int32_t picture_buffer_id = it->second;
  530. int32_t bitstream_id = FakeTimestampToBitstreamId(frame.timestamp());
  531. return absl::make_optional(Picture(picture_buffer_id, bitstream_id,
  532. frame.visible_rect(), frame.ColorSpace(),
  533. frame.metadata().allow_overlay));
  534. }
  535. // static
  536. void VdVideoDecodeAccelerator::OnFrameReleasedThunk(
  537. absl::optional<base::WeakPtr<VdVideoDecodeAccelerator>> weak_this,
  538. scoped_refptr<base::SequencedTaskRunner> task_runner,
  539. scoped_refptr<VideoFrame> origin_frame) {
  540. DVLOGF(4);
  541. DCHECK(weak_this);
  542. task_runner->PostTask(
  543. FROM_HERE, base::BindOnce(&VdVideoDecodeAccelerator::OnFrameReleased,
  544. *weak_this, std::move(origin_frame)));
  545. }
  546. void VdVideoDecodeAccelerator::OnFrameReleased(
  547. scoped_refptr<VideoFrame> origin_frame) {
  548. DVLOGF(4);
  549. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  550. auto it =
  551. frame_id_to_picture_id_.find(origin_frame->GetGpuMemoryBuffer()->GetId());
  552. DCHECK(it != frame_id_to_picture_id_.end());
  553. int32_t picture_buffer_id = it->second;
  554. frame_id_to_picture_id_.erase(it);
  555. client_->DismissPictureBuffer(picture_buffer_id);
  556. }
  557. void VdVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) {
  558. DVLOGF(4) << "picture_buffer_id: " << picture_buffer_id;
  559. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  560. auto it = picture_at_client_.find(picture_buffer_id);
  561. if (it == picture_at_client_.end()) {
  562. DVLOGF(3) << picture_buffer_id << " has already been dismissed, ignore.";
  563. return;
  564. }
  565. size_t& num_sent = it->second.second;
  566. DCHECK_NE(num_sent, 0u);
  567. --num_sent;
  568. // The count of calling VDA::ReusePictureBuffer() is the same as calling
  569. // Client::PictureReady(). Now we could really reuse the buffer.
  570. if (num_sent == 0)
  571. picture_at_client_.erase(it);
  572. }
  573. void VdVideoDecodeAccelerator::OnError(base::Location location, Error error) {
  574. LOG(ERROR) << "Failed at " << location.ToString()
  575. << ", error code: " << static_cast<int>(error);
  576. DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
  577. client_->NotifyError(error);
  578. }
  579. } // namespace media