// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/gpu/vaapi/vaapi_video_decode_accelerator.h"

#include <string.h>
#include <va/va.h>

#include <memory>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
#include "base/containers/cxx20_erase.h"
#include "base/cpu.h"
#include "base/files/scoped_file.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "gpu/ipc/service/gpu_channel.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/format_utils.h"
#include "media/base/media_log.h"
#include "media/base/unaligned_shared_memory.h"
#include "media/base/video_util.h"
#include "media/gpu/accelerated_video_decoder.h"
#include "media/gpu/h264_decoder.h"
#include "media/gpu/macros.h"
#include "media/gpu/vaapi/h264_vaapi_video_decoder_delegate.h"
#include "media/gpu/vaapi/vaapi_common.h"
#include "media/gpu/vaapi/vaapi_picture.h"
#include "media/gpu/vaapi/vaapi_utils.h"
#include "media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.h"
#include "media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.h"
#include "media/gpu/vp8_decoder.h"
#include "media/gpu/vp9_decoder.h"
#include "media/video/picture.h"
#include "ui/base/ui_base_features.h"
#include "ui/gl/gl_image.h"

namespace media {

namespace {

// Returns the preferred VA_RT_FORMAT for the given |profile|.
unsigned int GetVaFormatForVideoCodecProfile(VideoCodecProfile profile) {
  if (profile == VP9PROFILE_PROFILE2 || profile == VP9PROFILE_PROFILE3)
    return VA_RT_FORMAT_YUV420_10BPP;
  return VA_RT_FORMAT_YUV420;
}

// Returns true if the CPU is an Intel Gemini Lake or later (including Kaby
// Lake) Cpu platform id's are referenced from the following file in kernel
// source arch/x86/include/asm/intel-family.h
bool IsGeminiLakeOrLater() {
  constexpr int kPentiumAndLaterFamily = 0x06;
  constexpr int kGeminiLakeModelId = 0x7A;
  static base::CPU cpuid;
  static bool is_geminilake_or_later =
      cpuid.family() == kPentiumAndLaterFamily &&
      cpuid.model() >= kGeminiLakeModelId;
  return is_geminilake_or_later;
}

}  // namespace

#define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \
  do {                                                             \
    if (!(result)) {                                               \
      LOG(ERROR) << log;                                           \
      NotifyError(error_code);                                     \
      return ret;                                                  \
    }                                                              \
  } while (0)

#define RETURN_AND_NOTIFY_ON_STATUS(status, ret) \
  do {                                           \
    if (!status.is_ok()) {                       \
      NotifyStatus(status);                      \
      return ret;                                \
    }                                            \
  } while (0)

class VaapiVideoDecodeAccelerator::InputBuffer {
 public:
  InputBuffer() : buffer_(nullptr) {}
  InputBuffer(int32_t id,
              scoped_refptr<DecoderBuffer> buffer,
              base::OnceCallback<void(int32_t id)> release_cb)
      : id_(id),
        buffer_(std::move(buffer)),
        release_cb_(std::move(release_cb)) {}

  InputBuffer(const InputBuffer&) = delete;
  InputBuffer& operator=(const InputBuffer&) = delete;

  ~InputBuffer() {
    DVLOGF(4) << "id = " << id_;
    if (release_cb_)
      std::move(release_cb_).Run(id_);
  }

  // Indicates this is a dummy buffer for flush request.
  bool IsFlushRequest() const { return !buffer_; }
  int32_t id() const { return id_; }
  const scoped_refptr<DecoderBuffer>& buffer() const { return buffer_; }

 private:
  const int32_t id_ = -1;
  const scoped_refptr<DecoderBuffer> buffer_;
  base::OnceCallback<void(int32_t id)> release_cb_;
};

void VaapiVideoDecodeAccelerator::NotifyStatus(Status status) {
  DCHECK(!status.is_ok());
  // Send a platform notification error
  NotifyError(PLATFORM_FAILURE);

  // TODO(crbug.com/1103510) there is no MediaLog here, we should change that.
  std::string output_str;
  base::JSONWriter::Write(MediaSerialize(status), &output_str);
  DLOG(ERROR) << output_str;
}

void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
  if (!task_runner_->BelongsToCurrentThread()) {
    DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
    task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&VaapiVideoDecodeAccelerator::NotifyError,
                                  weak_this_, error));
    return;
  }

  VLOGF(1) << "Notifying of error " << error;
  if (client_) {
    client_->NotifyError(error);
    client_ptr_factory_.reset();
  }
}

VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
    const MakeGLContextCurrentCallback& make_context_current_cb,
    const BindGLImageCallback& bind_image_cb)
    : state_(kUninitialized),
      input_ready_(&lock_),
      buffer_allocation_mode_(BufferAllocationMode::kNormal),
      surfaces_available_(&lock_),
      va_surface_format_(VA_INVALID_ID),
      task_runner_(base::ThreadTaskRunnerHandle::Get()),
      decoder_thread_("VaapiDecoderThread"),
      finish_flush_pending_(false),
      awaiting_va_surfaces_recycle_(false),
      requested_num_pics_(0),
      requested_num_reference_frames_(0),
      previously_requested_num_reference_frames_(0),
      profile_(VIDEO_CODEC_PROFILE_UNKNOWN),
      make_context_current_cb_(make_context_current_cb),
      bind_image_cb_(bind_image_cb),
      weak_this_factory_(this) {
  weak_this_ = weak_this_factory_.GetWeakPtr();
  va_surface_recycle_cb_ = BindToCurrentLoop(base::BindRepeating(
      &VaapiVideoDecodeAccelerator::RecycleVASurface, weak_this_));
  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
      this, "media::VaapiVideoDecodeAccelerator",
      base::ThreadTaskRunnerHandle::Get());
}

VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);
}

bool VaapiVideoDecodeAccelerator::Initialize(const Config& config,
                                             Client* client) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  vaapi_picture_factory_ = std::make_unique<VaapiPictureFactory>();

  if (config.is_encrypted()) {
    NOTREACHED() << "Encrypted streams are not supported for this VDA";
    return false;
  }

  client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
  client_ = client_ptr_factory_->GetWeakPtr();

  VideoCodecProfile profile = config.profile;

  base::AutoLock auto_lock(lock_);
  DCHECK_EQ(state_, kUninitialized);
  VLOGF(2) << "Initializing VAVDA, profile: " << GetProfileName(profile);

  vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec(
      VaapiWrapper::kDecode, profile, EncryptionScheme::kUnencrypted,
      base::BindRepeating(&ReportVaapiErrorToUMA,
                          "Media.VaapiVideoDecodeAccelerator.VAAPIError"));

  UMA_HISTOGRAM_BOOLEAN("Media.VAVDA.VaapiWrapperCreationSuccess",
                        vaapi_wrapper_.get());
  if (!vaapi_wrapper_.get()) {
    VLOGF(1) << "Failed initializing VAAPI for profile "
             << GetProfileName(profile);
    return false;
  }

  if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
    auto accelerator =
        std::make_unique<H264VaapiVideoDecoderDelegate>(this, vaapi_wrapper_);
    decoder_delegate_ = accelerator.get();
    decoder_.reset(new H264Decoder(std::move(accelerator), profile,
                                   config.container_color_space));
  } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) {
    auto accelerator =
        std::make_unique<VP8VaapiVideoDecoderDelegate>(this, vaapi_wrapper_);
    decoder_delegate_ = accelerator.get();
    decoder_.reset(new VP8Decoder(std::move(accelerator)));
  } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) {
    auto accelerator =
        std::make_unique<VP9VaapiVideoDecoderDelegate>(this, vaapi_wrapper_);
    decoder_delegate_ = accelerator.get();
    decoder_.reset(new VP9Decoder(std::move(accelerator), profile,
                                  config.container_color_space));
  } else {
    VLOGF(1) << "Unsupported profile " << GetProfileName(profile);
    return false;
  }

  CHECK(decoder_thread_.Start());
  decoder_thread_task_runner_ = decoder_thread_.task_runner();

  state_ = kIdle;
  profile_ = profile;
  output_mode_ = config.output_mode;
  buffer_allocation_mode_ = DecideBufferAllocationMode();
  previously_requested_num_reference_frames_ = 0;
  return true;
}

void VaapiVideoDecodeAccelerator::OutputPicture(
    scoped_refptr<VASurface> va_surface,
    int32_t input_id,
    gfx::Rect visible_rect,
    const VideoColorSpace& picture_color_space) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  const VASurfaceID va_surface_id = va_surface->id();

  VaapiPicture* picture = nullptr;
  {
    base::AutoLock auto_lock(lock_);
    int32_t picture_buffer_id = available_picture_buffers_.front();
    if (buffer_allocation_mode_ == BufferAllocationMode::kNone) {
      // Find the |pictures_| entry matching |va_surface_id|.
      for (const auto& id_and_picture : pictures_) {
        if (id_and_picture.second->va_surface_id() == va_surface_id) {
          picture_buffer_id = id_and_picture.first;
          break;
        }
      }
    }
    picture = pictures_[picture_buffer_id].get();
    DCHECK(base::Contains(available_picture_buffers_, picture_buffer_id));
    base::Erase(available_picture_buffers_, picture_buffer_id);
  }

  DCHECK(picture) << " could not find " << va_surface_id << " available";
  const int32_t output_id = picture->picture_buffer_id();

  DVLOGF(4) << "Outputting VASurface " << va_surface->id()
            << " into pixmap bound to picture buffer id " << output_id;

  if (buffer_allocation_mode_ != BufferAllocationMode::kNone) {
    TRACE_EVENT2("media,gpu", "VAVDA::DownloadFromSurface", "input_id",
                 input_id, "output_id", output_id);
    RETURN_AND_NOTIFY_ON_FAILURE(picture->DownloadFromSurface(va_surface),
                                 "Failed putting surface into pixmap",
                                 PLATFORM_FAILURE, );
  }

  {
    base::AutoLock auto_lock(lock_);
    TRACE_COUNTER_ID2("media,gpu", "Vaapi frames at client", this, "used",
                      pictures_.size() - available_picture_buffers_.size(),
                      "available", available_picture_buffers_.size());
  }

  DVLOGF(4) << "Notifying output picture id " << output_id << " for input "
            << input_id
            << " is ready. visible rect: " << visible_rect.ToString();
  if (!client_)
    return;

  Picture client_picture(output_id, input_id, visible_rect,
                         picture_color_space.ToGfxColorSpace(),
                         picture->AllowOverlay());
  client_picture.set_read_lock_fences_enabled(true);
  // Notify the |client_| a picture is ready to be consumed.
  client_->PictureReady(client_picture);
}

void VaapiVideoDecodeAccelerator::TryOutputPicture() {
  DCHECK(task_runner_->BelongsToCurrentThread());

  // Handle Destroy() arriving while pictures are queued for output.
  if (!client_)
    return;

  {
    base::AutoLock auto_lock(lock_);
    if (pending_output_cbs_.empty() || available_picture_buffers_.empty())
      return;
  }

  auto output_cb = std::move(pending_output_cbs_.front());
  pending_output_cbs_.pop();
  std::move(output_cb).Run();

  if (finish_flush_pending_ && pending_output_cbs_.empty())
    FinishFlush();
}

void VaapiVideoDecodeAccelerator::QueueInputBuffer(
    scoped_refptr<DecoderBuffer> buffer,
    int32_t bitstream_id) {
  DVLOGF(4) << "Queueing new input buffer id: " << bitstream_id
            << " size: " << (buffer->end_of_stream() ? 0 : buffer->data_size());
  DCHECK(task_runner_->BelongsToCurrentThread());
  TRACE_EVENT1("media,gpu", "QueueInputBuffer", "input_id", bitstream_id);

  base::AutoLock auto_lock(lock_);
  if (buffer->end_of_stream()) {
    auto flush_buffer = std::make_unique<InputBuffer>();
    DCHECK(flush_buffer->IsFlushRequest());
    input_buffers_.push(std::move(flush_buffer));
  } else {
    auto input_buffer = std::make_unique<InputBuffer>(
        bitstream_id, std::move(buffer),
        BindToCurrentLoop(
            base::BindOnce(&Client::NotifyEndOfBitstreamBuffer, client_)));
    input_buffers_.push(std::move(input_buffer));
  }

  TRACE_COUNTER1("media,gpu", "Vaapi input buffers", input_buffers_.size());
  input_ready_.Signal();

  switch (state_) {
    case kIdle:
      state_ = kDecoding;
      decoder_thread_task_runner_->PostTask(
          FROM_HERE, base::BindOnce(&VaapiVideoDecodeAccelerator::DecodeTask,
                                    base::Unretained(this)));
      break;

    case kDecoding:
      // Decoder already running.
      break;

    case kResetting:
      // When resetting, allow accumulating bitstream buffers, so that
      // the client can queue after-seek-buffers while we are finishing with
      // the before-seek one.
      break;

    default:
      LOG(ERROR) << "Decode/Flush request from client in invalid state: "
                 << state_;
      NotifyError(PLATFORM_FAILURE);
      break;
  }
}

bool VaapiVideoDecodeAccelerator::GetCurrInputBuffer_Locked() {
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  lock_.AssertAcquired();

  if (curr_input_buffer_.get())
    return true;

  // Will only wait if it is expected that in current state new buffers will
  // be queued from the client via Decode(). The state can change during wait.
  while (input_buffers_.empty() && (state_ == kDecoding || state_ == kIdle))
    input_ready_.Wait();

  // We could have got woken up in a different state or never got to sleep
  // due to current state.
  if (state_ != kDecoding && state_ != kIdle)
    return false;

  DCHECK(!input_buffers_.empty());
  curr_input_buffer_ = std::move(input_buffers_.front());
  input_buffers_.pop();
  TRACE_COUNTER1("media,gpu", "Vaapi input buffers", input_buffers_.size());

  if (curr_input_buffer_->IsFlushRequest()) {
    DVLOGF(4) << "New flush buffer";
    return true;
  }

  DVLOGF(4) << "New |curr_input_buffer_|, id: " << curr_input_buffer_->id()
            << " size: " << curr_input_buffer_->buffer()->data_size() << "B";
  decoder_->SetStream(curr_input_buffer_->id(), *curr_input_buffer_->buffer());
  return true;
}

void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() {
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  lock_.AssertAcquired();
  DCHECK(curr_input_buffer_.get());
  curr_input_buffer_.reset();
}

// TODO(posciak): refactor the whole class to remove sleeping in wait for
// surfaces, and reschedule DecodeTask instead.
bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() {
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  lock_.AssertAcquired();

  while (available_va_surfaces_.empty() &&
         (state_ == kDecoding || state_ == kIdle)) {
    surfaces_available_.Wait();
  }

  return state_ == kDecoding || state_ == kIdle;
}

void VaapiVideoDecodeAccelerator::DecodeTask() {
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  base::AutoLock auto_lock(lock_);

  if (state_ != kDecoding)
    return;
  DVLOGF(4) << "Decode task";

  // Try to decode what stream data is (still) in the decoder until we run out
  // of it.
  while (GetCurrInputBuffer_Locked()) {
    DCHECK(curr_input_buffer_.get());

    if (curr_input_buffer_->IsFlushRequest()) {
      FlushTask();
      break;
    }

    AcceleratedVideoDecoder::DecodeResult res;
    {
      // We are OK releasing the lock here, as decoder never calls our methods
      // directly and we will reacquire the lock before looking at state again.
      // This is the main decode function of the decoder and while keeping
      // the lock for its duration would be fine, it would defeat the purpose
      // of having a separate decoder thread.
      base::AutoUnlock auto_unlock(lock_);
      TRACE_EVENT0("media,gpu", "VAVDA::Decode");
      res = decoder_->Decode();
    }

    switch (res) {
      case AcceleratedVideoDecoder::kConfigChange: {
        const uint8_t bit_depth = decoder_->GetBitDepth();
        RETURN_AND_NOTIFY_ON_FAILURE(
            bit_depth == 8u,
            "Unsupported bit depth: " << base::strict_cast<int>(bit_depth),
            PLATFORM_FAILURE, );
        // The visible rect should be a subset of the picture size. Otherwise,
        // the encoded stream is bad.
        const gfx::Size pic_size = decoder_->GetPicSize();
        const gfx::Rect visible_rect = decoder_->GetVisibleRect();
        RETURN_AND_NOTIFY_ON_FAILURE(
            gfx::Rect(pic_size).Contains(visible_rect),
            "The visible rectangle is not contained by the picture size",
            UNREADABLE_INPUT, );
        VLOGF(2) << "Decoder requesting a new set of surfaces";
        size_t required_num_of_pictures = decoder_->GetRequiredNumOfPictures();
        if (buffer_allocation_mode_ == BufferAllocationMode::kNone &&
            profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) {
          // For H.264, the decoder might request too few pictures. In
          // BufferAllocationMode::kNone, this can cause us to do a lot of busy
          // work waiting for picture buffers to come back from the client (see
          // crbug.com/910986#c32). This is a workaround to increase the
          // likelihood that we don't have to wait on buffers to come back from
          // the client. |kNumOfPics| is picked to mirror the value returned by
          // VP9Decoder::GetRequiredNumOfPictures().
          constexpr size_t kMinNumOfPics = 13u;
          required_num_of_pictures =
              std::max(kMinNumOfPics, required_num_of_pictures);
        }

        // Notify |decoder_delegate_| of an imminent VAContextID destruction, so
        // it can destroy any internal structures making use of it.
        decoder_delegate_->OnVAContextDestructionSoon();

        task_runner_->PostTask(
            FROM_HERE,
            base::BindOnce(
                &VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange,
                weak_this_, required_num_of_pictures, pic_size,
                decoder_->GetNumReferenceFrames(), visible_rect));
        // We'll get rescheduled once ProvidePictureBuffers() finishes.
        return;
      }
      case AcceleratedVideoDecoder::kRanOutOfStreamData:
        ReturnCurrInputBuffer_Locked();
        break;

      case AcceleratedVideoDecoder::kRanOutOfSurfaces:
        // No more output buffers in the decoder, try getting more or go to
        // sleep waiting for them.
        if (!WaitForSurfaces_Locked())
          return;

        break;

      case AcceleratedVideoDecoder::kNeedContextUpdate:
        // This should not happen as we return false from
        // IsFrameContextRequired().
        NOTREACHED() << "Context updates not supported";
        return;

      case AcceleratedVideoDecoder::kDecodeError:
        RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream",
                                     PLATFORM_FAILURE, );
        return;

      case AcceleratedVideoDecoder::kTryAgain:
        NOTREACHED() << "Should not reach here unless this class accepts "
                        "encrypted streams.";
        RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream",
                                     PLATFORM_FAILURE, );
        return;
    }
  }
}

void VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange(
    size_t num_pics,
    gfx::Size size,
    size_t num_reference_frames,
    const gfx::Rect& visible_rect) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DCHECK(!awaiting_va_surfaces_recycle_);
  DCHECK_GT(num_pics, num_reference_frames);

  // At this point decoder has stopped running and has already posted onto our
  // loop any remaining output request callbacks, which executed before we got
  // here. Some of them might have been pended though, because we might not have
  // had enough PictureBuffers to output surfaces to. Initiate a wait cycle,
  // which will wait for client to return enough PictureBuffers to us, so that
  // we can finish all pending output callbacks, releasing associated surfaces.
  awaiting_va_surfaces_recycle_ = true;

  requested_pic_size_ = size;
  requested_visible_rect_ = visible_rect;
  if (buffer_allocation_mode_ == BufferAllocationMode::kSuperReduced) {
    // Add one to the reference frames for the one being currently egressed.
    requested_num_reference_frames_ = num_reference_frames + 1;
    requested_num_pics_ = num_pics - num_reference_frames;
  } else if (buffer_allocation_mode_ == BufferAllocationMode::kReduced) {
    // Add one to the reference frames for the one being currently egressed,
    // and an extra allocation for both |client_| and |decoder_|.
    requested_num_reference_frames_ = num_reference_frames + 2;
    requested_num_pics_ = num_pics - num_reference_frames + 1;
  } else {
    requested_num_reference_frames_ = 0;
    requested_num_pics_ = num_pics + num_extra_pics_;
  }

  VLOGF(2) << " |requested_num_pics_| = " << requested_num_pics_
           << "; |requested_num_reference_frames_| = "
           << requested_num_reference_frames_;

  TryFinishSurfaceSetChange();
}

void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
  DCHECK(task_runner_->BelongsToCurrentThread());

  if (!awaiting_va_surfaces_recycle_)
    return;

  base::AutoLock auto_lock(lock_);
  const size_t expected_max_available_va_surfaces =
      IsBufferAllocationModeReducedOrSuperReduced()
          ? previously_requested_num_reference_frames_
          : pictures_.size();
  if (!pending_output_cbs_.empty() ||
      expected_max_available_va_surfaces != available_va_surfaces_.size()) {
    // If we're here the stream resolution has changed; we need to wait until:
    // - all |pending_output_cbs_| have been executed
    // - all VASurfaces are back to |available_va_surfaces_|; we can't use
    //   |requested_num_reference_frames_| for comparison, since it might have
    //   changed in the previous call to InitiateSurfaceSetChange(), so we use
    //   |previously_requested_num_reference_frames_| instead.
    DVLOGF(2) << "Awaiting pending output/surface release callbacks to finish";
    task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange,
                       weak_this_));
    return;
  }

  previously_requested_num_reference_frames_ = requested_num_reference_frames_;

  // All surfaces released, destroy them and dismiss all PictureBuffers.
  awaiting_va_surfaces_recycle_ = false;

  const VideoCodecProfile new_profile = decoder_->GetProfile();
  if (profile_ != new_profile) {
    profile_ = new_profile;
    auto new_vaapi_wrapper = VaapiWrapper::CreateForVideoCodec(
        VaapiWrapper::kDecode, profile_, EncryptionScheme::kUnencrypted,
        base::BindRepeating(&ReportVaapiErrorToUMA,
                            "Media.VaapiVideoDecodeAccelerator.VAAPIError"));
    RETURN_AND_NOTIFY_ON_FAILURE(new_vaapi_wrapper.get(),
                                 "Failed creating VaapiWrapper",
                                 INVALID_ARGUMENT, );
    decoder_delegate_->set_vaapi_wrapper(new_vaapi_wrapper.get());
    vaapi_wrapper_ = std::move(new_vaapi_wrapper);
  } else {
    vaapi_wrapper_->DestroyContext();
  }

  available_va_surfaces_.clear();

  for (auto iter = pictures_.begin(); iter != pictures_.end(); ++iter) {
    VLOGF(2) << "Dismissing picture id: " << iter->first;
    if (client_)
      client_->DismissPictureBuffer(iter->first);
  }
  pictures_.clear();

  // And ask for a new set as requested.
  VLOGF(2) << "Requesting " << requested_num_pics_
           << " pictures of size: " << requested_pic_size_.ToString()
           << " and visible rectangle = " << requested_visible_rect_.ToString();

  const absl::optional<VideoPixelFormat> format =
      GfxBufferFormatToVideoPixelFormat(
          vaapi_picture_factory_->GetBufferFormat());
  CHECK(format);
  task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&Client::ProvidePictureBuffersWithVisibleRect,
                                client_, requested_num_pics_, *format, 1,
                                requested_pic_size_, requested_visible_rect_,
                                vaapi_picture_factory_->GetGLTextureTarget()));
  // |client_| may respond via AssignPictureBuffers().
}

void VaapiVideoDecodeAccelerator::Decode(BitstreamBuffer bitstream_buffer) {
  Decode(bitstream_buffer.ToDecoderBuffer(), bitstream_buffer.id());
}

void VaapiVideoDecodeAccelerator::Decode(scoped_refptr<DecoderBuffer> buffer,
                                         int32_t bitstream_id) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  TRACE_EVENT1("media,gpu", "VAVDA::Decode", "Buffer id", bitstream_id);

  if (bitstream_id < 0) {
    LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_id;
    NotifyError(INVALID_ARGUMENT);
    return;
  }

  if (!buffer) {
    if (client_)
      client_->NotifyEndOfBitstreamBuffer(bitstream_id);
    return;
  }

  QueueInputBuffer(std::move(buffer), bitstream_id);
}

void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
    const std::vector<PictureBuffer>& buffers) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  base::AutoLock auto_lock(lock_);
  DCHECK(pictures_.empty());

  available_picture_buffers_.clear();

  RETURN_AND_NOTIFY_ON_FAILURE(
      buffers.size() >= requested_num_pics_,
      "Got an invalid number of picture buffers. (Got " << buffers.size()
      << ", requested " << requested_num_pics_ << ")", INVALID_ARGUMENT, );
  // requested_pic_size_ can be adjusted by VDA client. We should update
  // |requested_pic_size_| by buffers[0].size(). But AMD driver doesn't decode
  // frames correctly if the surface stride is different from the width of a
  // coded size.
  // TODO(b/139460315): Save buffers[0].size() as |adjusted_size_| once the
  // AMD driver issue is resolved.

  va_surface_format_ = GetVaFormatForVideoCodecProfile(profile_);
  std::vector<VASurfaceID> va_surface_ids;
  scoped_refptr<VaapiWrapper> vaapi_wrapper_for_picture = vaapi_wrapper_;

  const bool requires_vpp =
      vaapi_picture_factory_->NeedsProcessingPipelineForDownloading();
  // If we aren't in BufferAllocationMode::kNone mode and the VaapiPicture
  // implementation we get from |vaapi_picture_factory_| requires the video
  // processing pipeline for downloading the decoded frame from the internal
  // surface, we need to create a |vpp_vaapi_wrapper_|.
  if (requires_vpp && buffer_allocation_mode_ != BufferAllocationMode::kNone) {
    if (!vpp_vaapi_wrapper_) {
      vpp_vaapi_wrapper_ = VaapiWrapper::Create(
          VaapiWrapper::kVideoProcess, VAProfileNone,
          EncryptionScheme::kUnencrypted,
          base::BindRepeating(
              &ReportVaapiErrorToUMA,
              "Media.VaapiVideoDecodeAccelerator.Vpp.VAAPIError"));
      RETURN_AND_NOTIFY_ON_FAILURE(vpp_vaapi_wrapper_,
                                   "Failed to initialize VppVaapiWrapper",
                                   PLATFORM_FAILURE, );
      // Size is irrelevant for a VPP context.
      RETURN_AND_NOTIFY_ON_FAILURE(
          vpp_vaapi_wrapper_->CreateContext(gfx::Size()),
          "Failed to create Context", PLATFORM_FAILURE, );
    }
    vaapi_wrapper_for_picture = vpp_vaapi_wrapper_;
  }

  for (size_t i = 0; i < buffers.size(); ++i) {
    // TODO(b/139460315): Create with buffers[i] once the AMD driver issue is
    // resolved.
    PictureBuffer buffer = buffers[i];
    buffer.set_size(requested_pic_size_);

    // Note that the |size_to_bind| is not relevant in IMPORT mode.
    const gfx::Size size_to_bind =
        (output_mode_ == Config::OutputMode::ALLOCATE)
            ? GetRectSizeFromOrigin(requested_visible_rect_)
            : gfx::Size();

    std::unique_ptr<VaapiPicture> picture = vaapi_picture_factory_->Create(
        vaapi_wrapper_for_picture, make_context_current_cb_, bind_image_cb_,
        buffer, size_to_bind);
    RETURN_AND_NOTIFY_ON_FAILURE(picture, "Failed creating a VaapiPicture",
                                 PLATFORM_FAILURE, );

    if (output_mode_ == Config::OutputMode::ALLOCATE) {
      RETURN_AND_NOTIFY_ON_STATUS(
          picture->Allocate(vaapi_picture_factory_->GetBufferFormat()), );

      available_picture_buffers_.push_back(buffers[i].id());
      VASurfaceID va_surface_id = picture->va_surface_id();
      if (va_surface_id != VA_INVALID_ID)
        va_surface_ids.push_back(va_surface_id);
    }

    DCHECK(!base::Contains(pictures_, buffers[i].id()));
    pictures_[buffers[i].id()] = std::move(picture);

    surfaces_available_.Signal();
  }

  base::RepeatingCallback<void(VASurfaceID)> va_surface_release_cb;

  // If we aren't in BufferAllocationMode::kNone, we use |va_surface_ids| for
  // decode, otherwise ask |vaapi_wrapper_| to allocate them for us.
  if (buffer_allocation_mode_ == BufferAllocationMode::kNone) {
    DCHECK(!va_surface_ids.empty());
    RETURN_AND_NOTIFY_ON_FAILURE(
        vaapi_wrapper_->CreateContext(requested_pic_size_),
        "Failed creating VA Context", PLATFORM_FAILURE, );
    DCHECK_EQ(va_surface_ids.size(), buffers.size());

    va_surface_release_cb = base::DoNothing();
  } else {
    const size_t requested_num_surfaces =
        IsBufferAllocationModeReducedOrSuperReduced()
            ? requested_num_reference_frames_
            : pictures_.size();
    CHECK_NE(requested_num_surfaces, 0u);
    va_surface_ids.clear();

    RETURN_AND_NOTIFY_ON_FAILURE(
        vaapi_wrapper_->CreateContextAndSurfaces(
            va_surface_format_, requested_pic_size_,
            {VaapiWrapper::SurfaceUsageHint::kVideoDecoder},
            requested_num_surfaces, &va_surface_ids),
        "Failed creating VA Surfaces", PLATFORM_FAILURE, );

    va_surface_release_cb =
        base::BindRepeating(&VaapiWrapper::DestroySurface, vaapi_wrapper_);
  }

  for (const VASurfaceID va_surface_id : va_surface_ids) {
    available_va_surfaces_.emplace_back(std::make_unique<ScopedVASurfaceID>(
        va_surface_id, va_surface_release_cb));
  }

  // Resume DecodeTask if it is still in decoding state.
  if (state_ == kDecoding) {
    decoder_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&VaapiVideoDecodeAccelerator::DecodeTask,
                                  base::Unretained(this)));
  }
}

#if defined(USE_OZONE)
void VaapiVideoDecodeAccelerator::ImportBufferForPicture(
    int32_t picture_buffer_id,
    VideoPixelFormat pixel_format,
    gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) {
  VLOGF(2) << "Importing picture id: " << picture_buffer_id;
  DCHECK(task_runner_->BelongsToCurrentThread());

  if (output_mode_ != Config::OutputMode::IMPORT) {
    LOG(ERROR) << "Cannot import in non-import mode";
    NotifyError(INVALID_ARGUMENT);
    return;
  }

  {
    base::AutoLock auto_lock(lock_);
    if (!pictures_.count(picture_buffer_id)) {
      // It's possible that we've already posted a DismissPictureBuffer for this
      // picture, but it has not yet executed when this ImportBufferForPicture
      // was posted to us by the client. In that case just ignore this (we've
      // already dismissed it and accounted for that).
      DVLOGF(3) << "got picture id=" << picture_buffer_id
                << " not in use (anymore?).";
      return;
    }

    auto buffer_format = VideoPixelFormatToGfxBufferFormat(pixel_format);
    if (!buffer_format) {
      LOG(ERROR) << "Unsupported format: " << pixel_format;
      NotifyError(INVALID_ARGUMENT);
      return;
    }

    VaapiPicture* picture = pictures_[picture_buffer_id].get();
    if (!picture->ImportGpuMemoryBufferHandle(
            *buffer_format, std::move(gpu_memory_buffer_handle))) {
      // ImportGpuMemoryBufferHandle will close the handles even on failure, so
      // we don't need to do this ourselves.
      LOG(ERROR) << "Failed to import GpuMemoryBufferHandle";
      NotifyError(PLATFORM_FAILURE);
      return;
    }
  }

  ReusePictureBuffer(picture_buffer_id);
}
#endif

void VaapiVideoDecodeAccelerator::ReusePictureBuffer(
    int32_t picture_buffer_id) {
  DVLOGF(4) << "picture id=" << picture_buffer_id;
  DCHECK(task_runner_->BelongsToCurrentThread());
  TRACE_EVENT1("media,gpu", "VAVDA::ReusePictureBuffer", "Picture id",
               picture_buffer_id);

  {
    base::AutoLock auto_lock(lock_);

    if (!pictures_.count(picture_buffer_id)) {
      // It's possible that we've already posted a DismissPictureBuffer for this
      // picture, but it has not yet executed when this ReusePictureBuffer
      // was posted to us by the client. In that case just ignore this (we've
      // already dismissed it and accounted for that).
      DVLOGF(3) << "got picture id=" << picture_buffer_id
                << " not in use (anymore?).";
      return;
    }

    available_picture_buffers_.push_back(picture_buffer_id);
    TRACE_COUNTER_ID2("media,gpu", "Vaapi frames at client", this, "used",
                      pictures_.size() - available_picture_buffers_.size(),
                      "available", available_picture_buffers_.size());
  }

  TryOutputPicture();
}

void VaapiVideoDecodeAccelerator::FlushTask() {
  VLOGF(2);
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  DCHECK(curr_input_buffer_ && curr_input_buffer_->IsFlushRequest());

  curr_input_buffer_.reset();

  // First flush all the pictures that haven't been outputted, notifying the
  // client to output them.
  bool res = decoder_->Flush();
  RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.",
                               PLATFORM_FAILURE, );

  // Put the decoder in idle state, ready to resume.
  decoder_->Reset();

  task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_));
}

void VaapiVideoDecodeAccelerator::Flush() {
  VLOGF(2) << "Got flush request";
  DCHECK(task_runner_->BelongsToCurrentThread());

  QueueInputBuffer(DecoderBuffer::CreateEOSBuffer(), -1);
}

void VaapiVideoDecodeAccelerator::FinishFlush() {
  VLOGF(2);
  DCHECK(task_runner_->BelongsToCurrentThread());

  finish_flush_pending_ = false;

  base::AutoLock auto_lock(lock_);
  if (state_ != kDecoding) {
    DCHECK(state_ == kDestroying || state_ == kResetting) << state_;
    return;
  }

  // Still waiting for textures from client to finish outputting all pending
  // frames. Try again later.
  if (!pending_output_cbs_.empty()) {
    finish_flush_pending_ = true;
    return;
  }

  // Resume decoding if necessary.
  if (input_buffers_.empty()) {
    state_ = kIdle;
  } else {
    decoder_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&VaapiVideoDecodeAccelerator::DecodeTask,
                                  base::Unretained(this)));
  }

  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(&Client::NotifyFlushDone, client_));
}

void VaapiVideoDecodeAccelerator::ResetTask() {
  VLOGF(2);
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());

  // All the decoding tasks from before the reset request from client are done
  // by now, as this task was scheduled after them and client is expected not
  // to call Decode() after Reset() and before NotifyResetDone.
  decoder_->Reset();

  base::AutoLock auto_lock(lock_);

  // Return current input buffer, if present.
  if (curr_input_buffer_)
    ReturnCurrInputBuffer_Locked();

  // And let client know that we are done with reset.
  task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
}

void VaapiVideoDecodeAccelerator::Reset() {
  VLOGF(2) << "Got reset request";
  DCHECK(task_runner_->BelongsToCurrentThread());

  // This will make any new decode tasks exit early.
  base::AutoLock auto_lock(lock_);
  state_ = kResetting;
  finish_flush_pending_ = false;

  // Drop all remaining input buffers, if present.
  while (!input_buffers_.empty())
    input_buffers_.pop();
  TRACE_COUNTER1("media,gpu", "Vaapi input buffers", input_buffers_.size());

  decoder_thread_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&VaapiVideoDecodeAccelerator::ResetTask,
                                base::Unretained(this)));

  input_ready_.Signal();
  surfaces_available_.Signal();
}

void VaapiVideoDecodeAccelerator::FinishReset() {
  VLOGF(2);
  DCHECK(task_runner_->BelongsToCurrentThread());
  base::AutoLock auto_lock(lock_);

  if (state_ != kResetting) {
    DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_;
    return;  // We could've gotten destroyed already.
  }

  // Drop pending outputs.
  while (!pending_output_cbs_.empty())
    pending_output_cbs_.pop();

  if (awaiting_va_surfaces_recycle_) {
    // Decoder requested a new surface set while we were waiting for it to
    // finish the last DecodeTask, running at the time of Reset().
    // Let the surface set change finish first before resetting.
    task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
    return;
  }

  state_ = kIdle;

  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(&Client::NotifyResetDone, client_));

  // The client might have given us new buffers via Decode() while we were
  // resetting and might be waiting for our move, and not call Decode() anymore
  // until we return something. Post a DecodeTask() so that we won't
  // sleep forever waiting for Decode() in that case. Having two of them
  // in the pipe is harmless, the additional one will return as soon as it sees
  // that we are back in kDecoding state.
  if (!input_buffers_.empty()) {
    state_ = kDecoding;
    decoder_thread_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&VaapiVideoDecodeAccelerator::DecodeTask,
                                  base::Unretained(this)));
  }
}

void VaapiVideoDecodeAccelerator::Cleanup() {
  DCHECK(task_runner_->BelongsToCurrentThread());

  base::AutoLock auto_lock(lock_);
  if (state_ == kUninitialized || state_ == kDestroying)
    return;

  VLOGF(2) << "Destroying VAVDA";
  state_ = kDestroying;

  // Call DismissPictureBuffer() to notify |client_| that the picture buffers
  // are no longer used and thus |client_| shall release them. If |client_| has
  // been invalidated in NotifyError(),|client_| will be destroyed shortly. The
  // destruction should release all the PictureBuffers.
  if (client_) {
    for (const auto& id_and_picture : pictures_)
      client_->DismissPictureBuffer(id_and_picture.first);
  }
  pictures_.clear();

  client_ptr_factory_.reset();
  weak_this_factory_.InvalidateWeakPtrs();

  // TODO(mcasas): consider deleting |decoder_| on
  // |decoder_thread_task_runner_|, https://crbug.com/789160.

  // Signal all potential waiters on the decoder_thread_, let them early-exit,
  // as we've just moved to the kDestroying state, and wait for all tasks
  // to finish.
  input_ready_.Signal();
  surfaces_available_.Signal();
  {
    base::AutoUnlock auto_unlock(lock_);
    decoder_thread_.Stop();
  }
  if (buffer_allocation_mode_ != BufferAllocationMode::kNone)
    available_va_surfaces_.clear();

  // Notify |decoder_delegate_| of an imminent VAContextID destruction, so it
  // can destroy any internal structures making use of it. At this point
  // |decoder_thread_| is stopped so we can access |decoder_delegate_| from
  // |task_runner_|.
  decoder_delegate_->OnVAContextDestructionSoon();
  vaapi_wrapper_->DestroyContext();

  if (vpp_vaapi_wrapper_)
    vpp_vaapi_wrapper_->DestroyContext();
  state_ = kUninitialized;
}

void VaapiVideoDecodeAccelerator::Destroy() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  Cleanup();
  delete this;
}

bool VaapiVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
    const base::WeakPtr<Client>& decode_client,
    const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
  return false;
}

void VaapiVideoDecodeAccelerator::SurfaceReady(
    scoped_refptr<VASurface> dec_surface,
    int32_t bitstream_id,
    const gfx::Rect& visible_rect,
    const VideoColorSpace& color_space) {
  if (!task_runner_->BelongsToCurrentThread()) {
    task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&VaapiVideoDecodeAccelerator::SurfaceReady,
                                  weak_this_, std::move(dec_surface),
                                  bitstream_id, visible_rect, color_space));
    return;
  }

  DCHECK(!awaiting_va_surfaces_recycle_);

  {
    base::AutoLock auto_lock(lock_);
    // Drop any requests to output if we are resetting or being destroyed.
    if (state_ == kResetting || state_ == kDestroying)
      return;
  }
  pending_output_cbs_.push(base::BindOnce(
      &VaapiVideoDecodeAccelerator::OutputPicture, weak_this_,
      std::move(dec_surface), bitstream_id, visible_rect, color_space));

  TryOutputPicture();
}

scoped_refptr<VASurface> VaapiVideoDecodeAccelerator::CreateSurface() {
  DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
  base::AutoLock auto_lock(lock_);

  if (available_va_surfaces_.empty())
    return nullptr;

  DCHECK_NE(VA_INVALID_ID, va_surface_format_);
  DCHECK(!awaiting_va_surfaces_recycle_);
  if (buffer_allocation_mode_ != BufferAllocationMode::kNone) {
    auto va_surface_id = std::move(available_va_surfaces_.front());
    const VASurfaceID id = va_surface_id->id();
    available_va_surfaces_.pop_front();

    TRACE_COUNTER_ID2("media,gpu", "Vaapi VASurfaceIDs", this, "used",
                      (IsBufferAllocationModeReducedOrSuperReduced()
                           ? requested_num_reference_frames_
                           : pictures_.size()) -
                          available_va_surfaces_.size(),
                      "available", available_va_surfaces_.size());

    return new VASurface(
        id, requested_pic_size_, va_surface_format_,
        base::BindOnce(va_surface_recycle_cb_, std::move(va_surface_id)));
  }

  // Find the first |available_va_surfaces_| id such that the associated
  // |pictures_| entry is marked as |available_picture_buffers_|. In practice,
  // we will quickly find an available |va_surface_id|.
  for (auto it = available_va_surfaces_.begin();
       it != available_va_surfaces_.end(); ++it) {
    const VASurfaceID va_surface_id = (*it)->id();
    for (const auto& id_and_picture : pictures_) {
      if (id_and_picture.second->va_surface_id() == va_surface_id &&
          base::Contains(available_picture_buffers_, id_and_picture.first)) {
        // Remove |va_surface_id| from the list of availables, and use the id
        // to return a new VASurface.
        auto va_surface = std::move(*it);
        available_va_surfaces_.erase(it);
        return new VASurface(
            va_surface_id, requested_pic_size_, va_surface_format_,
            base::BindOnce(va_surface_recycle_cb_, std::move(va_surface)));
      }
    }
  }
  return nullptr;
}

void VaapiVideoDecodeAccelerator::RecycleVASurface(
    std::unique_ptr<ScopedVASurfaceID> va_surface,
    // We don't use |va_surface_id| but it must be here because this method is
    // bound as VASurface::ReleaseCB.
    VASurfaceID /*va_surface_id*/) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  {
    base::AutoLock auto_lock(lock_);
    available_va_surfaces_.push_back(std::move(va_surface));

    if (buffer_allocation_mode_ != BufferAllocationMode::kNone) {
      TRACE_COUNTER_ID2("media,gpu", "Vaapi VASurfaceIDs", this, "used",
                        (IsBufferAllocationModeReducedOrSuperReduced()
                             ? requested_num_reference_frames_
                             : pictures_.size()) -
                            available_va_surfaces_.size(),
                        "available", available_va_surfaces_.size());
    }
    surfaces_available_.Signal();
  }

  TryOutputPicture();
}

// static
VideoDecodeAccelerator::SupportedProfiles
VaapiVideoDecodeAccelerator::GetSupportedProfiles() {
  VideoDecodeAccelerator::SupportedProfiles profiles =
      VaapiWrapper::GetSupportedDecodeProfiles();
  // VaVDA never supported VP9 Profile 2, AV1 and HEVC, but VaapiWrapper does.
  // Filter them out.
  base::EraseIf(profiles, [](const auto& profile) {
    VideoCodec codec = VideoCodecProfileToVideoCodec(profile.profile);
    return profile.profile == VP9PROFILE_PROFILE2 ||
           codec == VideoCodec::kAV1 || codec == VideoCodec::kHEVC;
  });
  return profiles;
}

VaapiVideoDecodeAccelerator::BufferAllocationMode
VaapiVideoDecodeAccelerator::DecideBufferAllocationMode() {
#if BUILDFLAG(USE_VAAPI_X11)
  // The IMPORT mode is used for Android on Chrome OS, so this doesn't apply
  // here.
  DCHECK_NE(output_mode_, VideoDecodeAccelerator::Config::OutputMode::IMPORT);
  // TODO(crbug/1116701): get video decode acceleration working with ozone.
  // For H.264 on older devices, another +1 is experimentally needed for
  // high-to-high resolution changes.
  // TODO(mcasas): Figure out why and why only H264, see crbug.com/912295 and
  // http://crrev.com/c/1363807/9/media/gpu/h264_decoder.cc#1449.
  if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX)
    return BufferAllocationMode::kReduced;
  return BufferAllocationMode::kSuperReduced;
#else
  // TODO(crbug.com/912295): Enable a better BufferAllocationMode for IMPORT
  // |output_mode_| as well.
  if (output_mode_ == VideoDecodeAccelerator::Config::OutputMode::IMPORT)
    return BufferAllocationMode::kNormal;

  // On Gemini Lake, Kaby Lake and later we can pass to libva the client's
  // PictureBuffers to decode onto, which skips the use of the Vpp unit and its
  // associated format reconciliation copy, avoiding all internal buffer
  // allocations.
  // TODO(crbug.com/911754): Enable for VP9 Profile 2.
  if (IsGeminiLakeOrLater() &&
      (profile_ == VP9PROFILE_PROFILE0 || profile_ == VP8PROFILE_ANY ||
       (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX))) {
    // Add one to the reference frames for the one being currently egressed, and
    // an extra allocation for both |client_| and |decoder_|, see
    // crrev.com/c/1576560.
    if (profile_ == VP8PROFILE_ANY)
      num_extra_pics_ = 3;
    return BufferAllocationMode::kNone;
  }

  // For H.264 on older devices, another +1 is experimentally needed for
  // high-to-high resolution changes.
  // TODO(mcasas): Figure out why and why only H264, see crbug.com/912295 and
  // http://crrev.com/c/1363807/9/media/gpu/h264_decoder.cc#1449.
  if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX)
    return BufferAllocationMode::kReduced;

  // If we're here, we have to use the Vpp unit and allocate buffers for
  // |decoder_|; usually we'd have to allocate the |decoder_|s
  // GetRequiredNumOfPictures() internally, we can allocate just |decoder_|s
  // GetNumReferenceFrames() + 1. Moreover, we also request the |client_| to
  // allocate less than the usual |decoder_|s GetRequiredNumOfPictures().
  return BufferAllocationMode::kSuperReduced;
#endif
}

bool VaapiVideoDecodeAccelerator::IsBufferAllocationModeReducedOrSuperReduced()
    const {
  return buffer_allocation_mode_ == BufferAllocationMode::kSuperReduced ||
         buffer_allocation_mode_ == BufferAllocationMode::kReduced;
}

bool VaapiVideoDecodeAccelerator::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  using base::trace_event::MemoryAllocatorDump;
  base::AutoLock auto_lock(lock_);
  if (buffer_allocation_mode_ == BufferAllocationMode::kNone ||
      !requested_num_reference_frames_) {
    return false;
  }

  auto dump_name = base::StringPrintf("gpu/vaapi/decoder/0x%" PRIxPTR,
                                      reinterpret_cast<uintptr_t>(this));
  MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);

  constexpr float kNumBytesPerPixelYUV420 = 12.0 / 8;
  constexpr float kNumBytesPerPixelYUV420_10bpp = 2 * kNumBytesPerPixelYUV420;
  DCHECK(va_surface_format_ == VA_RT_FORMAT_YUV420 ||
         va_surface_format_ == VA_RT_FORMAT_YUV420_10BPP);
  const float va_surface_bytes_per_pixel =
      va_surface_format_ == VA_RT_FORMAT_YUV420 ? kNumBytesPerPixelYUV420
                                                : kNumBytesPerPixelYUV420_10bpp;
  // Report |requested_num_surfaces| and the associated memory size. The
  // calculated size is an estimation since we don't know the internal VA
  // strides, texture compression, headers, etc, but is a good lower boundary.
  const size_t requested_num_surfaces =
      IsBufferAllocationModeReducedOrSuperReduced()
          ? requested_num_reference_frames_
          : pictures_.size();
  dump->AddScalar(MemoryAllocatorDump::kNameSize,
                  MemoryAllocatorDump::kUnitsBytes,
                  static_cast<uint64_t>(requested_num_surfaces *
                                        requested_pic_size_.GetArea() *
                                        va_surface_bytes_per_pixel));
  dump->AddScalar(MemoryAllocatorDump::kNameObjectCount,
                  MemoryAllocatorDump::kUnitsObjects,
                  static_cast<uint64_t>(requested_num_surfaces));

  return true;
}

}  // namespace media
