blob: f1845389ed226759201422f2fb55428662f911a7 [file] [log] [blame]
// Copyright 2016 Google Inc. 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 "starboard/memory.h"
using base::Time;
using base::TimeDelta;
namespace cobalt {
namespace media {
SbMediaAudioCodec MediaAudioCodecToSbMediaAudioCodec(AudioCodec codec) {
if (codec == kCodecAAC) {
return kSbMediaAudioCodecAac;
} else if (codec == kCodecVorbis) {
return kSbMediaAudioCodecVorbis;
} else if (codec == kCodecOpus) {
return kSbMediaAudioCodecOpus;
}
DLOG(ERROR) << "Unsupported audio codec " << codec;
return kSbMediaAudioCodecNone;
}
SbMediaVideoCodec MediaVideoCodecToSbMediaVideoCodec(VideoCodec codec) {
if (codec == kCodecH264) {
return kSbMediaVideoCodecH264;
} else if (codec == kCodecVC1) {
return kSbMediaVideoCodecVc1;
} else if (codec == kCodecMPEG2) {
return kSbMediaVideoCodecMpeg2;
} else if (codec == kCodecTheora) {
return kSbMediaVideoCodecTheora;
} else if (codec == kCodecVP8) {
return kSbMediaVideoCodecVp8;
} else if (codec == kCodecVP9) {
return kSbMediaVideoCodecVp9;
}
DLOG(ERROR) << "Unsupported video codec " << codec;
return kSbMediaVideoCodecNone;
}
SbMediaAudioHeader MediaAudioConfigToSbMediaAudioHeader(
const AudioDecoderConfig& audio_decoder_config) {
SbMediaAudioHeader audio_header;
// TODO: Make this work with non AAC audio.
audio_header.format_tag = 0x00ff;
audio_header.number_of_channels =
ChannelLayoutToChannelCount(audio_decoder_config.channel_layout());
audio_header.samples_per_second = audio_decoder_config.samples_per_second();
audio_header.average_bytes_per_second = 1;
audio_header.block_alignment = 4;
audio_header.bits_per_sample = audio_decoder_config.bits_per_channel();
#if SB_API_VERSION >= SB_AUDIO_SPECIFIC_CONFIG_AS_POINTER
audio_header.audio_specific_config_size =
static_cast<uint16_t>(audio_decoder_config.extra_data().size());
if (audio_header.audio_specific_config_size == 0) {
audio_header.audio_specific_config = NULL;
} else {
audio_header.audio_specific_config = &audio_decoder_config.extra_data()[0];
}
#else // SB_API_VERSION >= SB_AUDIO_SPECIFIC_CONFIG_AS_POINTER
audio_header.audio_specific_config_size = static_cast<uint16_t>(
std::min(audio_decoder_config.extra_data().size(),
sizeof(audio_header.audio_specific_config)));
if (audio_header.audio_specific_config_size > 0) {
SbMemoryCopy(audio_header.audio_specific_config,
&audio_decoder_config.extra_data()[0],
audio_header.audio_specific_config_size);
}
#endif // SB_API_VERSION >= SB_AUDIO_SPECIFIC_CONFIG_AS_POINTER
return audio_header;
}
TimeDelta SbMediaTimeToTimeDelta(SbMediaTime timestamp) {
return TimeDelta::FromMicroseconds(timestamp * Time::kMicrosecondsPerSecond /
kSbMediaTimeSecond);
}
SbMediaTime TimeDeltaToSbMediaTime(TimeDelta timedelta) {
return timedelta.InMicroseconds() * kSbMediaTimeSecond /
Time::kMicrosecondsPerSecond;
}
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 (!config || config->iv().empty() || config->key_id().empty()) {
drm_info->initialization_vector_size = 0;
drm_info->identifier_size = 0;
drm_info->subsample_count = 0;
drm_info->subsample_mapping = NULL;
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)) {
drm_info->initialization_vector_size = 0;
drm_info->identifier_size = 0;
drm_info->subsample_count = 0;
drm_info->subsample_mapping = NULL;
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();
}
}
// 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