chromium/chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chromeos/components/cdm_factory_daemon/stable_cdm_context_impl.h"

#include "base/functional/callback.h"
#include "base/task/bind_post_task.h"
#include "chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h"
#include "chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.h"

namespace chromeos {

StableCdmContextImpl::StableCdmContextImpl(media::CdmContext* cdm_context)
    : cdm_context_(cdm_context) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(cdm_context_);
  DCHECK(cdm_context_->GetChromeOsCdmContext());
  cdm_context_ref_ = cdm_context_->GetChromeOsCdmContext()->GetCdmContextRef();
}

StableCdmContextImpl::~StableCdmContextImpl() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

void StableCdmContextImpl::GetHwKeyData(
    std::unique_ptr<media::DecryptConfig> decrypt_config,
    const std::vector<uint8_t>& hw_identifier,
    GetHwKeyDataCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  cdm_context_->GetChromeOsCdmContext()->GetHwKeyData(
      decrypt_config.get(), hw_identifier,
      base::BindPostTaskToCurrentDefault(std::move(callback)));
}

void StableCdmContextImpl::RegisterEventCallback(
    mojo::PendingRemote<media::stable::mojom::CdmContextEventCallback>
        callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Note: we don't need to use base::BindPostTaskToCurrentDefault() for either
  // |callback| or the callback we pass to RegisterEventCB() because the
  // documentation for media::CdmContext::RegisterEventCB() says that "[t]he
  // registered callback will always be called on the thread where
  // RegisterEventCB() is called."
  remote_event_callbacks_.Add(std::move(callback));
  if (!callback_registration_) {
    callback_registration_ = cdm_context_->RegisterEventCB(
        base::BindRepeating(&StableCdmContextImpl::CdmEventCallback,
                            weak_ptr_factory_.GetWeakPtr()));
  }
}

void StableCdmContextImpl::GetHwConfigData(GetHwConfigDataCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  ChromeOsCdmFactory::GetHwConfigData(
      base::BindPostTaskToCurrentDefault(std::move(callback)));
}

void StableCdmContextImpl::GetScreenResolutions(
    GetScreenResolutionsCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  ChromeOsCdmFactory::GetScreenResolutions(
      base::BindPostTaskToCurrentDefault(std::move(callback)));
}

void StableCdmContextImpl::AllocateSecureBuffer(
    uint32_t size,
    AllocateSecureBufferCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  ChromeOsCdmFactory::AllocateSecureBuffer(
      size, base::BindPostTaskToCurrentDefault(std::move(callback)));
}

void StableCdmContextImpl::ParseEncryptedSliceHeader(
    uint64_t secure_handle,
    uint32_t offset,
    const std::vector<uint8_t>& stream_data,
    ParseEncryptedSliceHeaderCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  ChromeOsCdmFactory::ParseEncryptedSliceHeader(
      secure_handle, offset, stream_data,
      base::BindPostTaskToCurrentDefault(std::move(callback)));
}

void StableCdmContextImpl::DecryptVideoBuffer(
    const scoped_refptr<media::DecoderBuffer>& decoder_buffer,
    const std::vector<uint8_t>& bytes,
    DecryptVideoBufferCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK(cdm_context_->GetDecryptor());
  CHECK_EQ(decoder_buffer->size(), bytes.size());
  memcpy(decoder_buffer->writable_data(), bytes.data(), bytes.size());
  cdm_context_->GetDecryptor()->Decrypt(
      media::Decryptor::StreamType::kVideo, decoder_buffer,
      base::BindPostTaskToCurrentDefault(
          base::BindOnce(&StableCdmContextImpl::OnDecryptDone,
                         weak_ptr_factory_.GetWeakPtr(), std::move(callback))));
}

void StableCdmContextImpl::CdmEventCallback(media::CdmContext::Event event) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  for (auto& cb : remote_event_callbacks_)
    cb->EventCallback(event);
}

void StableCdmContextImpl::OnDecryptDone(
    DecryptVideoBufferCallback decrypt_video_buffer_cb,
    media::Decryptor::Status status,
    scoped_refptr<media::DecoderBuffer> decoder_buffer) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  std::vector<uint8_t> bytes;
  if (decoder_buffer) {
    bytes.insert(bytes.begin(), decoder_buffer->data(),
                 decoder_buffer->data() + decoder_buffer->size());
  }
  std::move(decrypt_video_buffer_cb).Run(status, decoder_buffer, bytes);
}

}  // namespace chromeos