blob: 012d818c5bc05359c046e54e4ce4aadf0cea8cfb [file] [log] [blame]
// Copyright 2014 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/common/media_type_converters.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "media/base/audio_buffer.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/base/subsample_entry.h"
#include "mojo/public/cpp/system/buffer.h"
namespace mojo {
// TODO(crbug.com/611224): Stop using TypeConverters.
// static
media::mojom::DecryptConfigPtr
TypeConverter<media::mojom::DecryptConfigPtr, media::DecryptConfig>::Convert(
const media::DecryptConfig& input) {
media::mojom::DecryptConfigPtr mojo_decrypt_config(
media::mojom::DecryptConfig::New());
mojo_decrypt_config->key_id = input.key_id();
mojo_decrypt_config->iv = input.iv();
mojo_decrypt_config->subsamples = input.subsamples();
mojo_decrypt_config->encryption_mode = input.encryption_mode();
mojo_decrypt_config->encryption_pattern = input.encryption_pattern();
return mojo_decrypt_config;
}
// static
std::unique_ptr<media::DecryptConfig>
TypeConverter<std::unique_ptr<media::DecryptConfig>,
media::mojom::DecryptConfigPtr>::
Convert(const media::mojom::DecryptConfigPtr& input) {
return std::make_unique<media::DecryptConfig>(
input->encryption_mode, input->key_id, input->iv, input->subsamples,
input->encryption_pattern);
}
// static
media::mojom::DecoderBufferPtr
TypeConverter<media::mojom::DecoderBufferPtr, media::DecoderBuffer>::Convert(
const media::DecoderBuffer& input) {
media::mojom::DecoderBufferPtr mojo_buffer(
media::mojom::DecoderBuffer::New());
if (input.end_of_stream()) {
mojo_buffer->is_end_of_stream = true;
return mojo_buffer;
}
mojo_buffer->is_end_of_stream = false;
mojo_buffer->timestamp = input.timestamp();
mojo_buffer->duration = input.duration();
mojo_buffer->is_key_frame = input.is_key_frame();
mojo_buffer->data_size = base::checked_cast<uint32_t>(input.data_size());
mojo_buffer->front_discard = input.discard_padding().first;
mojo_buffer->back_discard = input.discard_padding().second;
// Note: The side data is always small, so this copy is okay.
if (input.side_data()) {
DCHECK_GT(input.side_data_size(), 0u);
mojo_buffer->side_data.assign(input.side_data(),
input.side_data() + input.side_data_size());
}
if (input.decrypt_config()) {
mojo_buffer->decrypt_config =
media::mojom::DecryptConfig::From(*input.decrypt_config());
}
// TODO(dalecurtis): We intentionally do not serialize the data section of
// the DecoderBuffer here; this must instead be done by clients via their
// own DataPipe. See http://crbug.com/432960
return mojo_buffer;
}
// static
scoped_refptr<media::DecoderBuffer>
TypeConverter<scoped_refptr<media::DecoderBuffer>,
media::mojom::DecoderBufferPtr>::
Convert(const media::mojom::DecoderBufferPtr& input) {
if (input->is_end_of_stream)
return media::DecoderBuffer::CreateEOSBuffer();
scoped_refptr<media::DecoderBuffer> buffer(
new media::DecoderBuffer(input->data_size));
if (!input->side_data.empty())
buffer->CopySideDataFrom(input->side_data.data(), input->side_data.size());
buffer->set_timestamp(input->timestamp);
buffer->set_duration(input->duration);
buffer->set_is_key_frame(input->is_key_frame);
if (input->decrypt_config) {
buffer->set_decrypt_config(
input->decrypt_config.To<std::unique_ptr<media::DecryptConfig>>());
}
media::DecoderBuffer::DiscardPadding discard_padding(input->front_discard,
input->back_discard);
buffer->set_discard_padding(discard_padding);
// TODO(dalecurtis): We intentionally do not deserialize the data section of
// the DecoderBuffer here; this must instead be done by clients via their
// own DataPipe. See http://crbug.com/432960
return buffer;
}
// static
media::mojom::AudioBufferPtr
TypeConverter<media::mojom::AudioBufferPtr, media::AudioBuffer>::Convert(
const media::AudioBuffer& input) {
media::mojom::AudioBufferPtr buffer(media::mojom::AudioBuffer::New());
buffer->sample_format = input.sample_format_;
buffer->channel_layout = input.channel_layout();
buffer->channel_count = input.channel_count();
buffer->sample_rate = input.sample_rate();
buffer->frame_count = input.frame_count();
buffer->end_of_stream = input.end_of_stream();
buffer->timestamp = input.timestamp();
if (input.data_) {
DCHECK_GT(input.data_size(), 0u);
buffer->data.assign(input.data_.get(),
input.data_.get() + input.data_size_);
}
return buffer;
}
// static
scoped_refptr<media::AudioBuffer>
TypeConverter<scoped_refptr<media::AudioBuffer>, media::mojom::AudioBufferPtr>::
Convert(const media::mojom::AudioBufferPtr& input) {
if (input->end_of_stream)
return media::AudioBuffer::CreateEOSBuffer();
if (input->frame_count <= 0 ||
static_cast<size_t>(input->sample_format) > media::kSampleFormatMax ||
static_cast<size_t>(input->channel_layout) > media::CHANNEL_LAYOUT_MAX ||
ChannelLayoutToChannelCount(input->channel_layout) !=
input->channel_count) {
LOG(ERROR) << "Receive an invalid audio buffer, replace it with EOS.";
return media::AudioBuffer::CreateEOSBuffer();
}
if (IsBitstream(input->sample_format)) {
uint8_t* data = input->data.data();
return media::AudioBuffer::CopyBitstreamFrom(
input->sample_format, input->channel_layout, input->channel_count,
input->sample_rate, input->frame_count, &data, input->data.size(),
input->timestamp);
}
// Setup channel pointers. AudioBuffer::CopyFrom() will only use the first
// one in the case of interleaved data.
std::vector<const uint8_t*> channel_ptrs(input->channel_count, nullptr);
const size_t size_per_channel = input->data.size() / input->channel_count;
DCHECK_EQ(0u, input->data.size() % input->channel_count);
for (int i = 0; i < input->channel_count; ++i)
channel_ptrs[i] = input->data.data() + i * size_per_channel;
return media::AudioBuffer::CopyFrom(
input->sample_format, input->channel_layout, input->channel_count,
input->sample_rate, input->frame_count, &channel_ptrs[0],
input->timestamp);
}
} // namespace mojo