vaapi_video_decoder.cc 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. // Copyright 2019 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/vaapi_video_decoder.h"
  5. #include <vulkan/vulkan.h>
  6. #include <limits>
  7. #include <vector>
  8. #include "base/bind.h"
  9. #include "base/callback_helpers.h"
  10. #include "base/command_line.h"
  11. #include "base/containers/contains.h"
  12. #include "base/containers/fixed_flat_map.h"
  13. #include "base/memory/ptr_util.h"
  14. #include "base/metrics/histogram_macros.h"
  15. #include "base/trace_event/trace_event.h"
  16. #include "build/build_config.h"
  17. #include "build/chromeos_buildflags.h"
  18. #include "gpu/ipc/common/gpu_memory_buffer_support.h"
  19. #include "media/base/bind_to_current_loop.h"
  20. #include "media/base/format_utils.h"
  21. #include "media/base/media_log.h"
  22. #include "media/base/media_switches.h"
  23. #include "media/base/video_frame.h"
  24. #include "media/base/video_util.h"
  25. #include "media/gpu/av1_decoder.h"
  26. #include "media/gpu/chromeos/dmabuf_video_frame_pool.h"
  27. #include "media/gpu/chromeos/platform_video_frame_utils.h"
  28. #include "media/gpu/gpu_video_decode_accelerator_helpers.h"
  29. #include "media/gpu/macros.h"
  30. #include "media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h"
  31. #include "media/gpu/vaapi/h264_vaapi_video_decoder_delegate.h"
  32. #include "media/gpu/vaapi/va_surface.h"
  33. #include "media/gpu/vaapi/vaapi_utils.h"
  34. #include "media/gpu/vaapi/vaapi_wrapper.h"
  35. #include "media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.h"
  36. #include "media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.h"
  37. #include "media/media_buildflags.h"
  38. #include "ui/gfx/buffer_format_util.h"
  39. #if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
  40. #include "media/gpu/vaapi/h265_vaapi_video_decoder_delegate.h"
  41. #endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
  42. #if BUILDFLAG(IS_CHROMEOS_ASH)
  43. // gn check does not account for BUILDFLAG(), so including these headers will
  44. // make gn check fail for builds other than ash-chrome. See gn help nogncheck
  45. // for more information.
  46. #include "chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h" // nogncheck
  47. #include "chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.h" // nogncheck
  48. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  49. namespace media {
  50. namespace {
  51. // Size of the timestamp cache, needs to be large enough for frame-reordering.
  52. constexpr size_t kTimestampCacheSize = 128;
  53. absl::optional<VideoPixelFormat> GetPixelFormatForBitDepth(uint8_t bit_depth) {
  54. constexpr auto kSupportedBitDepthAndGfxFormats = base::MakeFixedFlatMap<
  55. uint8_t, gfx::BufferFormat>({
  56. #if defined(USE_OZONE)
  57. {8u, gfx::BufferFormat::YUV_420_BIPLANAR}, {10u, gfx::BufferFormat::P010},
  58. #else
  59. {8u, gfx::BufferFormat::RGBX_8888},
  60. #endif // defined(USE_OZONE)
  61. });
  62. if (!base::Contains(kSupportedBitDepthAndGfxFormats, bit_depth)) {
  63. VLOGF(1) << "Unsupported bit depth: " << base::strict_cast<int>(bit_depth);
  64. return absl::nullopt;
  65. }
  66. return GfxBufferFormatToVideoPixelFormat(
  67. kSupportedBitDepthAndGfxFormats.at(bit_depth));
  68. }
  69. inline int RoundDownToEven(int x) {
  70. DCHECK_GE(x, 0);
  71. return x - (x % 2);
  72. }
  73. inline int RoundUpToEven(int x) {
  74. DCHECK_GE(x, 0);
  75. CHECK_LT(x, std::numeric_limits<int>::max());
  76. return x + (x % 2);
  77. }
  78. } // namespace
  79. // static
  80. base::AtomicRefCount VaapiVideoDecoder::num_instances_(0);
  81. VaapiVideoDecoder::DecodeTask::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
  82. int32_t buffer_id,
  83. DecodeCB decode_done_cb)
  84. : buffer_(std::move(buffer)),
  85. buffer_id_(buffer_id),
  86. decode_done_cb_(std::move(decode_done_cb)) {}
  87. VaapiVideoDecoder::DecodeTask::~DecodeTask() = default;
  88. VaapiVideoDecoder::DecodeTask::DecodeTask(DecodeTask&&) = default;
  89. // static
  90. std::unique_ptr<VideoDecoderMixin> VaapiVideoDecoder::Create(
  91. std::unique_ptr<MediaLog> media_log,
  92. scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
  93. base::WeakPtr<VideoDecoderMixin::Client> client) {
  94. const bool can_create_decoder =
  95. num_instances_.Increment() < kMaxNumOfInstances ||
  96. !base::FeatureList::IsEnabled(media::kLimitConcurrentDecoderInstances);
  97. if (!can_create_decoder) {
  98. num_instances_.Decrement();
  99. return nullptr;
  100. }
  101. return base::WrapUnique<VideoDecoderMixin>(new VaapiVideoDecoder(
  102. std::move(media_log), std::move(decoder_task_runner), std::move(client)));
  103. }
  104. // static
  105. absl::optional<SupportedVideoDecoderConfigs>
  106. VaapiVideoDecoder::GetSupportedConfigs() {
  107. return ConvertFromSupportedProfiles(
  108. VaapiWrapper::GetSupportedDecodeProfiles(),
  109. #if BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
  110. true /* allow_encrypted */);
  111. #else
  112. false /* allow_encrypted */);
  113. #endif
  114. }
  115. VaapiVideoDecoder::VaapiVideoDecoder(
  116. std::unique_ptr<MediaLog> media_log,
  117. scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
  118. base::WeakPtr<VideoDecoderMixin::Client> client)
  119. : VideoDecoderMixin(std::move(media_log),
  120. std::move(decoder_task_runner),
  121. std::move(client)),
  122. buffer_id_to_timestamp_(kTimestampCacheSize),
  123. weak_this_factory_(this) {
  124. VLOGF(2);
  125. DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());
  126. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  127. weak_this_ = weak_this_factory_.GetWeakPtr();
  128. }
  129. VaapiVideoDecoder::~VaapiVideoDecoder() {
  130. VLOGF(2);
  131. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  132. // Abort all currently scheduled decode tasks.
  133. ClearDecodeTaskQueue(DecoderStatus::Codes::kAborted);
  134. weak_this_factory_.InvalidateWeakPtrs();
  135. // Notify |decoder_delegate_| of an imminent VAContextID destruction, so it
  136. // can destroy any internal structures making use of it.
  137. if (decoder_delegate_)
  138. decoder_delegate_->OnVAContextDestructionSoon();
  139. // Destroy explicitly to DCHECK() that |vaapi_wrapper_| references are held
  140. // inside the accelerator in |decoder_|, by the |allocated_va_surfaces_| and
  141. // of course by this class. To clear |allocated_va_surfaces_| we have to first
  142. // DestroyContext().
  143. decoder_ = nullptr;
  144. if (vaapi_wrapper_) {
  145. vaapi_wrapper_->DestroyContext();
  146. allocated_va_surfaces_.clear();
  147. DCHECK(vaapi_wrapper_->HasOneRef());
  148. vaapi_wrapper_ = nullptr;
  149. }
  150. num_instances_.Decrement();
  151. }
  152. void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
  153. bool /*low_delay*/,
  154. CdmContext* cdm_context,
  155. InitCB init_cb,
  156. const OutputCB& output_cb,
  157. const WaitingCB& waiting_cb) {
  158. DVLOGF(2) << config.AsHumanReadableString();
  159. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  160. DCHECK(config.IsValidConfig());
  161. // Reinitializing the decoder is allowed if there are no pending decodes.
  162. if (current_decode_task_ || !decode_task_queue_.empty() ||
  163. state_ == State::kExpectingReset) {
  164. LOG(ERROR)
  165. << "Don't call Initialize() while there are pending decode tasks";
  166. std::move(init_cb).Run(DecoderStatus::Codes::kFailed);
  167. return;
  168. }
  169. DCHECK(state_ == State::kError || state_ == State::kUninitialized ||
  170. state_ == State::kWaitingForInput);
  171. if (state_ != State::kUninitialized) {
  172. DVLOGF(3) << "Reinitializing decoder";
  173. // Notify |decoder_delegate_| of an imminent VAContextID destruction, so it
  174. // can destroy any internal structures making use of it.
  175. decoder_delegate_->OnVAContextDestructionSoon();
  176. decoder_ = nullptr;
  177. DCHECK(vaapi_wrapper_);
  178. // To clear |allocated_va_surfaces_|, we have to first DestroyContext().
  179. vaapi_wrapper_->DestroyContext();
  180. allocated_va_surfaces_.clear();
  181. DCHECK(vaapi_wrapper_->HasOneRef());
  182. vaapi_wrapper_ = nullptr;
  183. decoder_delegate_ = nullptr;
  184. // |cdm_context_ref_| is reset after |decoder_| because we passed
  185. // |cdm_context_ref_->GetCdmContext()| when creating the |decoder_|, so we
  186. // don't want |decoder_| to have a dangling pointer. We also destroy
  187. // |cdm_event_cb_registration_| before |cdm_context_ref_| so that we have a
  188. // CDM at the moment of destroying the callback registration.
  189. #if BUILDFLAG(IS_CHROMEOS_ASH)
  190. cdm_event_cb_registration_ = nullptr;
  191. #endif
  192. cdm_context_ref_ = nullptr;
  193. transcryption_ = false;
  194. SetState(State::kUninitialized);
  195. }
  196. DCHECK(!current_decode_task_);
  197. DCHECK(decode_task_queue_.empty());
  198. // Destroying the |decoder_| during re-initialization should release all
  199. // output buffers (and there should be no output buffers to begin with if the
  200. // decoder was previously uninitialized).
  201. DCHECK(output_frames_.empty());
  202. if (config.is_encrypted()) {
  203. #if !BUILDFLAG(IS_CHROMEOS_ASH)
  204. SetErrorState("encrypted content is not supported");
  205. std::move(init_cb).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
  206. return;
  207. #else
  208. if (!cdm_context || !cdm_context->GetChromeOsCdmContext()) {
  209. SetErrorState("cannot support encrypted stream w/out ChromeOsCdmContext");
  210. std::move(init_cb).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
  211. return;
  212. }
  213. bool encrypted_av1_support = false;
  214. #if BUILDFLAG(USE_CHROMEOS_PROTECTED_AV1)
  215. encrypted_av1_support = true;
  216. #elif BUILDFLAG(IS_CHROMEOS_LACROS)
  217. encrypted_av1_support = base::CommandLine::ForCurrentProcess()->HasSwitch(
  218. switches::kLacrosUseChromeosProtectedAv1);
  219. #endif
  220. if (config.codec() != VideoCodec::kH264 &&
  221. config.codec() != VideoCodec::kVP9 &&
  222. (config.codec() != VideoCodec::kAV1 || !encrypted_av1_support) &&
  223. config.codec() != VideoCodec::kHEVC) {
  224. SetErrorState(
  225. base::StringPrintf("%s is not supported for encrypted content",
  226. GetCodecName(config.codec()).c_str()));
  227. std::move(init_cb).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
  228. return;
  229. }
  230. cdm_event_cb_registration_ = cdm_context->RegisterEventCB(
  231. base::BindRepeating(&VaapiVideoDecoder::OnCdmContextEvent,
  232. weak_this_factory_.GetWeakPtr()));
  233. cdm_context_ref_ = cdm_context->GetChromeOsCdmContext()->GetCdmContextRef();
  234. // On AMD the content is transcrypted by the pipeline before reaching us,
  235. // but we still need to do special handling with it.
  236. transcryption_ = (VaapiWrapper::GetImplementationType() ==
  237. VAImplementation::kMesaGallium);
  238. #endif
  239. }
  240. // Initialize VAAPI wrapper.
  241. const VideoCodecProfile profile = config.profile();
  242. vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec(
  243. #if BUILDFLAG(IS_CHROMEOS_ASH)
  244. (!cdm_context_ref_ || transcryption_) ? VaapiWrapper::kDecode
  245. : VaapiWrapper::kDecodeProtected,
  246. #else
  247. VaapiWrapper::kDecode,
  248. #endif
  249. profile,
  250. transcryption_ ? EncryptionScheme::kUnencrypted
  251. : config.encryption_scheme(),
  252. base::BindRepeating(&ReportVaapiErrorToUMA,
  253. "Media.VaapiVideoDecoder.VAAPIError"));
  254. UMA_HISTOGRAM_BOOLEAN("Media.VaapiVideoDecoder.VaapiWrapperCreationSuccess",
  255. vaapi_wrapper_.get());
  256. if (!vaapi_wrapper_.get()) {
  257. SetErrorState(
  258. base::StringPrintf("failed initializing VaapiWrapper for profile %s, ",
  259. GetProfileName(profile).c_str()));
  260. std::move(init_cb).Run(DecoderStatus::Codes::kUnsupportedProfile);
  261. return;
  262. }
  263. profile_ = profile;
  264. color_space_ = config.color_space_info();
  265. hdr_metadata_ = config.hdr_metadata();
  266. encryption_scheme_ = transcryption_ ? EncryptionScheme::kUnencrypted
  267. : config.encryption_scheme();
  268. auto accel_status = CreateAcceleratedVideoDecoder();
  269. if (!accel_status.is_ok()) {
  270. SetErrorState("failed to create decoder delegate");
  271. std::move(init_cb).Run(DecoderStatus(DecoderStatus::Codes::kFailed)
  272. .AddCause(std::move(accel_status)));
  273. return;
  274. }
  275. aspect_ratio_ = config.aspect_ratio();
  276. output_cb_ = std::move(output_cb);
  277. waiting_cb_ = std::move(waiting_cb);
  278. SetState(State::kWaitingForInput);
  279. // Notify client initialization was successful.
  280. std::move(init_cb).Run(DecoderStatus::Codes::kOk);
  281. }
  282. void VaapiVideoDecoder::OnCdmContextEvent(CdmContext::Event event) {
  283. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  284. if (event != CdmContext::Event::kHasAdditionalUsableKey)
  285. return;
  286. // Invoke the callback we'd get for a protected session update because this is
  287. // the same thing, it's a trigger that there are new keys, so if we were
  288. // waiting for a key we should fetch them again.
  289. ProtectedSessionUpdate(true);
  290. }
  291. void VaapiVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
  292. DecodeCB decode_cb) {
  293. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  294. DVLOGF(4) << "Queuing input buffer, id: " << next_buffer_id_ << ", size: "
  295. << (buffer->end_of_stream() ? 0 : buffer->data_size());
  296. // If we're in the error state, immediately fail the decode task.
  297. if (state_ == State::kError) {
  298. // VideoDecoder interface: |decode_cb| can't be called from within Decode().
  299. base::SequencedTaskRunnerHandle::Get()->PostTask(
  300. FROM_HERE,
  301. base::BindOnce(std::move(decode_cb), DecoderStatus::Codes::kFailed));
  302. return;
  303. }
  304. if (!buffer->end_of_stream())
  305. buffer_id_to_timestamp_.Put(next_buffer_id_, buffer->timestamp());
  306. decode_task_queue_.emplace(std::move(buffer), next_buffer_id_,
  307. std::move(decode_cb));
  308. // Generate the next positive buffer id. Don't let it overflow because that
  309. // behavior is undefined for signed integers, we mask it down to 30 bits to
  310. // avoid that problem.
  311. next_buffer_id_ = (next_buffer_id_ + 1) & 0x3fffffff;
  312. // If we were waiting for input buffers, start decoding again.
  313. if (state_ == State::kWaitingForInput) {
  314. DCHECK(!current_decode_task_);
  315. SetState(State::kDecoding);
  316. ScheduleNextDecodeTask();
  317. }
  318. }
  319. void VaapiVideoDecoder::ScheduleNextDecodeTask() {
  320. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  321. DCHECK_EQ(state_, State::kDecoding);
  322. DCHECK(!current_decode_task_);
  323. DCHECK(!decode_task_queue_.empty());
  324. // Dequeue the next decode task.
  325. current_decode_task_ = std::move(decode_task_queue_.front());
  326. decode_task_queue_.pop();
  327. if (!current_decode_task_->buffer_->end_of_stream()) {
  328. decoder_->SetStream(current_decode_task_->buffer_id_,
  329. *current_decode_task_->buffer_);
  330. }
  331. decoder_task_runner_->PostTask(
  332. FROM_HERE,
  333. base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
  334. }
  335. void VaapiVideoDecoder::HandleDecodeTask() {
  336. DVLOGF(4);
  337. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  338. if (state_ != State::kDecoding)
  339. return;
  340. DCHECK_EQ(state_, State::kDecoding);
  341. DCHECK(current_decode_task_);
  342. // Check whether a flush was requested.
  343. if (current_decode_task_->buffer_->end_of_stream()) {
  344. Flush();
  345. return;
  346. }
  347. TRACE_EVENT_BEGIN0("media,gpu", "VaapiVideoDecoder::Decode");
  348. AcceleratedVideoDecoder::DecodeResult decode_result = decoder_->Decode();
  349. TRACE_EVENT_END0("media,gpu", "VaapiVideoDecoder::Decode");
  350. switch (decode_result) {
  351. case AcceleratedVideoDecoder::kRanOutOfStreamData:
  352. // Decoding was successful, notify client and try to schedule the next
  353. // task. Switch to the idle state if we ran out of buffers to decode.
  354. std::move(current_decode_task_->decode_done_cb_)
  355. .Run(DecoderStatus::Codes::kOk);
  356. current_decode_task_ = absl::nullopt;
  357. if (!decode_task_queue_.empty()) {
  358. ScheduleNextDecodeTask();
  359. } else {
  360. SetState(State::kWaitingForInput);
  361. }
  362. break;
  363. case AcceleratedVideoDecoder::kConfigChange:
  364. // A new set of output buffers is requested. We either didn't have any
  365. // output buffers yet or encountered a resolution change.
  366. // After the pipeline flushes all frames, ApplyResolutionChange() will be
  367. // called and we can start changing resolution.
  368. DCHECK(client_);
  369. SetState(State::kChangingResolution);
  370. client_->PrepareChangeResolution();
  371. break;
  372. case AcceleratedVideoDecoder::kRanOutOfSurfaces:
  373. // No more surfaces to decode into available, wait until client returns
  374. // video frames to the frame pool.
  375. SetState(State::kWaitingForOutput);
  376. break;
  377. case AcceleratedVideoDecoder::kNeedContextUpdate:
  378. SetErrorState("context updates not supported");
  379. break;
  380. case AcceleratedVideoDecoder::kDecodeError:
  381. UMA_HISTOGRAM_BOOLEAN("Media.VaapiVideoDecoder.DecodeError", true);
  382. SetErrorState("error decoding stream");
  383. break;
  384. case AcceleratedVideoDecoder::kTryAgain:
  385. DVLOG(1) << "Decoder going into the waiting for protected state";
  386. DCHECK_NE(encryption_scheme_, EncryptionScheme::kUnencrypted);
  387. SetState(State::kWaitingForProtected);
  388. // If we have lost our protected HW session, it should be recoverable, so
  389. // indicate that we have lost our decoder state so it can be reloaded.
  390. if (decoder_delegate_->HasInitiatedProtectedRecovery())
  391. waiting_cb_.Run(WaitingReason::kDecoderStateLost);
  392. break;
  393. }
  394. }
  395. void VaapiVideoDecoder::ClearDecodeTaskQueue(DecoderStatus status) {
  396. DVLOGF(4);
  397. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  398. if (current_decode_task_) {
  399. std::move(current_decode_task_->decode_done_cb_).Run(status);
  400. current_decode_task_ = absl::nullopt;
  401. }
  402. while (!decode_task_queue_.empty()) {
  403. std::move(decode_task_queue_.front().decode_done_cb_).Run(status);
  404. decode_task_queue_.pop();
  405. }
  406. }
  407. scoped_refptr<VASurface> VaapiVideoDecoder::CreateSurface() {
  408. DVLOGF(4);
  409. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  410. DCHECK_EQ(state_, State::kDecoding);
  411. DCHECK(current_decode_task_);
  412. // Get a video frame from the video frame pool.
  413. DCHECK(client_);
  414. DmabufVideoFramePool* frame_pool = client_->GetVideoFramePool();
  415. DCHECK(frame_pool);
  416. scoped_refptr<VideoFrame> frame = frame_pool->GetFrame();
  417. if (!frame) {
  418. // Ask the video frame pool to notify us when new frames are available, so
  419. // we can retry the current decode task.
  420. frame_pool->NotifyWhenFrameAvailable(
  421. base::BindOnce(&VaapiVideoDecoder::NotifyFrameAvailable, weak_this_));
  422. return nullptr;
  423. }
  424. // |frame|s coming from ARC++ are not GpuMemoryBuffer-backed, but they have
  425. // DmaBufs whose fd numbers are consistent along the lifetime of the VA
  426. // surfaces they back.
  427. DCHECK(frame->GetGpuMemoryBuffer() || frame->HasDmaBufs());
  428. const gfx::GpuMemoryBufferId frame_id =
  429. frame->GetGpuMemoryBuffer()
  430. ? frame->GetGpuMemoryBuffer()->GetId()
  431. : gfx::GpuMemoryBufferId(frame->DmabufFds()[0].get());
  432. scoped_refptr<VASurface> va_surface;
  433. if (!base::Contains(allocated_va_surfaces_, frame_id)) {
  434. scoped_refptr<gfx::NativePixmap> pixmap =
  435. CreateNativePixmapDmaBuf(frame.get());
  436. if (!pixmap) {
  437. SetErrorState("failed to create NativePixmap from VideoFrame");
  438. return nullptr;
  439. }
  440. va_surface = vaapi_wrapper_->CreateVASurfaceForPixmap(
  441. std::move(pixmap), cdm_context_ref_ || transcryption_);
  442. if (!va_surface || va_surface->id() == VA_INVALID_ID) {
  443. SetErrorState("failed to create VASurface from VideoFrame");
  444. return nullptr;
  445. }
  446. allocated_va_surfaces_[frame_id] = va_surface;
  447. } else {
  448. va_surface = allocated_va_surfaces_[frame_id];
  449. DCHECK_EQ(frame->coded_size(), va_surface->size());
  450. }
  451. // Store the mapping between surface and video frame, so we know which video
  452. // frame to output when the surface is ready. It's also important to keep a
  453. // reference to the video frame during decoding, as the frame will be
  454. // automatically returned to the pool when the last reference is dropped.
  455. VASurfaceID surface_id = va_surface->id();
  456. DCHECK_EQ(output_frames_.count(surface_id), 0u);
  457. output_frames_[surface_id] = frame;
  458. // When the decoder is done using the frame for output or reference, it will
  459. // drop its reference to the surface. We can then safely remove the associated
  460. // video frame from |output_frames_|. To be notified when this happens we wrap
  461. // the surface in another surface with ReleaseVideoFrame() as destruction
  462. // observer.
  463. VASurface::ReleaseCB release_frame_cb =
  464. base::BindOnce(&VaapiVideoDecoder::ReleaseVideoFrame, weak_this_);
  465. return new VASurface(surface_id, frame->layout().coded_size(),
  466. va_surface->format(), std::move(release_frame_cb));
  467. }
  468. void VaapiVideoDecoder::SurfaceReady(scoped_refptr<VASurface> va_surface,
  469. int32_t buffer_id,
  470. const gfx::Rect& visible_rect,
  471. const VideoColorSpace& color_space) {
  472. DVLOGF(4);
  473. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  474. DCHECK_EQ(state_, State::kDecoding);
  475. // Find the timestamp associated with |buffer_id|. It's possible that a
  476. // surface is output multiple times for different |buffer_id|s (e.g. VP9
  477. // show_existing_frame feature). This means we need to output the same frame
  478. // again with a different timestamp.
  479. // On some rare occasions it's also possible that a single DecoderBuffer
  480. // produces multiple surfaces with the same |buffer_id|, so we shouldn't
  481. // remove the timestamp from the cache.
  482. const auto it = buffer_id_to_timestamp_.Peek(buffer_id);
  483. DCHECK(it != buffer_id_to_timestamp_.end());
  484. base::TimeDelta timestamp = it->second;
  485. // Find the frame associated with the surface. We won't erase it from
  486. // |output_frames_| yet, as the decoder might still be using it for reference.
  487. DCHECK_EQ(output_frames_.count(va_surface->id()), 1u);
  488. scoped_refptr<VideoFrame> video_frame = output_frames_[va_surface->id()];
  489. // Set the timestamp at which the decode operation started on the
  490. // |video_frame|. If the frame has been outputted before (e.g. because of VP9
  491. // show-existing-frame feature) we can't overwrite the timestamp directly, as
  492. // the original frame might still be in use. Instead we wrap the frame in
  493. // another frame with a different timestamp.
  494. if (video_frame->timestamp().is_zero())
  495. video_frame->set_timestamp(timestamp);
  496. if (video_frame->visible_rect() != visible_rect ||
  497. video_frame->timestamp() != timestamp) {
  498. gfx::Size natural_size = aspect_ratio_.GetNaturalSize(visible_rect);
  499. scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame(
  500. video_frame, video_frame->format(), visible_rect, natural_size);
  501. wrapped_frame->set_timestamp(timestamp);
  502. video_frame = std::move(wrapped_frame);
  503. }
  504. #if BUILDFLAG(IS_CHROMEOS_ASH)
  505. if (cdm_context_ref_ && !transcryption_) {
  506. // Store the VA-API protected session ID so that it can be re-used for
  507. // scaling the decoded video frame later in the pipeline.
  508. VAProtectedSessionID va_protected_session_id =
  509. vaapi_wrapper_->GetProtectedSessionID();
  510. static_assert(
  511. std::is_same<decltype(va_protected_session_id),
  512. decltype(
  513. video_frame->metadata()
  514. .hw_va_protected_session_id)::value_type>::value,
  515. "The type of VideoFrameMetadata::hw_va_protected_session_id "
  516. "does not match the type exposed by VaapiWrapper");
  517. video_frame->metadata().hw_va_protected_session_id =
  518. va_protected_session_id;
  519. }
  520. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  521. const auto gfx_color_space = color_space.ToGfxColorSpace();
  522. if (gfx_color_space.IsValid())
  523. video_frame->set_color_space(gfx_color_space);
  524. video_frame->set_hdr_metadata(hdr_metadata_);
  525. output_cb_.Run(std::move(video_frame));
  526. }
  527. void VaapiVideoDecoder::ApplyResolutionChange() {
  528. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  529. DCHECK(state_ == State::kChangingResolution ||
  530. state_ == State::kWaitingForInput);
  531. DCHECK(output_frames_.empty());
  532. VLOGF(2);
  533. if (cdm_context_ref_ && !transcryption_) {
  534. // Get the screen resolutions so we can determine if we should pre-scale
  535. // content during decoding to maximize use of overlay downscaling since
  536. // protected content requires overlays currently.
  537. // NOTE: Only use this for protected content as other requirements for using
  538. // it are tied to protected content.
  539. #if BUILDFLAG(IS_CHROMEOS_ASH)
  540. cdm_context_ref_->GetCdmContext()
  541. ->GetChromeOsCdmContext()
  542. ->GetScreenResolutions(BindToCurrentLoop(base::BindOnce(
  543. &VaapiVideoDecoder::ApplyResolutionChangeWithScreenSizes,
  544. weak_this_)));
  545. return;
  546. #endif
  547. }
  548. ApplyResolutionChangeWithScreenSizes(std::vector<gfx::Size>());
  549. }
  550. void VaapiVideoDecoder::ApplyResolutionChangeWithScreenSizes(
  551. const std::vector<gfx::Size>& screen_resolutions) {
  552. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  553. DCHECK(state_ == State::kChangingResolution ||
  554. state_ == State::kWaitingForInput || state_ == State::kResetting ||
  555. state_ == State::kError);
  556. DCHECK(output_frames_.empty());
  557. VLOGF(2);
  558. // If we are not in the state for changing resolution, then skip doing it. For
  559. // all the other states, those can occur because something happened after the
  560. // async call to get the screen sizes in ApplyResolutionChange(), and in that
  561. // case we will get another resolution change event when the decoder parses
  562. // the resolution and notifies us.
  563. if (state_ != State::kChangingResolution)
  564. return;
  565. const uint8_t bit_depth = decoder_->GetBitDepth();
  566. const absl::optional<VideoPixelFormat> format =
  567. GetPixelFormatForBitDepth(bit_depth);
  568. if (!format) {
  569. SetErrorState(base::StringPrintf("unsupported bit depth: %d", bit_depth));
  570. return;
  571. }
  572. // Notify |decoder_delegate_| of an imminent VAContextID destruction, so it
  573. // can destroy any internal structures making use of it.
  574. decoder_delegate_->OnVAContextDestructionSoon();
  575. // All pending decode operations will be completed before triggering a
  576. // resolution change, so we can safely DestroyContext() here; that, in turn,
  577. // allows for clearing the |allocated_va_surfaces_|.
  578. vaapi_wrapper_->DestroyContext();
  579. allocated_va_surfaces_.clear();
  580. const gfx::Rect decoder_visible_rect = decoder_->GetVisibleRect();
  581. const gfx::Size decoder_pic_size = decoder_->GetPicSize();
  582. if (decoder_pic_size.IsEmpty()) {
  583. SetErrorState("|decoder_| returned an empty picture size");
  584. return;
  585. }
  586. gfx::Rect output_visible_rect = decoder_visible_rect;
  587. gfx::Size output_pic_size = decoder_pic_size;
  588. const auto format_fourcc = Fourcc::FromVideoPixelFormat(*format);
  589. CHECK(format_fourcc);
  590. if (!screen_resolutions.empty()) {
  591. // Ideally we would base this off visible size, but that can change
  592. // midstream without forcing a config change, so we need to scale the
  593. // overall decoded image and then apply that same relative scaling to the
  594. // visible rect later.
  595. CHECK(cdm_context_ref_);
  596. gfx::Size max_desired_size;
  597. const float pic_aspect = static_cast<float>(decoder_pic_size.width()) /
  598. decoder_pic_size.height();
  599. for (const auto& screen : screen_resolutions) {
  600. if (screen.IsEmpty())
  601. continue;
  602. int target_width;
  603. int target_height;
  604. const float screen_aspect =
  605. static_cast<float>(screen.width()) / screen.height();
  606. if (pic_aspect >= screen_aspect) {
  607. // Constrain on width.
  608. if (screen.width() < decoder_pic_size.width()) {
  609. target_width = screen.width();
  610. target_height =
  611. base::checked_cast<int>(std::lround(target_width / pic_aspect));
  612. } else {
  613. target_width = decoder_pic_size.width();
  614. target_height = decoder_pic_size.height();
  615. }
  616. } else {
  617. // Constrain on height.
  618. if (screen.height() < decoder_pic_size.height()) {
  619. target_height = screen.height();
  620. target_width =
  621. base::checked_cast<int>(std::lround(target_height * pic_aspect));
  622. } else {
  623. target_height = decoder_pic_size.height();
  624. target_width = decoder_pic_size.width();
  625. }
  626. }
  627. if (target_width > max_desired_size.width() ||
  628. target_height > max_desired_size.height()) {
  629. max_desired_size.SetSize(target_width, target_height);
  630. }
  631. }
  632. if (!max_desired_size.IsEmpty() &&
  633. max_desired_size.width() < decoder_pic_size.width()) {
  634. // Fix this so we are sure it's on a multiple of two to deal with
  635. // subsampling.
  636. max_desired_size.set_width(RoundUpToEven(max_desired_size.width()));
  637. max_desired_size.set_height(RoundUpToEven(max_desired_size.height()));
  638. const auto decode_to_output_scale_factor =
  639. static_cast<float>(max_desired_size.width()) /
  640. decoder_pic_size.width();
  641. output_pic_size = max_desired_size;
  642. output_visible_rect = ScaleToEnclosedRect(decoder_visible_rect,
  643. decode_to_output_scale_factor);
  644. // Make the dimensions even numbered to align with other requirements
  645. // later in the pipeline.
  646. output_visible_rect.set_width(
  647. RoundDownToEven(output_visible_rect.width()));
  648. output_visible_rect.set_height(
  649. RoundDownToEven(output_visible_rect.height()));
  650. CHECK(gfx::Rect(output_pic_size).Contains(output_visible_rect));
  651. }
  652. }
  653. if (profile_ != decoder_->GetProfile()) {
  654. // When a profile is changed, we need to re-initialize VaapiWrapper.
  655. profile_ = decoder_->GetProfile();
  656. auto new_vaapi_wrapper = VaapiWrapper::CreateForVideoCodec(
  657. #if BUILDFLAG(IS_CHROMEOS_ASH)
  658. (!cdm_context_ref_ || transcryption_) ? VaapiWrapper::kDecode
  659. : VaapiWrapper::kDecodeProtected,
  660. #else
  661. VaapiWrapper::kDecode,
  662. #endif
  663. profile_, encryption_scheme_,
  664. base::BindRepeating(&ReportVaapiErrorToUMA,
  665. "Media.VaapiVideoDecoder.VAAPIError"));
  666. if (!new_vaapi_wrapper.get()) {
  667. SetErrorState("failed (re)creating VaapiWrapper");
  668. return;
  669. }
  670. decoder_delegate_->set_vaapi_wrapper(new_vaapi_wrapper.get());
  671. vaapi_wrapper_ = std::move(new_vaapi_wrapper);
  672. }
  673. if (!vaapi_wrapper_->CreateContext(decoder_pic_size)) {
  674. SetErrorState("failed creating VAContext");
  675. return;
  676. }
  677. const gfx::Size decoder_natural_size =
  678. aspect_ratio_.GetNaturalSize(decoder_visible_rect);
  679. #if BUILDFLAG(IS_LINUX)
  680. absl::optional<DmabufVideoFramePool::CreateFrameCB> allocator =
  681. base::BindRepeating(&AllocateCustomFrameProxy, weak_this_);
  682. std::vector<ImageProcessor::PixelLayoutCandidate> candidates = {
  683. {.fourcc = *format_fourcc,
  684. .size = decoder_pic_size,
  685. .modifier = gfx::NativePixmapHandle::kNoModifier}};
  686. #elif BUILDFLAG(IS_CHROMEOS_LACROS)
  687. absl::optional<DmabufVideoFramePool::CreateFrameCB> allocator = absl::nullopt;
  688. std::vector<ImageProcessor::PixelLayoutCandidate> candidates = {
  689. {.fourcc = *format_fourcc,
  690. .size = decoder_pic_size,
  691. .modifier = gfx::NativePixmapHandle::kNoModifier}};
  692. #else
  693. absl::optional<DmabufVideoFramePool::CreateFrameCB> allocator = absl::nullopt;
  694. // TODO(b/203240043): We assume that the |dummy_frame|'s modifier matches the
  695. // buffer returned by the video frame pool. We should create a test to make
  696. // sure this assumption is never violated.
  697. // TODO(b/203240043): Create a GMB directly instead of allocating a
  698. // VideoFrame.
  699. scoped_refptr<VideoFrame> dummy_frame = CreateGpuMemoryBufferVideoFrame(
  700. *format, decoder_pic_size, decoder_visible_rect, decoder_natural_size,
  701. /*timestamp=*/base::TimeDelta(),
  702. cdm_context_ref_ ? gfx::BufferUsage::PROTECTED_SCANOUT_VDA_WRITE
  703. : gfx::BufferUsage::SCANOUT_VDA_WRITE);
  704. if (!dummy_frame) {
  705. SetErrorState("failed to allocate a dummy buffer");
  706. return;
  707. }
  708. std::vector<ImageProcessor::PixelLayoutCandidate> candidates = {
  709. {.fourcc = *format_fourcc,
  710. .size = decoder_pic_size,
  711. .modifier = dummy_frame->layout().modifier()}};
  712. #endif // BUILDFLAG(IS_LINUX)
  713. auto status_or_layout = client_->PickDecoderOutputFormat(
  714. candidates, decoder_visible_rect, decoder_natural_size,
  715. output_visible_rect.size(), decoder_->GetRequiredNumOfPictures(),
  716. /*use_protected=*/!!cdm_context_ref_,
  717. /*need_aux_frame_pool=*/true, std::move(allocator));
  718. if (status_or_layout.has_error()) {
  719. if (status_or_layout == CroStatus::Codes::kResetRequired) {
  720. DVLOGF(2) << "The frame pool initialization is aborted";
  721. SetState(State::kExpectingReset);
  722. } else {
  723. // TODO(crbug/1103510): don't drop the error on the floor here.
  724. SetErrorState("failed Initialize()ing the frame pool");
  725. }
  726. return;
  727. }
  728. DCHECK(current_decode_task_);
  729. // Retry the current decode task.
  730. SetState(State::kDecoding);
  731. decoder_task_runner_->PostTask(
  732. FROM_HERE,
  733. base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
  734. }
  735. // Static
  736. CroStatus::Or<scoped_refptr<VideoFrame>>
  737. VaapiVideoDecoder::AllocateCustomFrameProxy(
  738. base::WeakPtr<VaapiVideoDecoder> decoder,
  739. VideoPixelFormat format,
  740. const gfx::Size& coded_size,
  741. const gfx::Rect& visible_rect,
  742. const gfx::Size& natural_size,
  743. bool use_protected,
  744. bool use_linear_buffers,
  745. base::TimeDelta timestamp) {
  746. if (!decoder)
  747. return CroStatus::Codes::kFailedToCreateVideoFrame;
  748. return decoder->AllocateCustomFrame(format, coded_size, visible_rect,
  749. natural_size, use_protected,
  750. use_linear_buffers, timestamp);
  751. }
  752. CroStatus::Or<scoped_refptr<VideoFrame>> VaapiVideoDecoder::AllocateCustomFrame(
  753. VideoPixelFormat format,
  754. const gfx::Size& coded_size,
  755. const gfx::Rect& visible_rect,
  756. const gfx::Size& natural_size,
  757. bool use_protected,
  758. bool use_linear_buffers,
  759. base::TimeDelta timestamp) {
  760. DVLOGF(2);
  761. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  762. DCHECK(state_ == State::kChangingResolution || state_ == State::kDecoding);
  763. DCHECK(!use_linear_buffers);
  764. if (format != PIXEL_FORMAT_NV12)
  765. return CroStatus::Codes::kFailedToCreateVideoFrame;
  766. auto surface = vaapi_wrapper_->CreateVASurfaceWithUsageHints(
  767. VA_RT_FORMAT_YUV420, coded_size,
  768. {VaapiWrapper::SurfaceUsageHint::kVideoDecoder});
  769. if (!surface)
  770. return CroStatus::Codes::kFailedToCreateVideoFrame;
  771. auto pixmap_and_info =
  772. vaapi_wrapper_->ExportVASurfaceAsNativePixmapDmaBuf(*surface);
  773. if (!pixmap_and_info)
  774. return CroStatus::Codes::kFailedToCreateVideoFrame;
  775. gfx::GpuMemoryBufferHandle gmb_handle;
  776. auto handle_id = GetNextGpuMemoryBufferId();
  777. gmb_handle.id = handle_id;
  778. gmb_handle.type = gfx::GpuMemoryBufferType::NATIVE_PIXMAP;
  779. gmb_handle.native_pixmap_handle = pixmap_and_info->pixmap->ExportHandle();
  780. if (gmb_handle.native_pixmap_handle.planes.empty())
  781. return CroStatus::Codes::kFailedToCreateVideoFrame;
  782. gpu::GpuMemoryBufferSupport gmb_support;
  783. auto gmb = gmb_support.CreateGpuMemoryBufferImplFromHandle(
  784. std::move(gmb_handle), pixmap_and_info->pixmap->GetBufferSize(),
  785. pixmap_and_info->pixmap->GetBufferFormat(),
  786. gfx::BufferUsage::SCANOUT_VDA_WRITE, base::NullCallback());
  787. if (!gmb)
  788. return CroStatus::Codes::kFailedToCreateVideoFrame;
  789. const gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes] = {};
  790. auto frame = VideoFrame::WrapExternalGpuMemoryBuffer(
  791. visible_rect, natural_size, std::move(gmb), mailbox_holders,
  792. base::NullCallback(), timestamp);
  793. if (!frame)
  794. return CroStatus::Codes::kFailedToCreateVideoFrame;
  795. frame->set_ycbcr_info(gpu::VulkanYCbCrInfo(
  796. /*image_format=*/VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
  797. /*external_format=*/0,
  798. /*suggested_ycbcr_model=*/VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709,
  799. /*suggested_ycbcr_range=*/VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
  800. /*suggested_xchroma_offset=*/VK_CHROMA_LOCATION_COSITED_EVEN,
  801. /*suggested_ychroma_offset=*/VK_CHROMA_LOCATION_COSITED_EVEN,
  802. /*format_features=*/VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
  803. VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
  804. VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
  805. VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
  806. VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
  807. VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT));
  808. allocated_va_surfaces_[handle_id] = surface;
  809. return frame;
  810. }
  811. bool VaapiVideoDecoder::NeedsBitstreamConversion() const {
  812. DCHECK(output_cb_) << "VaapiVideoDecoder hasn't been initialized";
  813. NOTREACHED();
  814. return (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) ||
  815. (profile_ >= HEVCPROFILE_MIN && profile_ <= HEVCPROFILE_MAX);
  816. }
  817. bool VaapiVideoDecoder::CanReadWithoutStalling() const {
  818. NOTIMPLEMENTED();
  819. NOTREACHED();
  820. return true;
  821. }
  822. int VaapiVideoDecoder::GetMaxDecodeRequests() const {
  823. NOTREACHED();
  824. return 4;
  825. }
  826. VideoDecoderType VaapiVideoDecoder::GetDecoderType() const {
  827. return VideoDecoderType::kVaapi;
  828. }
  829. bool VaapiVideoDecoder::IsPlatformDecoder() const {
  830. return true;
  831. }
  832. bool VaapiVideoDecoder::NeedsTranscryption() {
  833. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  834. DCHECK(state_ == State::kWaitingForInput);
  835. #if BUILDFLAG(IS_CHROMEOS_ASH)
  836. // We do not need to invoke transcryption if this is coming from a remote CDM
  837. // since it will already have been done.
  838. if (cdm_context_ref_ &&
  839. cdm_context_ref_->GetCdmContext()->GetChromeOsCdmContext() &&
  840. cdm_context_ref_->GetCdmContext()
  841. ->GetChromeOsCdmContext()
  842. ->IsRemoteCdm()) {
  843. return false;
  844. }
  845. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  846. return transcryption_;
  847. }
  848. void VaapiVideoDecoder::ReleaseVideoFrame(VASurfaceID surface_id) {
  849. DVLOGF(4);
  850. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  851. // The decoder has finished using the frame associated with |surface_id| for
  852. // output or reference, so it's safe to drop our reference here. Once the
  853. // client drops its reference the frame will be automatically returned to the
  854. // pool for reuse.
  855. size_t num_erased = output_frames_.erase(surface_id);
  856. DCHECK_EQ(num_erased, 1u);
  857. }
  858. void VaapiVideoDecoder::NotifyFrameAvailable() {
  859. DVLOGF(4);
  860. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  861. // If we were waiting for output buffers, retry the current decode task.
  862. if (state_ == State::kWaitingForOutput) {
  863. DCHECK(current_decode_task_);
  864. SetState(State::kDecoding);
  865. decoder_task_runner_->PostTask(
  866. FROM_HERE,
  867. base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
  868. }
  869. }
  870. void VaapiVideoDecoder::ProtectedSessionUpdate(bool success) {
  871. DVLOGF(4);
  872. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  873. if (!success) {
  874. SetErrorState("terminating decoding after failed protected update");
  875. return;
  876. }
  877. // If we were waiting for a protected update, retry the current decode task.
  878. if (state_ != State::kWaitingForProtected)
  879. return;
  880. DCHECK(current_decode_task_);
  881. SetState(State::kDecoding);
  882. decoder_task_runner_->PostTask(
  883. FROM_HERE,
  884. base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
  885. }
  886. void VaapiVideoDecoder::Flush() {
  887. DVLOGF(2);
  888. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  889. DCHECK_EQ(state_, State::kDecoding);
  890. DCHECK(current_decode_task_);
  891. DCHECK(current_decode_task_->buffer_->end_of_stream());
  892. DCHECK(decode_task_queue_.empty());
  893. // Flush will block until SurfaceReady() has been called for every frame
  894. // currently decoding.
  895. if (!decoder_->Flush()) {
  896. SetErrorState("failed to flush the decoder delegate");
  897. return;
  898. }
  899. // Put the decoder in an idle state, ready to resume. This will release all
  900. // VASurfaces currently held, so |output_frames_| should be empty after reset.
  901. decoder_->Reset();
  902. DCHECK(output_frames_.empty());
  903. // Notify the client flushing is done.
  904. std::move(current_decode_task_->decode_done_cb_)
  905. .Run(DecoderStatus::Codes::kOk);
  906. current_decode_task_ = absl::nullopt;
  907. // Wait for new decodes, no decode tasks should be queued while flushing.
  908. SetState(State::kWaitingForInput);
  909. }
  910. void VaapiVideoDecoder::Reset(base::OnceClosure reset_cb) {
  911. DVLOGF(2);
  912. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  913. // If we encountered an error, skip reset and notify client.
  914. if (state_ == State::kError) {
  915. std::move(reset_cb).Run();
  916. return;
  917. }
  918. if (state_ == State::kChangingResolution ||
  919. state_ == State::kExpectingReset) {
  920. // Recreate |decoder_| and |decoder_delegate_| if we are either:
  921. // a) Reset() in the interim between calling |client_|s
  922. // PrepareChangeResolution() and being called back on
  923. // ApplyResolutionChange(), so the latter will find a fresh |decoder_|;
  924. // b) expecting a Reset() after the initialization of the frame pool was
  925. // aborted.
  926. // Also give a chance to |decoder_delegate_| to release its internal data
  927. // structures.
  928. decoder_delegate_->OnVAContextDestructionSoon();
  929. if (!CreateAcceleratedVideoDecoder().is_ok()) {
  930. SetErrorState("failed to (re)create decoder/delegate");
  931. std::move(reset_cb).Run();
  932. return;
  933. }
  934. } else {
  935. // Put the decoder in an idle state, ready to resume. This will release all
  936. // VASurfaces currently held, so |output_frames_| should be empty after
  937. // reset.
  938. decoder_->Reset();
  939. }
  940. DCHECK(output_frames_.empty());
  941. SetState(State::kResetting);
  942. // Wait until any pending decode task has been aborted.
  943. decoder_task_runner_->PostTask(
  944. FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetDone, weak_this_,
  945. std::move(reset_cb)));
  946. }
  947. VaapiStatus VaapiVideoDecoder::CreateAcceleratedVideoDecoder() {
  948. DVLOGF(2);
  949. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  950. DCHECK(state_ == State::kUninitialized ||
  951. state_ == State::kChangingResolution ||
  952. state_ == State::kExpectingReset);
  953. VaapiVideoDecoderDelegate::ProtectedSessionUpdateCB protected_update_cb =
  954. BindToCurrentLoop(base::BindRepeating(
  955. &VaapiVideoDecoder::ProtectedSessionUpdate, weak_this_));
  956. if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) {
  957. auto accelerator = std::make_unique<H264VaapiVideoDecoderDelegate>(
  958. this, vaapi_wrapper_, std::move(protected_update_cb),
  959. cdm_context_ref_ ? cdm_context_ref_->GetCdmContext() : nullptr,
  960. encryption_scheme_);
  961. decoder_delegate_ = accelerator.get();
  962. decoder_ = std::make_unique<H264Decoder>(std::move(accelerator), profile_,
  963. color_space_);
  964. } else if (profile_ >= VP8PROFILE_MIN && profile_ <= VP8PROFILE_MAX) {
  965. auto accelerator =
  966. std::make_unique<VP8VaapiVideoDecoderDelegate>(this, vaapi_wrapper_);
  967. decoder_delegate_ = accelerator.get();
  968. decoder_ =
  969. std::make_unique<VP8Decoder>(std::move(accelerator), color_space_);
  970. } else if (profile_ >= VP9PROFILE_MIN && profile_ <= VP9PROFILE_MAX) {
  971. auto accelerator = std::make_unique<VP9VaapiVideoDecoderDelegate>(
  972. this, vaapi_wrapper_, std::move(protected_update_cb),
  973. cdm_context_ref_ ? cdm_context_ref_->GetCdmContext() : nullptr,
  974. encryption_scheme_);
  975. decoder_delegate_ = accelerator.get();
  976. decoder_ = std::make_unique<VP9Decoder>(std::move(accelerator), profile_,
  977. color_space_);
  978. }
  979. #if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
  980. else if (profile_ >= HEVCPROFILE_MIN && profile_ <= HEVCPROFILE_MAX) {
  981. auto accelerator = std::make_unique<H265VaapiVideoDecoderDelegate>(
  982. this, vaapi_wrapper_, std::move(protected_update_cb),
  983. cdm_context_ref_ ? cdm_context_ref_->GetCdmContext() : nullptr,
  984. encryption_scheme_);
  985. decoder_delegate_ = accelerator.get();
  986. decoder_ = std::make_unique<H265Decoder>(std::move(accelerator), profile_,
  987. color_space_);
  988. }
  989. #endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
  990. else if (profile_ >= AV1PROFILE_MIN && profile_ <= AV1PROFILE_MAX) {
  991. auto accelerator = std::make_unique<AV1VaapiVideoDecoderDelegate>(
  992. this, vaapi_wrapper_, std::move(protected_update_cb),
  993. cdm_context_ref_ ? cdm_context_ref_->GetCdmContext() : nullptr,
  994. encryption_scheme_);
  995. decoder_delegate_ = accelerator.get();
  996. decoder_ = std::make_unique<AV1Decoder>(std::move(accelerator), profile_,
  997. color_space_);
  998. } else {
  999. return VaapiStatus(VaapiStatus::Codes::kUnsupportedProfile)
  1000. .WithData("profile", profile_);
  1001. }
  1002. return VaapiStatus::Codes::kOk;
  1003. }
  1004. void VaapiVideoDecoder::ResetDone(base::OnceClosure reset_cb) {
  1005. DVLOGF(2);
  1006. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1007. DCHECK_EQ(state_, State::kResetting);
  1008. DCHECK(!current_decode_task_);
  1009. DCHECK(decode_task_queue_.empty());
  1010. std::move(reset_cb).Run();
  1011. SetState(State::kWaitingForInput);
  1012. }
  1013. void VaapiVideoDecoder::SetState(State state) {
  1014. DVLOGF(3) << static_cast<int>(state)
  1015. << ", current state: " << static_cast<int>(state_);
  1016. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1017. // Check whether the state change is valid.
  1018. switch (state) {
  1019. case State::kUninitialized:
  1020. DCHECK(state_ == State::kWaitingForInput || state_ == State::kError);
  1021. break;
  1022. case State::kWaitingForInput:
  1023. DCHECK(decode_task_queue_.empty());
  1024. DCHECK(!current_decode_task_);
  1025. DCHECK(state_ == State::kUninitialized || state_ == State::kDecoding ||
  1026. state_ == State::kResetting);
  1027. break;
  1028. case State::kWaitingForProtected:
  1029. DCHECK(!!cdm_context_ref_);
  1030. [[fallthrough]];
  1031. case State::kWaitingForOutput:
  1032. DCHECK(current_decode_task_);
  1033. DCHECK_EQ(state_, State::kDecoding);
  1034. break;
  1035. case State::kDecoding:
  1036. DCHECK(state_ == State::kWaitingForInput ||
  1037. state_ == State::kWaitingForOutput ||
  1038. state_ == State::kChangingResolution ||
  1039. state_ == State::kWaitingForProtected);
  1040. break;
  1041. case State::kResetting:
  1042. DCHECK(state_ == State::kWaitingForInput ||
  1043. state_ == State::kWaitingForOutput || state_ == State::kDecoding ||
  1044. state_ == State::kWaitingForProtected ||
  1045. state_ == State::kChangingResolution ||
  1046. state_ == State::kExpectingReset);
  1047. ClearDecodeTaskQueue(DecoderStatus::Codes::kAborted);
  1048. break;
  1049. case State::kChangingResolution:
  1050. DCHECK_EQ(state_, State::kDecoding);
  1051. break;
  1052. case State::kExpectingReset:
  1053. DCHECK_EQ(state_, State::kChangingResolution);
  1054. break;
  1055. case State::kError:
  1056. ClearDecodeTaskQueue(DecoderStatus::Codes::kFailed);
  1057. break;
  1058. }
  1059. state_ = state;
  1060. }
  1061. void VaapiVideoDecoder::SetErrorState(std::string message) {
  1062. LOG(ERROR) << message;
  1063. if (media_log_)
  1064. MEDIA_LOG(ERROR, media_log_) << "VaapiVideoDecoder: " << message;
  1065. SetState(State::kError);
  1066. }
  1067. } // namespace media