// Copyright 2015 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/cdm/cdm_adapter.h"

#include <stddef.h>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/cdm_initialized_promise.h"
#include "media/base/cdm_key_information.h"
#include "media/base/channel_layout.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/base/limits.h"
#include "media/base/sample_format.h"
#include "media/base/video_codecs.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "media/cdm/cdm_allocator.h"
#include "media/cdm/cdm_file_io.h"
#include "media/cdm/cdm_helpers.h"
#include "media/cdm/cdm_wrapper.h"
#include "ui/gfx/geometry/rect.h"

namespace media {

namespace {

cdm::HdcpVersion ToCdmHdcpVersion(HdcpVersion hdcp_version) {
  switch (hdcp_version) {
    case media::HdcpVersion::kHdcpVersionNone:
      return cdm::kHdcpVersionNone;
    case media::HdcpVersion::kHdcpVersion1_0:
      return cdm::kHdcpVersion1_0;
    case media::HdcpVersion::kHdcpVersion1_1:
      return cdm::kHdcpVersion1_1;
    case media::HdcpVersion::kHdcpVersion1_2:
      return cdm::kHdcpVersion1_2;
    case media::HdcpVersion::kHdcpVersion1_3:
      return cdm::kHdcpVersion1_3;
    case media::HdcpVersion::kHdcpVersion1_4:
      return cdm::kHdcpVersion1_4;
    case media::HdcpVersion::kHdcpVersion2_0:
      return cdm::kHdcpVersion2_0;
    case media::HdcpVersion::kHdcpVersion2_1:
      return cdm::kHdcpVersion2_1;
    case media::HdcpVersion::kHdcpVersion2_2:
      return cdm::kHdcpVersion2_2;
  }

  NOTREACHED();
  return cdm::kHdcpVersion2_2;
}

cdm::SessionType ToCdmSessionType(CdmSessionType session_type) {
  switch (session_type) {
    case CdmSessionType::TEMPORARY_SESSION:
      return cdm::kTemporary;
    case CdmSessionType::PERSISTENT_LICENSE_SESSION:
      return cdm::kPersistentLicense;
    case CdmSessionType::PERSISTENT_RELEASE_MESSAGE_SESSION:
      return cdm::kPersistentKeyRelease;
  }

  NOTREACHED() << "Unexpected session type: " << static_cast<int>(session_type);
  return cdm::kTemporary;
}

cdm::InitDataType ToCdmInitDataType(EmeInitDataType init_data_type) {
  switch (init_data_type) {
    case EmeInitDataType::CENC:
      return cdm::kCenc;
    case EmeInitDataType::KEYIDS:
      return cdm::kKeyIds;
    case EmeInitDataType::WEBM:
      return cdm::kWebM;
    case EmeInitDataType::UNKNOWN:
      break;
  }

  NOTREACHED();
  return cdm::kKeyIds;
}

CdmPromise::Exception ToMediaExceptionType(cdm::Exception exception) {
  switch (exception) {
    case cdm::kExceptionTypeError:
      return CdmPromise::INVALID_ACCESS_ERROR;
    case cdm::kExceptionNotSupportedError:
      return CdmPromise::NOT_SUPPORTED_ERROR;
    case cdm::kExceptionInvalidStateError:
      return CdmPromise::INVALID_STATE_ERROR;
    case cdm::kExceptionQuotaExceededError:
      return CdmPromise::QUOTA_EXCEEDED_ERROR;
  }

  NOTREACHED() << "Unexpected cdm::Exception " << exception;
  return CdmPromise::INVALID_STATE_ERROR;
}

cdm::Exception ToCdmExceptionType(cdm::Error error) {
  switch (error) {
    case cdm::kNotSupportedError:
      return cdm::kExceptionNotSupportedError;
    case cdm::kInvalidStateError:
      return cdm::kExceptionTypeError;
    case cdm::kInvalidAccessError:
      return cdm::kExceptionInvalidStateError;
    case cdm::kQuotaExceededError:
      return cdm::kExceptionQuotaExceededError;
    case cdm::kUnknownError:
    case cdm::kClientError:
    case cdm::kOutputError:
      break;
  }

  NOTREACHED() << "Unexpected cdm::Error " << error;
  return cdm::kExceptionInvalidStateError;
}

CdmMessageType ToMediaMessageType(cdm::MessageType message_type) {
  switch (message_type) {
    case cdm::kLicenseRequest:
      return CdmMessageType::LICENSE_REQUEST;
    case cdm::kLicenseRenewal:
      return CdmMessageType::LICENSE_RENEWAL;
    case cdm::kLicenseRelease:
      return CdmMessageType::LICENSE_RELEASE;
  }

  NOTREACHED() << "Unexpected cdm::MessageType " << message_type;
  return CdmMessageType::LICENSE_REQUEST;
}

CdmKeyInformation::KeyStatus ToCdmKeyInformationKeyStatus(
    cdm::KeyStatus status) {
  switch (status) {
    case cdm::kUsable:
      return CdmKeyInformation::USABLE;
    case cdm::kInternalError:
      return CdmKeyInformation::INTERNAL_ERROR;
    case cdm::kExpired:
      return CdmKeyInformation::EXPIRED;
    case cdm::kOutputRestricted:
      return CdmKeyInformation::OUTPUT_RESTRICTED;
    case cdm::kOutputDownscaled:
      return CdmKeyInformation::OUTPUT_DOWNSCALED;
    case cdm::kStatusPending:
      return CdmKeyInformation::KEY_STATUS_PENDING;
    case cdm::kReleased:
      return CdmKeyInformation::RELEASED;
  }

  NOTREACHED() << "Unexpected cdm::KeyStatus " << status;
  return CdmKeyInformation::INTERNAL_ERROR;
}

cdm::AudioDecoderConfig::AudioCodec ToCdmAudioCodec(AudioCodec codec) {
  switch (codec) {
    case kCodecVorbis:
      return cdm::AudioDecoderConfig::kCodecVorbis;
    case kCodecAAC:
      return cdm::AudioDecoderConfig::kCodecAac;
    default:
      DVLOG(1) << "Unsupported AudioCodec " << codec;
      return cdm::AudioDecoderConfig::kUnknownAudioCodec;
  }
}

cdm::VideoDecoderConfig::VideoCodec ToCdmVideoCodec(VideoCodec codec) {
  switch (codec) {
    case kCodecVP8:
      return cdm::VideoDecoderConfig::kCodecVp8;
    case kCodecH264:
      return cdm::VideoDecoderConfig::kCodecH264;
    case kCodecVP9:
      return cdm::VideoDecoderConfig::kCodecVp9;
    default:
      DVLOG(1) << "Unsupported VideoCodec " << codec;
      return cdm::VideoDecoderConfig::kUnknownVideoCodec;
  }
}

cdm::VideoDecoderConfig::VideoCodecProfile ToCdmVideoCodecProfile(
    VideoCodecProfile profile) {
  switch (profile) {
    case VP8PROFILE_ANY:
    // TODO(servolk): See crbug.com/592074. We'll need to update this code to
    // handle different VP9 profiles properly after adding VP9 profiles in
    // media/cdm/api/content_decryption_module.h in a separate CL.
    // For now return kProfileNotNeeded to avoid breaking unit tests.
    case VP9PROFILE_PROFILE0:
    case VP9PROFILE_PROFILE1:
    case VP9PROFILE_PROFILE2:
    case VP9PROFILE_PROFILE3:
      return cdm::VideoDecoderConfig::kProfileNotNeeded;
    case H264PROFILE_BASELINE:
      return cdm::VideoDecoderConfig::kH264ProfileBaseline;
    case H264PROFILE_MAIN:
      return cdm::VideoDecoderConfig::kH264ProfileMain;
    case H264PROFILE_EXTENDED:
      return cdm::VideoDecoderConfig::kH264ProfileExtended;
    case H264PROFILE_HIGH:
      return cdm::VideoDecoderConfig::kH264ProfileHigh;
    case H264PROFILE_HIGH10PROFILE:
      return cdm::VideoDecoderConfig::kH264ProfileHigh10;
    case H264PROFILE_HIGH422PROFILE:
      return cdm::VideoDecoderConfig::kH264ProfileHigh422;
    case H264PROFILE_HIGH444PREDICTIVEPROFILE:
      return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
    default:
      DVLOG(1) << "Unsupported VideoCodecProfile " << profile;
      return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
  }
}

cdm::VideoFormat ToCdmVideoFormat(VideoPixelFormat format) {
  switch (format) {
    case PIXEL_FORMAT_YV12:
      return cdm::kYv12;
    case PIXEL_FORMAT_I420:
      return cdm::kI420;
    default:
      DVLOG(1) << "Unsupported VideoPixelFormat " << format;
      return cdm::kUnknownVideoFormat;
  }
}

cdm::StreamType ToCdmStreamType(Decryptor::StreamType stream_type) {
  switch (stream_type) {
    case Decryptor::kAudio:
      return cdm::kStreamTypeAudio;
    case Decryptor::kVideo:
      return cdm::kStreamTypeVideo;
  }

  NOTREACHED() << "Unexpected Decryptor::StreamType " << stream_type;
  return cdm::kStreamTypeVideo;
}

Decryptor::Status ToMediaDecryptorStatus(cdm::Status status) {
  switch (status) {
    case cdm::kSuccess:
      return Decryptor::kSuccess;
    case cdm::kNoKey:
      return Decryptor::kNoKey;
    case cdm::kNeedMoreData:
      return Decryptor::kNeedMoreData;
    case cdm::kDecryptError:
      return Decryptor::kError;
    case cdm::kDecodeError:
      return Decryptor::kError;
    case cdm::kInitializationError:
    case cdm::kDeferredInitialization:
      break;
  }

  NOTREACHED() << "Unexpected cdm::Status " << status;
  return Decryptor::kError;
}

SampleFormat ToMediaSampleFormat(cdm::AudioFormat format) {
  switch (format) {
    case cdm::kAudioFormatU8:
      return kSampleFormatU8;
    case cdm::kAudioFormatS16:
      return kSampleFormatS16;
    case cdm::kAudioFormatS32:
      return kSampleFormatS32;
    case cdm::kAudioFormatF32:
      return kSampleFormatF32;
    case cdm::kAudioFormatPlanarS16:
      return kSampleFormatPlanarS16;
    case cdm::kAudioFormatPlanarF32:
      return kSampleFormatPlanarF32;
    case cdm::kUnknownAudioFormat:
      return kUnknownSampleFormat;
  }

  NOTREACHED() << "Unexpected cdm::AudioFormat " << format;
  return kUnknownSampleFormat;
}

// Fill |input_buffer| based on the values in |encrypted|. |subsamples|
// is used to hold some of the data. |input_buffer| will contain pointers
// to data contained in |encrypted| and |subsamples|, so the lifetime of
// |input_buffer| must be <= the lifetime of |encrypted| and |subsamples|.
void ToCdmInputBuffer(const scoped_refptr<DecoderBuffer>& encrypted_buffer,
                      std::vector<cdm::SubsampleEntry>* subsamples,
                      cdm::InputBuffer* input_buffer) {
  // End of stream buffers are represented as empty resources.
  DCHECK(!input_buffer->data);
  if (encrypted_buffer->end_of_stream())
    return;

  input_buffer->data = encrypted_buffer->data();
  input_buffer->data_size = encrypted_buffer->data_size();
  input_buffer->timestamp = encrypted_buffer->timestamp().InMicroseconds();

  const DecryptConfig* decrypt_config = encrypted_buffer->decrypt_config();
  if (!decrypt_config) {
    DVLOG(2) << __func__ << ": Clear buffer.";
    return;
  }

  input_buffer->key_id =
      reinterpret_cast<const uint8_t*>(decrypt_config->key_id().data());
  input_buffer->key_id_size = decrypt_config->key_id().size();
  input_buffer->iv =
      reinterpret_cast<const uint8_t*>(decrypt_config->iv().data());
  input_buffer->iv_size = decrypt_config->iv().size();

  DCHECK(subsamples->empty());
  size_t num_subsamples = decrypt_config->subsamples().size();
  if (num_subsamples > 0) {
    subsamples->reserve(num_subsamples);
    for (const auto& sample : decrypt_config->subsamples()) {
      subsamples->push_back(
          cdm::SubsampleEntry(sample.clear_bytes, sample.cypher_bytes));
    }
  }

  input_buffer->subsamples = subsamples->data();
  input_buffer->num_subsamples = num_subsamples;
}

void* GetCdmHost(int host_interface_version, void* user_data) {
  if (!host_interface_version || !user_data)
    return nullptr;

  static_assert(
      cdm::ContentDecryptionModule::Host::kVersion == cdm::Host_9::kVersion,
      "update the code below");

  // Ensure IsSupportedCdmHostVersion matches implementation of this function.
  // Always update this DCHECK when updating this function.
  // If this check fails, update this function and DCHECK or update
  // IsSupportedCdmHostVersion.

  DCHECK(
      // Future version is not supported.
      !IsSupportedCdmHostVersion(cdm::Host_9::kVersion + 1) &&
      // Current version is supported.
      IsSupportedCdmHostVersion(cdm::Host_9::kVersion) &&
      // Include all previous supported versions (if any) here.
      IsSupportedCdmHostVersion(cdm::Host_8::kVersion) &&
      // One older than the oldest supported version is not supported.
      !IsSupportedCdmHostVersion(cdm::Host_8::kVersion - 1));
  DCHECK(IsSupportedCdmHostVersion(host_interface_version));

  CdmAdapter* cdm_adapter = static_cast<CdmAdapter*>(user_data);
  DVLOG(1) << "Create CDM Host with version " << host_interface_version;
  switch (host_interface_version) {
    case cdm::Host_8::kVersion:
      return static_cast<cdm::Host_8*>(cdm_adapter);
    case cdm::Host_9::kVersion:
      return static_cast<cdm::Host_9*>(cdm_adapter);
    default:
      NOTREACHED() << "Unexpected host interface version "
                   << host_interface_version;
      return nullptr;
  }
}

}  // namespace

// static
void CdmAdapter::Create(
    const std::string& key_system,
    const base::FilePath& cdm_path,
    const CdmConfig& cdm_config,
    std::unique_ptr<CdmAllocator> allocator,
    const CreateCdmFileIOCB& create_cdm_file_io_cb,
    const SessionMessageCB& session_message_cb,
    const SessionClosedCB& session_closed_cb,
    const SessionKeysChangeCB& session_keys_change_cb,
    const SessionExpirationUpdateCB& session_expiration_update_cb,
    const CdmCreatedCB& cdm_created_cb) {
  DCHECK(!key_system.empty());
  DCHECK(!session_message_cb.is_null());
  DCHECK(!session_closed_cb.is_null());
  DCHECK(!session_keys_change_cb.is_null());
  DCHECK(!session_expiration_update_cb.is_null());

  scoped_refptr<CdmAdapter> cdm = new CdmAdapter(
      key_system, cdm_config, std::move(allocator), create_cdm_file_io_cb,
      session_message_cb, session_closed_cb, session_keys_change_cb,
      session_expiration_update_cb);

  // |cdm| ownership passed to the promise.
  std::unique_ptr<CdmInitializedPromise> cdm_created_promise(
      new CdmInitializedPromise(cdm_created_cb, cdm));

  cdm->Initialize(cdm_path, std::move(cdm_created_promise));
}

CdmAdapter::CdmAdapter(
    const std::string& key_system,
    const CdmConfig& cdm_config,
    std::unique_ptr<CdmAllocator> allocator,
    const CreateCdmFileIOCB& create_cdm_file_io_cb,
    const SessionMessageCB& session_message_cb,
    const SessionClosedCB& session_closed_cb,
    const SessionKeysChangeCB& session_keys_change_cb,
    const SessionExpirationUpdateCB& session_expiration_update_cb)
    : key_system_(key_system),
      cdm_config_(cdm_config),
      session_message_cb_(session_message_cb),
      session_closed_cb_(session_closed_cb),
      session_keys_change_cb_(session_keys_change_cb),
      session_expiration_update_cb_(session_expiration_update_cb),
      audio_samples_per_second_(0),
      audio_channel_layout_(CHANNEL_LAYOUT_NONE),
      allocator_(std::move(allocator)),
      create_cdm_file_io_cb_(create_cdm_file_io_cb),
      task_runner_(base::ThreadTaskRunnerHandle::Get()),
      pool_(new AudioBufferMemoryPool()),
      weak_factory_(this) {
  DCHECK(!key_system_.empty());
  DCHECK(!session_message_cb_.is_null());
  DCHECK(!session_closed_cb_.is_null());
  DCHECK(!session_keys_change_cb_.is_null());
  DCHECK(!session_expiration_update_cb_.is_null());
  DCHECK(allocator_);
}

CdmAdapter::~CdmAdapter() {}

CdmWrapper* CdmAdapter::CreateCdmInstance(const std::string& key_system,
                                          const base::FilePath& cdm_path) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  // TODO(jrummell): We need to call INITIALIZE_CDM_MODULE() and
  // DeinitializeCdmModule(). However, that should only be done once for the
  // library.
  base::NativeLibraryLoadError error;
  library_.Reset(base::LoadNativeLibrary(cdm_path, &error));
  if (!library_.is_valid()) {
    DVLOG(1) << "CDM instance for " + key_system + " could not be created. "
             << error.ToString();
    return nullptr;
  }

  CreateCdmFunc create_cdm_func = reinterpret_cast<CreateCdmFunc>(
      library_.GetFunctionPointer("CreateCdmInstance"));
  if (!create_cdm_func) {
    DVLOG(1) << "No CreateCdmInstance() in library for " + key_system;
    return nullptr;
  }

  CdmWrapper* cdm = CdmWrapper::Create(create_cdm_func, key_system.data(),
                                       key_system.size(), GetCdmHost, this);

  DVLOG(1) << "CDM instance for " + key_system + (cdm ? "" : " could not be") +
                  " created.";
  return cdm;
}

void CdmAdapter::Initialize(const base::FilePath& cdm_path,
                            std::unique_ptr<media::SimpleCdmPromise> promise) {
  cdm_.reset(CreateCdmInstance(key_system_, cdm_path));
  if (!cdm_) {
    promise->reject(CdmPromise::INVALID_ACCESS_ERROR, 0,
                    "Unable to create CDM.");
    return;
  }

  cdm_->Initialize(cdm_config_.allow_distinctive_identifier,
                   cdm_config_.allow_persistent_state);
  promise->resolve();
}

void CdmAdapter::SetServerCertificate(
    const std::vector<uint8_t>& certificate,
    std::unique_ptr<SimpleCdmPromise> promise) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  if (certificate.size() < limits::kMinCertificateLength ||
      certificate.size() > limits::kMaxCertificateLength) {
    promise->reject(CdmPromise::INVALID_ACCESS_ERROR, 0,
                    "Incorrect certificate.");
    return;
  }

  uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
  cdm_->SetServerCertificate(promise_id, certificate.data(),
                             certificate.size());
}

void CdmAdapter::GetStatusForPolicy(
    HdcpVersion min_hdcp_version,
    std::unique_ptr<KeyStatusCdmPromise> promise) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
  cdm_->GetStatusForPolicy(promise_id, ToCdmHdcpVersion(min_hdcp_version));
}

void CdmAdapter::CreateSessionAndGenerateRequest(
    CdmSessionType session_type,
    EmeInitDataType init_data_type,
    const std::vector<uint8_t>& init_data,
    std::unique_ptr<NewSessionCdmPromise> promise) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
  cdm_->CreateSessionAndGenerateRequest(
      promise_id, ToCdmSessionType(session_type),
      ToCdmInitDataType(init_data_type), init_data.data(), init_data.size());
}

void CdmAdapter::LoadSession(CdmSessionType session_type,
                             const std::string& session_id,
                             std::unique_ptr<NewSessionCdmPromise> promise) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
  cdm_->LoadSession(promise_id, ToCdmSessionType(session_type),
                    session_id.data(), session_id.size());
}

void CdmAdapter::UpdateSession(const std::string& session_id,
                               const std::vector<uint8_t>& response,
                               std::unique_ptr<SimpleCdmPromise> promise) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DCHECK(!session_id.empty());
  DCHECK(!response.empty());

  uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
  cdm_->UpdateSession(promise_id, session_id.data(), session_id.size(),
                      response.data(), response.size());
}

void CdmAdapter::CloseSession(const std::string& session_id,
                              std::unique_ptr<SimpleCdmPromise> promise) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DCHECK(!session_id.empty());

  uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
  cdm_->CloseSession(promise_id, session_id.data(), session_id.size());
}

void CdmAdapter::RemoveSession(const std::string& session_id,
                               std::unique_ptr<SimpleCdmPromise> promise) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DCHECK(!session_id.empty());

  uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
  cdm_->RemoveSession(promise_id, session_id.data(), session_id.size());
}

CdmContext* CdmAdapter::GetCdmContext() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  return this;
}

Decryptor* CdmAdapter::GetDecryptor() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  return this;
}

int CdmAdapter::GetCdmId() const {
  DCHECK(task_runner_->BelongsToCurrentThread());
  return kInvalidCdmId;
}

void CdmAdapter::RegisterNewKeyCB(StreamType stream_type,
                                  const NewKeyCB& key_added_cb) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  switch (stream_type) {
    case kAudio:
      new_audio_key_cb_ = key_added_cb;
      return;
    case kVideo:
      new_video_key_cb_ = key_added_cb;
      return;
  }

  NOTREACHED() << "Unexpected StreamType " << stream_type;
}

void CdmAdapter::Decrypt(StreamType stream_type,
                         const scoped_refptr<DecoderBuffer>& encrypted,
                         const DecryptCB& decrypt_cb) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  cdm::InputBuffer input_buffer;
  std::vector<cdm::SubsampleEntry> subsamples;
  std::unique_ptr<DecryptedBlockImpl> decrypted_block(new DecryptedBlockImpl());

  ToCdmInputBuffer(encrypted, &subsamples, &input_buffer);
  cdm::Status status = cdm_->Decrypt(input_buffer, decrypted_block.get());

  if (status != cdm::kSuccess) {
    DVLOG(1) << __func__ << " failed with cdm::Error " << status;
    decrypt_cb.Run(ToMediaDecryptorStatus(status), nullptr);
    return;
  }

  scoped_refptr<DecoderBuffer> decrypted_buffer(
      DecoderBuffer::CopyFrom(decrypted_block->DecryptedBuffer()->Data(),
                              decrypted_block->DecryptedBuffer()->Size()));
  decrypted_buffer->set_timestamp(
      base::TimeDelta::FromMicroseconds(decrypted_block->Timestamp()));
  decrypt_cb.Run(Decryptor::kSuccess, decrypted_buffer);
}

void CdmAdapter::CancelDecrypt(StreamType stream_type) {
  // As the Decrypt methods are synchronous, nothing can be done here.
  DCHECK(task_runner_->BelongsToCurrentThread());
}

void CdmAdapter::InitializeAudioDecoder(const AudioDecoderConfig& config,
                                        const DecoderInitCB& init_cb) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DCHECK(audio_init_cb_.is_null());

  cdm::AudioDecoderConfig cdm_decoder_config;
  cdm_decoder_config.codec = ToCdmAudioCodec(config.codec());
  cdm_decoder_config.channel_count =
      ChannelLayoutToChannelCount(config.channel_layout());
  cdm_decoder_config.bits_per_channel = config.bits_per_channel();
  cdm_decoder_config.samples_per_second = config.samples_per_second();
  cdm_decoder_config.extra_data =
      const_cast<uint8_t*>(config.extra_data().data());
  cdm_decoder_config.extra_data_size = config.extra_data().size();

  cdm::Status status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
  if (status != cdm::kSuccess && status != cdm::kDeferredInitialization) {
    // DCHECK(status == cdm::kSessionError); http://crbug.com/570486
    DVLOG(1) << __func__ << " failed with cdm::Error " << status;
    init_cb.Run(false);
    return;
  }

  audio_samples_per_second_ = config.samples_per_second();
  audio_channel_layout_ = config.channel_layout();

  if (status == cdm::kDeferredInitialization) {
    DVLOG(1) << "Deferred initialization in " << __func__;
    audio_init_cb_ = init_cb;
    return;
  }

  init_cb.Run(true);
}

void CdmAdapter::InitializeVideoDecoder(const VideoDecoderConfig& config,
                                        const DecoderInitCB& init_cb) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DCHECK(video_init_cb_.is_null());

  cdm::VideoDecoderConfig cdm_decoder_config;
  cdm_decoder_config.codec = ToCdmVideoCodec(config.codec());
  cdm_decoder_config.profile = ToCdmVideoCodecProfile(config.profile());
  cdm_decoder_config.format = ToCdmVideoFormat(config.format());
  cdm_decoder_config.coded_size.width = config.coded_size().width();
  cdm_decoder_config.coded_size.height = config.coded_size().height();
  cdm_decoder_config.extra_data =
      const_cast<uint8_t*>(config.extra_data().data());
  cdm_decoder_config.extra_data_size = config.extra_data().size();

  cdm::Status status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
  if (status != cdm::kSuccess && status != cdm::kDeferredInitialization) {
    // DCHECK(status == cdm::kSessionError); http://crbug.com/570486
    DVLOG(1) << __func__ << " failed with cdm::Error " << status;
    init_cb.Run(false);
    return;
  }

  natural_size_ = config.natural_size();

  if (status == cdm::kDeferredInitialization) {
    DVLOG(1) << "Deferred initialization in " << __func__;
    video_init_cb_ = init_cb;
    return;
  }

  init_cb.Run(true);
}

void CdmAdapter::DecryptAndDecodeAudio(
    const scoped_refptr<DecoderBuffer>& encrypted,
    const AudioDecodeCB& audio_decode_cb) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  cdm::InputBuffer input_buffer;
  std::vector<cdm::SubsampleEntry> subsamples;
  std::unique_ptr<AudioFramesImpl> audio_frames(new AudioFramesImpl());

  ToCdmInputBuffer(encrypted, &subsamples, &input_buffer);
  cdm::Status status =
      cdm_->DecryptAndDecodeSamples(input_buffer, audio_frames.get());

  const Decryptor::AudioFrames empty_frames;
  if (status != cdm::kSuccess) {
    DVLOG(1) << __func__ << " failed with cdm::Error " << status;
    audio_decode_cb.Run(ToMediaDecryptorStatus(status), empty_frames);
    return;
  }

  Decryptor::AudioFrames audio_frame_list;
  DCHECK(audio_frames->FrameBuffer());
  if (!AudioFramesDataToAudioFrames(std::move(audio_frames),
                                    &audio_frame_list)) {
    DVLOG(1) << __func__ << " unable to convert Audio Frames";
    audio_decode_cb.Run(Decryptor::kError, empty_frames);
    return;
  }

  audio_decode_cb.Run(Decryptor::kSuccess, audio_frame_list);
}

void CdmAdapter::DecryptAndDecodeVideo(
    const scoped_refptr<DecoderBuffer>& encrypted,
    const VideoDecodeCB& video_decode_cb) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DVLOG(3) << __func__ << " encrypted: " << encrypted->AsHumanReadableString();

  cdm::InputBuffer input_buffer;
  std::vector<cdm::SubsampleEntry> subsamples;
  std::unique_ptr<VideoFrameImpl> video_frame =
      allocator_->CreateCdmVideoFrame();

  ToCdmInputBuffer(encrypted, &subsamples, &input_buffer);
  cdm::Status status =
      cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get());

  if (status != cdm::kSuccess) {
    DVLOG(1) << __func__ << " failed with cdm::Error " << status;
    video_decode_cb.Run(ToMediaDecryptorStatus(status), nullptr);
    return;
  }

  scoped_refptr<VideoFrame> decoded_frame =
      video_frame->TransformToVideoFrame(natural_size_);
  video_decode_cb.Run(Decryptor::kSuccess, decoded_frame);
}

void CdmAdapter::ResetDecoder(StreamType stream_type) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  cdm_->ResetDecoder(ToCdmStreamType(stream_type));
}

void CdmAdapter::DeinitializeDecoder(StreamType stream_type) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  cdm_->DeinitializeDecoder(ToCdmStreamType(stream_type));

  // Reset the saved values from initializing the decoder.
  switch (stream_type) {
    case Decryptor::kAudio:
      audio_samples_per_second_ = 0;
      audio_channel_layout_ = CHANNEL_LAYOUT_NONE;
      break;
    case Decryptor::kVideo:
      natural_size_ = gfx::Size();
      break;
  }
}

cdm::Buffer* CdmAdapter::Allocate(uint32_t capacity) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  return allocator_->CreateCdmBuffer(capacity);
}

void CdmAdapter::SetTimer(int64_t delay_ms, void* context) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  task_runner_->PostDelayedTask(FROM_HERE,
                                base::Bind(&CdmAdapter::TimerExpired,
                                           weak_factory_.GetWeakPtr(), context),
                                base::TimeDelta::FromMilliseconds(delay_ms));
}

void CdmAdapter::TimerExpired(void* context) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  cdm_->TimerExpired(context);
}

cdm::Time CdmAdapter::GetCurrentWallTime() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  return base::Time::Now().ToDoubleT();
}

void CdmAdapter::OnResolveKeyStatusPromise(uint32_t promise_id,
                                           cdm::KeyStatus key_status) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  cdm_promise_adapter_.ResolvePromise(promise_id,
                                      ToCdmKeyInformationKeyStatus(key_status));
}

void CdmAdapter::OnResolvePromise(uint32_t promise_id) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  cdm_promise_adapter_.ResolvePromise(promise_id);
}

void CdmAdapter::OnResolveNewSessionPromise(uint32_t promise_id,
                                            const char* session_id,
                                            uint32_t session_id_size) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  cdm_promise_adapter_.ResolvePromise(promise_id,
                                      std::string(session_id, session_id_size));
}

void CdmAdapter::OnRejectPromise(uint32_t promise_id,
                                 cdm::Exception exception,
                                 uint32_t system_code,
                                 const char* error_message,
                                 uint32_t error_message_size) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  cdm_promise_adapter_.RejectPromise(
      promise_id, ToMediaExceptionType(exception), system_code,
      std::string(error_message, error_message_size));
}

void CdmAdapter::OnRejectPromise(uint32_t promise_id,
                                 cdm::Error error,
                                 uint32_t system_code,
                                 const char* error_message,
                                 uint32_t error_message_size) {
  // cdm::Host_8 version. Remove when CDM_8 no longer supported.
  // https://crbug.com/737296.
  OnRejectPromise(promise_id, ToCdmExceptionType(error), system_code,
                  error_message, error_message_size);
}

void CdmAdapter::OnSessionMessage(const char* session_id,
                                  uint32_t session_id_size,
                                  cdm::MessageType message_type,
                                  const char* message,
                                  uint32_t message_size) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(message);
  session_message_cb_.Run(
      std::string(session_id, session_id_size),
      ToMediaMessageType(message_type),
      std::vector<uint8_t>(message_ptr, message_ptr + message_size));
}

void CdmAdapter::OnSessionMessage(const char* session_id,
                                  uint32_t session_id_size,
                                  cdm::MessageType message_type,
                                  const char* message,
                                  uint32_t message_size,
                                  const char* /* legacy_destination_url */,
                                  uint32_t /* legacy_destination_url_size */) {
  // cdm::Host_8 version. Remove when CDM_8 no longer supported.
  // https://crbug.com/737296.
  OnSessionMessage(session_id, session_id_size, message_type, message,
                   message_size);
}

void CdmAdapter::OnSessionKeysChange(const char* session_id,
                                     uint32_t session_id_size,
                                     bool has_additional_usable_key,
                                     const cdm::KeyInformation* keys_info,
                                     uint32_t keys_info_count) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  CdmKeysInfo keys;
  keys.reserve(keys_info_count);
  for (uint32_t i = 0; i < keys_info_count; ++i) {
    const auto& info = keys_info[i];
    keys.push_back(base::MakeUnique<CdmKeyInformation>(
        info.key_id, info.key_id_size,
        ToCdmKeyInformationKeyStatus(info.status), info.system_code));
  }

  // TODO(jrummell): Handling resume playback should be done in the media
  // player, not in the Decryptors. http://crbug.com/413413.
  if (has_additional_usable_key) {
    if (!new_audio_key_cb_.is_null())
      new_audio_key_cb_.Run();
    if (!new_video_key_cb_.is_null())
      new_video_key_cb_.Run();
  }

  session_keys_change_cb_.Run(std::string(session_id, session_id_size),
                              has_additional_usable_key, std::move(keys));
}

void CdmAdapter::OnExpirationChange(const char* session_id,
                                    uint32_t session_id_size,
                                    cdm::Time new_expiry_time) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  session_expiration_update_cb_.Run(std::string(session_id, session_id_size),
                                    base::Time::FromDoubleT(new_expiry_time));
}

void CdmAdapter::OnSessionClosed(const char* session_id,
                                 uint32_t session_id_size) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  session_closed_cb_.Run(std::string(session_id, session_id_size));
}

void CdmAdapter::OnLegacySessionError(const char* session_id,
                                      uint32_t session_id_size,
                                      cdm::Error error,
                                      uint32_t system_code,
                                      const char* error_message,
                                      uint32_t error_message_size) {
  // cdm::Host_8 version. Remove when CDM_8 no longer supported.
  // https://crbug.com/737296.
  DCHECK(task_runner_->BelongsToCurrentThread());
}

void CdmAdapter::SendPlatformChallenge(const char* service_id,
                                       uint32_t service_id_size,
                                       const char* challenge,
                                       uint32_t challenge_size) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  // TODO(jrummell): If platform verification is available, use it.
  NOTIMPLEMENTED();
  cdm::PlatformChallengeResponse platform_challenge_response = {};
  cdm_->OnPlatformChallengeResponse(platform_challenge_response);
}

void CdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  // TODO(jrummell): If output protection is available, use it.
  NOTIMPLEMENTED();
}

void CdmAdapter::QueryOutputProtectionStatus() {
  DCHECK(task_runner_->BelongsToCurrentThread());

  // TODO(jrummell): If output protection is available, use it.
  NOTIMPLEMENTED();
  cdm_->OnQueryOutputProtectionStatus(cdm::kQueryFailed, 0, 0);
}

void CdmAdapter::OnDeferredInitializationDone(cdm::StreamType stream_type,
                                              cdm::Status decoder_status) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DVLOG_IF(1, decoder_status != cdm::kSuccess)
      << __func__ << " failed with cdm::Error " << decoder_status;

  switch (stream_type) {
    case cdm::kStreamTypeAudio:
      base::ResetAndReturn(&audio_init_cb_)
          .Run(decoder_status == cdm::kSuccess);
      return;
    case cdm::kStreamTypeVideo:
      base::ResetAndReturn(&video_init_cb_)
          .Run(decoder_status == cdm::kSuccess);
      return;
  }

  NOTREACHED() << "Unexpected cdm::StreamType " << stream_type;
}

cdm::FileIO* CdmAdapter::CreateFileIO(cdm::FileIOClient* client) {
  DCHECK(task_runner_->BelongsToCurrentThread());

  std::unique_ptr<CdmFileIO> file_io = create_cdm_file_io_cb_.Run(client);

  // The CDM owns the returned object and must call FileIO::Close()
  // to release it.
  return file_io.release();
}

void CdmAdapter::RequestStorageId() {
  // TODO(jrummell): Implement Storage Id. https://crbug.com/478960.
  NOTIMPLEMENTED();
  cdm_->OnStorageId(nullptr, 0);
}

bool CdmAdapter::AudioFramesDataToAudioFrames(
    std::unique_ptr<AudioFramesImpl> audio_frames,
    Decryptor::AudioFrames* result_frames) {
  const uint8_t* data = audio_frames->FrameBuffer()->Data();
  const size_t data_size = audio_frames->FrameBuffer()->Size();
  size_t bytes_left = data_size;
  const SampleFormat sample_format =
      ToMediaSampleFormat(audio_frames->Format());
  const int audio_channel_count =
      ChannelLayoutToChannelCount(audio_channel_layout_);
  const int audio_bytes_per_frame =
      SampleFormatToBytesPerChannel(sample_format) * audio_channel_count;
  if (audio_bytes_per_frame <= 0)
    return false;

  // Allocate space for the channel pointers given to AudioBuffer.
  std::vector<const uint8_t*> channel_ptrs(audio_channel_count, nullptr);
  do {
    // AudioFrames can contain multiple audio output buffers, which are
    // serialized into this format:
    // |<------------------- serialized audio buffer ------------------->|
    // | int64_t timestamp | int64_t length | length bytes of audio data |
    int64_t timestamp = 0;
    int64_t frame_size = -1;
    const size_t kHeaderSize = sizeof(timestamp) + sizeof(frame_size);
    if (bytes_left < kHeaderSize)
      return false;

    memcpy(&timestamp, data, sizeof(timestamp));
    memcpy(&frame_size, data + sizeof(timestamp), sizeof(frame_size));
    data += kHeaderSize;
    bytes_left -= kHeaderSize;

    // We should *not* have empty frames in the list.
    if (frame_size <= 0 ||
        bytes_left < base::checked_cast<size_t>(frame_size)) {
      return false;
    }

    // Setup channel pointers.  AudioBuffer::CopyFrom() will only use the first
    // one in the case of interleaved data.
    const int size_per_channel = frame_size / audio_channel_count;
    for (int i = 0; i < audio_channel_count; ++i)
      channel_ptrs[i] = data + i * size_per_channel;

    const int frame_count = frame_size / audio_bytes_per_frame;
    scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom(
        sample_format, audio_channel_layout_, audio_channel_count,
        audio_samples_per_second_, frame_count, &channel_ptrs[0],
        base::TimeDelta::FromMicroseconds(timestamp), pool_);
    result_frames->push_back(frame);

    data += frame_size;
    bytes_left -= frame_size;
  } while (bytes_left > 0);

  return true;
}

}  // namespace media
