blob: 89c87bff48104e35674e2dc2ff7886b66c7e722a [file] [log] [blame]
// 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/mojo/services/mojo_decryptor_service.h"
#include <utility>
#include "base/bind.h"
#include "base/numerics/safe_conversions.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/cdm_context.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decryptor.h"
#include "media/base/media_keys.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "media/mojo/common/media_type_converters.h"
#include "media/mojo/common/mojo_shared_buffer_video_frame.h"
#include "media/mojo/interfaces/demuxer_stream.mojom.h"
namespace media {
MojoDecryptorService::MojoDecryptorService(
const scoped_refptr<MediaKeys>& cdm,
mojo::InterfaceRequest<interfaces::Decryptor> request,
const mojo::Closure& error_handler)
: binding_(this, std::move(request)), cdm_(cdm), weak_factory_(this) {
DVLOG(1) << __FUNCTION__;
decryptor_ = cdm->GetCdmContext()->GetDecryptor();
DCHECK(decryptor_);
weak_this_ = weak_factory_.GetWeakPtr();
binding_.set_connection_error_handler(error_handler);
}
MojoDecryptorService::~MojoDecryptorService() {}
void MojoDecryptorService::Initialize(
mojo::ScopedDataPipeConsumerHandle receive_pipe,
mojo::ScopedDataPipeProducerHandle transmit_pipe) {
producer_handle_ = std::move(transmit_pipe);
consumer_handle_ = std::move(receive_pipe);
}
void MojoDecryptorService::Decrypt(interfaces::DemuxerStream::Type stream_type,
interfaces::DecoderBufferPtr encrypted,
const DecryptCallback& callback) {
DVLOG(3) << __FUNCTION__;
decryptor_->Decrypt(
static_cast<media::Decryptor::StreamType>(stream_type),
ReadDecoderBuffer(std::move(encrypted)),
base::Bind(&MojoDecryptorService::OnDecryptDone, weak_this_, callback));
}
void MojoDecryptorService::CancelDecrypt(
interfaces::DemuxerStream::Type stream_type) {
DVLOG(1) << __FUNCTION__;
decryptor_->CancelDecrypt(
static_cast<media::Decryptor::StreamType>(stream_type));
}
void MojoDecryptorService::InitializeAudioDecoder(
interfaces::AudioDecoderConfigPtr config,
const InitializeAudioDecoderCallback& callback) {
DVLOG(1) << __FUNCTION__;
decryptor_->InitializeAudioDecoder(
config.To<AudioDecoderConfig>(),
base::Bind(&MojoDecryptorService::OnAudioDecoderInitialized, weak_this_,
callback));
}
void MojoDecryptorService::InitializeVideoDecoder(
interfaces::VideoDecoderConfigPtr config,
const InitializeVideoDecoderCallback& callback) {
DVLOG(1) << __FUNCTION__;
decryptor_->InitializeVideoDecoder(
config.To<VideoDecoderConfig>(),
base::Bind(&MojoDecryptorService::OnVideoDecoderInitialized, weak_this_,
callback));
}
void MojoDecryptorService::DecryptAndDecodeAudio(
interfaces::DecoderBufferPtr encrypted,
const DecryptAndDecodeAudioCallback& callback) {
DVLOG(3) << __FUNCTION__;
decryptor_->DecryptAndDecodeAudio(
ReadDecoderBuffer(std::move(encrypted)),
base::Bind(&MojoDecryptorService::OnAudioDecoded, weak_this_, callback));
}
void MojoDecryptorService::DecryptAndDecodeVideo(
interfaces::DecoderBufferPtr encrypted,
const DecryptAndDecodeVideoCallback& callback) {
DVLOG(3) << __FUNCTION__;
decryptor_->DecryptAndDecodeVideo(
ReadDecoderBuffer(std::move(encrypted)),
base::Bind(&MojoDecryptorService::OnVideoDecoded, weak_this_, callback));
}
void MojoDecryptorService::ResetDecoder(
interfaces::DemuxerStream::Type stream_type) {
DVLOG(1) << __FUNCTION__;
decryptor_->ResetDecoder(
static_cast<media::Decryptor::StreamType>(stream_type));
}
void MojoDecryptorService::DeinitializeDecoder(
interfaces::DemuxerStream::Type stream_type) {
DVLOG(1) << __FUNCTION__;
decryptor_->DeinitializeDecoder(
static_cast<media::Decryptor::StreamType>(stream_type));
}
void MojoDecryptorService::ReleaseSharedBuffer(
mojo::ScopedSharedBufferHandle buffer,
uint64_t buffer_size) {
in_use_video_frames_.erase(buffer.get().value());
}
void MojoDecryptorService::OnDecryptDone(
const DecryptCallback& callback,
media::Decryptor::Status status,
const scoped_refptr<DecoderBuffer>& buffer) {
DVLOG_IF(1, status != media::Decryptor::kSuccess) << __FUNCTION__ << "("
<< status << ")";
DVLOG_IF(3, status == media::Decryptor::kSuccess) << __FUNCTION__;
if (!buffer) {
DCHECK_NE(status, media::Decryptor::kSuccess);
callback.Run(static_cast<Decryptor::Status>(status), nullptr);
return;
}
callback.Run(static_cast<Decryptor::Status>(status),
TransferDecoderBuffer(buffer));
}
void MojoDecryptorService::OnAudioDecoderInitialized(
const InitializeAudioDecoderCallback& callback,
bool success) {
DVLOG(1) << __FUNCTION__ << "(" << success << ")";
callback.Run(success);
}
void MojoDecryptorService::OnVideoDecoderInitialized(
const InitializeVideoDecoderCallback& callback,
bool success) {
DVLOG(1) << __FUNCTION__ << "(" << success << ")";
callback.Run(success);
}
void MojoDecryptorService::OnAudioDecoded(
const DecryptAndDecodeAudioCallback& callback,
media::Decryptor::Status status,
const media::Decryptor::AudioFrames& frames) {
DVLOG_IF(1, status != media::Decryptor::kSuccess) << __FUNCTION__ << "("
<< status << ")";
DVLOG_IF(3, status == media::Decryptor::kSuccess) << __FUNCTION__;
mojo::Array<interfaces::AudioBufferPtr> audio_buffers;
for (const auto& frame : frames)
audio_buffers.push_back(interfaces::AudioBuffer::From(frame));
callback.Run(static_cast<Decryptor::Status>(status),
std::move(audio_buffers));
}
void MojoDecryptorService::OnVideoDecoded(
const DecryptAndDecodeVideoCallback& callback,
media::Decryptor::Status status,
const scoped_refptr<VideoFrame>& frame) {
DVLOG_IF(1, status != media::Decryptor::kSuccess) << __FUNCTION__ << "("
<< status << ")";
DVLOG_IF(3, status == media::Decryptor::kSuccess) << __FUNCTION__;
if (!frame) {
DCHECK_NE(status, media::Decryptor::kSuccess);
callback.Run(static_cast<Decryptor::Status>(status), nullptr);
return;
}
// If |frame| has shared memory that will be passed back, keep a reference
// to it until the other side is done with the memory.
if (frame->storage_type() == VideoFrame::STORAGE_MOJO_SHARED_BUFFER) {
MojoSharedBufferVideoFrame* mojo_frame =
static_cast<MojoSharedBufferVideoFrame*>(frame.get());
in_use_video_frames_.insert(
std::make_pair(mojo_frame->Handle().value(), frame));
}
callback.Run(static_cast<Decryptor::Status>(status),
interfaces::VideoFrame::From(frame));
}
interfaces::DecoderBufferPtr MojoDecryptorService::TransferDecoderBuffer(
const scoped_refptr<DecoderBuffer>& encrypted) {
interfaces::DecoderBufferPtr buffer =
interfaces::DecoderBuffer::From(encrypted);
if (encrypted->end_of_stream())
return buffer;
// Serialize the data section of the DecoderBuffer into our pipe.
uint32_t bytes_to_write =
base::checked_cast<uint32_t>(encrypted->data_size());
DCHECK_GT(bytes_to_write, 0u);
uint32_t bytes_written = bytes_to_write;
CHECK_EQ(WriteDataRaw(producer_handle_.get(), encrypted->data(),
&bytes_written, MOJO_READ_DATA_FLAG_ALL_OR_NONE),
MOJO_RESULT_OK);
CHECK_EQ(bytes_to_write, bytes_written);
return buffer;
}
scoped_refptr<DecoderBuffer> MojoDecryptorService::ReadDecoderBuffer(
interfaces::DecoderBufferPtr buffer) {
scoped_refptr<DecoderBuffer> media_buffer(
buffer.To<scoped_refptr<DecoderBuffer>>());
if (media_buffer->end_of_stream())
return media_buffer;
// Wait for the data to become available in the DataPipe.
MojoHandleSignalsState state;
CHECK_EQ(MOJO_RESULT_OK,
MojoWait(consumer_handle_.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
MOJO_DEADLINE_INDEFINITE, &state));
CHECK_EQ(MOJO_HANDLE_SIGNAL_READABLE, state.satisfied_signals);
// Read the inner data for the DecoderBuffer from our DataPipe.
uint32_t bytes_to_read =
base::checked_cast<uint32_t>(media_buffer->data_size());
DCHECK_GT(bytes_to_read, 0u);
uint32_t bytes_read = bytes_to_read;
CHECK_EQ(ReadDataRaw(consumer_handle_.get(), media_buffer->writable_data(),
&bytes_read, MOJO_READ_DATA_FLAG_ALL_OR_NONE),
MOJO_RESULT_OK);
CHECK_EQ(bytes_to_read, bytes_read);
return media_buffer;
}
} // namespace media