blob: d56c2eead7f1eaa3d3e7fb60c5303c062f9215ef [file] [log] [blame]
// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/media/base/starboard_utils.h"
#include <algorithm>
#include "base/logging.h"
#include "cobalt/media/base/decrypt_config.h"
#include "starboard/configuration.h"
#include "starboard/memory.h"
using base::Time;
using base::TimeDelta;
namespace cobalt {
namespace media {
SbMediaAudioCodec MediaAudioCodecToSbMediaAudioCodec(AudioCodec codec) {
switch (codec) {
case kCodecAAC:
return kSbMediaAudioCodecAac;
#if SB_API_VERSION >= 12 || SB_HAS(AC3_AUDIO)
case kCodecAC3:
if (!kSbHasAc3Audio) {
DLOG(ERROR) << "Audio codec AC3 not enabled on this platform. To "
<< "enable it, set kSbHasAc3Audio to |true|.";
return kSbMediaAudioCodecNone;
}
return kSbMediaAudioCodecAc3;
case kCodecEAC3:
if (!kSbHasAc3Audio) {
DLOG(ERROR) << "Audio codec AC3 not enabled on this platform. To "
<< "enable it, set kSbHasAc3Audio to |true|.";
return kSbMediaAudioCodecNone;
}
return kSbMediaAudioCodecEac3;
#endif // SB_API_VERSION >= 12 ||
// SB_HAS(AC3_AUDIO)
case kCodecVorbis:
return kSbMediaAudioCodecVorbis;
case kCodecOpus:
return kSbMediaAudioCodecOpus;
default:
// Cobalt only supports a subset of audio codecs defined by Chromium.
DLOG(ERROR) << "Unsupported audio codec "
<< cobalt::media::GetCodecName(codec);
return kSbMediaAudioCodecNone;
}
NOTREACHED();
return kSbMediaAudioCodecNone;
}
SbMediaVideoCodec MediaVideoCodecToSbMediaVideoCodec(VideoCodec codec) {
switch (codec) {
case kCodecH264:
return kSbMediaVideoCodecH264;
case kCodecVC1:
return kSbMediaVideoCodecVc1;
case kCodecMPEG2:
return kSbMediaVideoCodecMpeg2;
case kCodecTheora:
return kSbMediaVideoCodecTheora;
case kCodecVP8:
return kSbMediaVideoCodecVp8;
case kCodecVP9:
return kSbMediaVideoCodecVp9;
case kCodecHEVC:
return kSbMediaVideoCodecH265;
case kCodecAV1:
return kSbMediaVideoCodecAv1;
default:
// Cobalt only supports a subset of video codecs defined by Chromium.
DLOG(ERROR) << "Unsupported video codec "
<< cobalt::media::GetCodecName(codec);
return kSbMediaVideoCodecNone;
}
NOTREACHED();
return kSbMediaVideoCodecNone;
}
SbMediaAudioSampleInfo MediaAudioConfigToSbMediaAudioSampleInfo(
const AudioDecoderConfig& audio_decoder_config) {
DCHECK(audio_decoder_config.IsValidConfig());
SbMediaAudioSampleInfo audio_sample_info;
audio_sample_info.codec =
MediaAudioCodecToSbMediaAudioCodec(audio_decoder_config.codec());
#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
audio_sample_info.mime = audio_decoder_config.mime().c_str();
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
// TODO: Make this work with non AAC audio.
audio_sample_info.format_tag = 0x00ff;
audio_sample_info.number_of_channels =
ChannelLayoutToChannelCount(audio_decoder_config.channel_layout());
audio_sample_info.samples_per_second =
audio_decoder_config.samples_per_second();
audio_sample_info.average_bytes_per_second = 1;
audio_sample_info.block_alignment = 4;
audio_sample_info.bits_per_sample = audio_decoder_config.bits_per_channel();
audio_sample_info.audio_specific_config_size =
static_cast<uint16_t>(audio_decoder_config.extra_data().size());
if (audio_sample_info.audio_specific_config_size == 0) {
audio_sample_info.audio_specific_config = NULL;
} else {
audio_sample_info.audio_specific_config =
&audio_decoder_config.extra_data()[0];
}
return audio_sample_info;
}
DemuxerStream::Type SbMediaTypeToDemuxerStreamType(SbMediaType type) {
if (type == kSbMediaTypeAudio) {
return DemuxerStream::AUDIO;
}
DCHECK_EQ(type, kSbMediaTypeVideo);
return DemuxerStream::VIDEO;
}
SbMediaType DemuxerStreamTypeToSbMediaType(DemuxerStream::Type type) {
if (type == DemuxerStream::AUDIO) {
return kSbMediaTypeAudio;
}
DCHECK_EQ(type, DemuxerStream::VIDEO);
return kSbMediaTypeVideo;
}
void FillDrmSampleInfo(const scoped_refptr<DecoderBuffer>& buffer,
SbDrmSampleInfo* drm_info,
SbDrmSubSampleMapping* subsample_mapping) {
DCHECK(drm_info);
DCHECK(subsample_mapping);
const DecryptConfig* config = buffer->decrypt_config();
#if SB_API_VERSION >= 12
if (config->encryption_mode() == EncryptionMode::kCenc) {
drm_info->encryption_scheme = kSbDrmEncryptionSchemeAesCtr;
} else {
DCHECK_EQ(config->encryption_mode(), EncryptionMode::kCbcs);
drm_info->encryption_scheme = kSbDrmEncryptionSchemeAesCbc;
}
#else // SB_API_VERSION >= 12
DCHECK_EQ(config->encryption_mode(), EncryptionMode::kCenc);
#endif // SB_API_VERSION >= 12
// Set content of |drm_info| to default or invalid values.
#if SB_API_VERSION >= 12
drm_info->encryption_pattern.crypt_byte_block = 0;
drm_info->encryption_pattern.skip_byte_block = 0;
#endif // SB_API_VERSION >= 12
drm_info->initialization_vector_size = 0;
drm_info->identifier_size = 0;
drm_info->subsample_count = 0;
drm_info->subsample_mapping = NULL;
if (!config || config->iv().empty() || config->key_id().empty()) {
return;
}
DCHECK_LE(config->iv().size(), sizeof(drm_info->initialization_vector));
DCHECK_LE(config->key_id().size(), sizeof(drm_info->identifier));
if (config->iv().size() > sizeof(drm_info->initialization_vector) ||
config->key_id().size() > sizeof(drm_info->identifier)) {
return;
}
SbMemoryCopy(drm_info->initialization_vector, &config->iv()[0],
config->iv().size());
drm_info->initialization_vector_size = config->iv().size();
SbMemoryCopy(drm_info->identifier, &config->key_id()[0],
config->key_id().size());
drm_info->identifier_size = config->key_id().size();
drm_info->subsample_count = config->subsamples().size();
if (drm_info->subsample_count > 0) {
COMPILE_ASSERT(sizeof(SbDrmSubSampleMapping) == sizeof(SubsampleEntry),
SubSampleEntrySizesMatch);
drm_info->subsample_mapping =
reinterpret_cast<const SbDrmSubSampleMapping*>(
&config->subsamples()[0]);
} else {
drm_info->subsample_count = 1;
drm_info->subsample_mapping = subsample_mapping;
subsample_mapping->clear_byte_count = 0;
subsample_mapping->encrypted_byte_count = buffer->data_size();
}
#if SB_API_VERSION >= 12
if (buffer->decrypt_config()->HasPattern()) {
drm_info->encryption_pattern.crypt_byte_block =
config->encryption_pattern()->crypt_byte_block();
drm_info->encryption_pattern.skip_byte_block =
config->encryption_pattern()->skip_byte_block();
}
#else // SB_API_VERSION >= 12
if (buffer->decrypt_config()->HasPattern()) {
DCHECK_EQ(config->encryption_pattern()->crypt_byte_block(), 0);
DCHECK_EQ(config->encryption_pattern()->skip_byte_block(), 0);
}
#endif // SB_API_VERSION >= 12
}
// Ensure that the enums in starboard/media.h match enums in gfx::ColorSpace.
#define ENUM_EQ(a, b) \
COMPILE_ASSERT(static_cast<int>(a) == static_cast<int>(b), mismatching_enums)
// Ensure PrimaryId enums convert correctly.
ENUM_EQ(kSbMediaPrimaryIdReserved0, gfx::ColorSpace::kPrimaryIdReserved0);
ENUM_EQ(kSbMediaPrimaryIdBt709, gfx::ColorSpace::kPrimaryIdBt709);
ENUM_EQ(kSbMediaPrimaryIdUnspecified, gfx::ColorSpace::kPrimaryIdUnspecified);
ENUM_EQ(kSbMediaPrimaryIdReserved, gfx::ColorSpace::kPrimaryIdReserved);
ENUM_EQ(kSbMediaPrimaryIdBt470M, gfx::ColorSpace::kPrimaryIdBt470M);
ENUM_EQ(kSbMediaPrimaryIdBt470Bg, gfx::ColorSpace::kPrimaryIdBt470Bg);
ENUM_EQ(kSbMediaPrimaryIdSmpte170M, gfx::ColorSpace::kPrimaryIdSmpte170M);
ENUM_EQ(kSbMediaPrimaryIdSmpte240M, gfx::ColorSpace::kPrimaryIdSmpte240M);
ENUM_EQ(kSbMediaPrimaryIdFilm, gfx::ColorSpace::kPrimaryIdFilm);
ENUM_EQ(kSbMediaPrimaryIdBt2020, gfx::ColorSpace::kPrimaryIdBt2020);
ENUM_EQ(kSbMediaPrimaryIdSmpteSt4281, gfx::ColorSpace::kPrimaryIdSmpteSt4281);
ENUM_EQ(kSbMediaPrimaryIdSmpteSt4312, gfx::ColorSpace::kPrimaryIdSmpteSt4312);
ENUM_EQ(kSbMediaPrimaryIdSmpteSt4321, gfx::ColorSpace::kPrimaryIdSmpteSt4321);
ENUM_EQ(kSbMediaPrimaryIdLastStandardValue,
gfx::ColorSpace::kPrimaryIdLastStandardValue);
ENUM_EQ(kSbMediaPrimaryIdUnknown, gfx::ColorSpace::kPrimaryIdUnknown);
ENUM_EQ(kSbMediaPrimaryIdXyzD50, gfx::ColorSpace::kPrimaryIdXyzD50);
ENUM_EQ(kSbMediaPrimaryIdCustom, gfx::ColorSpace::kPrimaryIdCustom);
ENUM_EQ(kSbMediaPrimaryIdLast, gfx::ColorSpace::kPrimaryIdLast);
// Ensure TransferId enums convert correctly.
ENUM_EQ(kSbMediaTransferIdReserved0, gfx::ColorSpace::kTransferIdReserved0);
ENUM_EQ(kSbMediaTransferIdBt709, gfx::ColorSpace::kTransferIdBt709);
ENUM_EQ(kSbMediaTransferIdUnspecified, gfx::ColorSpace::kTransferIdUnspecified);
ENUM_EQ(kSbMediaTransferIdReserved, gfx::ColorSpace::kTransferIdReserved);
ENUM_EQ(kSbMediaTransferIdGamma22, gfx::ColorSpace::kTransferIdGamma22);
ENUM_EQ(kSbMediaTransferIdGamma28, gfx::ColorSpace::kTransferIdGamma28);
ENUM_EQ(kSbMediaTransferIdSmpte170M, gfx::ColorSpace::kTransferIdSmpte170M);
ENUM_EQ(kSbMediaTransferIdSmpte240M, gfx::ColorSpace::kTransferIdSmpte240M);
ENUM_EQ(kSbMediaTransferIdLinear, gfx::ColorSpace::kTransferIdLinear);
ENUM_EQ(kSbMediaTransferIdLog, gfx::ColorSpace::kTransferIdLog);
ENUM_EQ(kSbMediaTransferIdLogSqrt, gfx::ColorSpace::kTransferIdLogSqrt);
ENUM_EQ(kSbMediaTransferIdIec6196624, gfx::ColorSpace::kTransferIdIec6196624);
ENUM_EQ(kSbMediaTransferIdBt1361Ecg, gfx::ColorSpace::kTransferIdBt1361Ecg);
ENUM_EQ(kSbMediaTransferIdIec6196621, gfx::ColorSpace::kTransferIdIec6196621);
ENUM_EQ(kSbMediaTransferId10BitBt2020, gfx::ColorSpace::kTransferId10BitBt2020);
ENUM_EQ(kSbMediaTransferId12BitBt2020, gfx::ColorSpace::kTransferId12BitBt2020);
ENUM_EQ(kSbMediaTransferIdSmpteSt2084, gfx::ColorSpace::kTransferIdSmpteSt2084);
ENUM_EQ(kSbMediaTransferIdSmpteSt4281, gfx::ColorSpace::kTransferIdSmpteSt4281);
ENUM_EQ(kSbMediaTransferIdAribStdB67, gfx::ColorSpace::kTransferIdAribStdB67);
ENUM_EQ(kSbMediaTransferIdLastStandardValue,
gfx::ColorSpace::kTransferIdLastStandardValue);
ENUM_EQ(kSbMediaTransferIdUnknown, gfx::ColorSpace::kTransferIdUnknown);
ENUM_EQ(kSbMediaTransferIdGamma24, gfx::ColorSpace::kTransferIdGamma24);
ENUM_EQ(kSbMediaTransferIdSmpteSt2084NonHdr,
gfx::ColorSpace::kTransferIdSmpteSt2084NonHdr);
ENUM_EQ(kSbMediaTransferIdCustom, gfx::ColorSpace::kTransferIdCustom);
ENUM_EQ(kSbMediaTransferIdLast, gfx::ColorSpace::kTransferIdLast);
// Ensure MatrixId enums convert correctly.
ENUM_EQ(kSbMediaMatrixIdRgb, gfx::ColorSpace::kMatrixIdRgb);
ENUM_EQ(kSbMediaMatrixIdBt709, gfx::ColorSpace::kMatrixIdBt709);
ENUM_EQ(kSbMediaMatrixIdUnspecified, gfx::ColorSpace::kMatrixIdUnspecified);
ENUM_EQ(kSbMediaMatrixIdReserved, gfx::ColorSpace::kMatrixIdReserved);
ENUM_EQ(kSbMediaMatrixIdFcc, gfx::ColorSpace::kMatrixIdFcc);
ENUM_EQ(kSbMediaMatrixIdBt470Bg, gfx::ColorSpace::kMatrixIdBt470Bg);
ENUM_EQ(kSbMediaMatrixIdSmpte170M, gfx::ColorSpace::kMatrixIdSmpte170M);
ENUM_EQ(kSbMediaMatrixIdSmpte240M, gfx::ColorSpace::kMatrixIdSmpte240M);
ENUM_EQ(kSbMediaMatrixIdYCgCo, gfx::ColorSpace::kMatrixIdYCgCo);
ENUM_EQ(kSbMediaMatrixIdBt2020NonconstantLuminance,
gfx::ColorSpace::kMatrixIdBt2020NonconstantLuminance);
ENUM_EQ(kSbMediaMatrixIdBt2020ConstantLuminance,
gfx::ColorSpace::kMatrixIdBt2020ConstantLuminance);
ENUM_EQ(kSbMediaMatrixIdYDzDx, gfx::ColorSpace::kMatrixIdYDzDx);
ENUM_EQ(kSbMediaMatrixIdLastStandardValue,
gfx::ColorSpace::kMatrixIdLastStandardValue);
ENUM_EQ(kSbMediaMatrixIdUnknown, gfx::ColorSpace::kMatrixIdUnknown);
ENUM_EQ(kSbMediaMatrixIdLast, gfx::ColorSpace::kMatrixIdLast);
// Ensure RangeId enums convert correctly.
ENUM_EQ(kSbMediaRangeIdUnspecified, gfx::ColorSpace::kRangeIdUnspecified);
ENUM_EQ(kSbMediaRangeIdLimited, gfx::ColorSpace::kRangeIdLimited);
ENUM_EQ(kSbMediaRangeIdFull, gfx::ColorSpace::kRangeIdFull);
ENUM_EQ(kSbMediaRangeIdDerived, gfx::ColorSpace::kRangeIdDerived);
ENUM_EQ(kSbMediaRangeIdLast, gfx::ColorSpace::kRangeIdLast);
SbMediaColorMetadata MediaToSbMediaColorMetadata(
const WebMColorMetadata& webm_color_metadata) {
SbMediaColorMetadata sb_media_color_metadata;
// Copy the other color metadata below.
sb_media_color_metadata.bits_per_channel = webm_color_metadata.BitsPerChannel;
sb_media_color_metadata.chroma_subsampling_horizontal =
webm_color_metadata.ChromaSubsamplingHorz;
sb_media_color_metadata.chroma_subsampling_vertical =
webm_color_metadata.ChromaSubsamplingVert;
sb_media_color_metadata.cb_subsampling_horizontal =
webm_color_metadata.CbSubsamplingHorz;
sb_media_color_metadata.cb_subsampling_vertical =
webm_color_metadata.CbSubsamplingVert;
sb_media_color_metadata.chroma_siting_horizontal =
webm_color_metadata.ChromaSitingHorz;
sb_media_color_metadata.chroma_siting_vertical =
webm_color_metadata.ChromaSitingVert;
// Copy the HDR Metadata below.
SbMediaMasteringMetadata sb_media_mastering_metadata;
HDRMetadata hdr_metadata = webm_color_metadata.hdr_metadata;
MasteringMetadata mastering_metadata = hdr_metadata.mastering_metadata;
sb_media_mastering_metadata.primary_r_chromaticity_x =
mastering_metadata.primary_r_chromaticity_x;
sb_media_mastering_metadata.primary_r_chromaticity_y =
mastering_metadata.primary_r_chromaticity_y;
sb_media_mastering_metadata.primary_g_chromaticity_x =
mastering_metadata.primary_g_chromaticity_x;
sb_media_mastering_metadata.primary_g_chromaticity_y =
mastering_metadata.primary_g_chromaticity_y;
sb_media_mastering_metadata.primary_b_chromaticity_x =
mastering_metadata.primary_b_chromaticity_x;
sb_media_mastering_metadata.primary_b_chromaticity_y =
mastering_metadata.primary_b_chromaticity_y;
sb_media_mastering_metadata.white_point_chromaticity_x =
mastering_metadata.white_point_chromaticity_x;
sb_media_mastering_metadata.white_point_chromaticity_y =
mastering_metadata.white_point_chromaticity_y;
sb_media_mastering_metadata.luminance_max = mastering_metadata.luminance_max;
sb_media_mastering_metadata.luminance_min = mastering_metadata.luminance_min;
sb_media_color_metadata.mastering_metadata = sb_media_mastering_metadata;
sb_media_color_metadata.max_cll = hdr_metadata.max_cll;
sb_media_color_metadata.max_fall = hdr_metadata.max_fall;
// Copy the color space below.
gfx::ColorSpace color_space = webm_color_metadata.color_space;
sb_media_color_metadata.primaries =
static_cast<SbMediaPrimaryId>(color_space.primaries());
sb_media_color_metadata.transfer =
static_cast<SbMediaTransferId>(color_space.transfer());
sb_media_color_metadata.matrix =
static_cast<SbMediaMatrixId>(color_space.matrix());
sb_media_color_metadata.range =
static_cast<SbMediaRangeId>(color_space.range());
if (sb_media_color_metadata.primaries == kSbMediaPrimaryIdCustom) {
const float* custom_primary_matrix = color_space.custom_primary_matrix();
SbMemoryCopy(sb_media_color_metadata.custom_primary_matrix,
custom_primary_matrix, sizeof(custom_primary_matrix));
}
return sb_media_color_metadata;
}
} // namespace media
} // namespace cobalt