// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Defines APIs that are specific to Starboard 15. GetStarboardApiWrapper() is
// the public API; everything else is an implementation detail.
#include <starboard/drm.h>
#include <starboard/media.h>
#include <starboard/player.h>
#include "base/logging.h"
#include "chromecast/starboard/media/media/starboard_api_wrapper_base.h"
namespace chromecast {
namespace media {
namespace {
// Populates a VideoStreamInfo struct from a StarboardVideoSampleInfo.
SbMediaVideoStreamInfo ToSbMediaVideoStreamInfo(
const StarboardVideoSampleInfo& in_video_info) {
SbMediaVideoStreamInfo out_video_info = {};
out_video_info.codec = static_cast<SbMediaVideoCodec>(in_video_info.codec);
out_video_info.mime = in_video_info.mime;
out_video_info.max_video_capabilities = in_video_info.max_video_capabilities;
out_video_info.frame_width = in_video_info.frame_width;
out_video_info.frame_height = in_video_info.frame_height;
const StarboardColorMetadata& in_color_metadata =
in_video_info.color_metadata;
SbMediaColorMetadata& out_color_metadata = out_video_info.color_metadata;
out_color_metadata.bits_per_channel = in_color_metadata.bits_per_channel;
out_color_metadata.chroma_subsampling_horizontal =
in_color_metadata.chroma_subsampling_horizontal;
out_color_metadata.chroma_subsampling_vertical =
in_color_metadata.chroma_subsampling_vertical;
out_color_metadata.cb_subsampling_horizontal =
in_color_metadata.cb_subsampling_horizontal;
out_color_metadata.cb_subsampling_vertical =
in_color_metadata.cb_subsampling_vertical;
out_color_metadata.chroma_siting_horizontal =
in_color_metadata.chroma_siting_horizontal;
out_color_metadata.chroma_siting_vertical =
in_color_metadata.chroma_siting_vertical;
// note: we skip SbMediaMasteringMetadata
out_color_metadata.max_cll = in_color_metadata.max_cll;
out_color_metadata.max_fall = in_color_metadata.max_fall;
out_color_metadata.primaries =
static_cast<SbMediaPrimaryId>(in_color_metadata.primaries);
out_color_metadata.transfer =
static_cast<SbMediaTransferId>(in_color_metadata.transfer);
out_color_metadata.matrix =
static_cast<SbMediaMatrixId>(in_color_metadata.matrix);
out_color_metadata.range =
static_cast<SbMediaRangeId>(in_color_metadata.range);
static_assert(sizeof(out_color_metadata.custom_primary_matrix) ==
sizeof(in_color_metadata.custom_primary_matrix),
"Struct field size mismatch (custom_primary_matrix)");
memcpy(out_color_metadata.custom_primary_matrix,
in_color_metadata.custom_primary_matrix,
sizeof(out_color_metadata.custom_primary_matrix));
return out_video_info;
}
// Populates an AudioStreamInfo struct from a StarboardAudioSampleInfo.
SbMediaAudioStreamInfo ToSbMediaAudioStreamInfo(
const StarboardAudioSampleInfo& in_audio_info) {
SbMediaAudioStreamInfo out_audio_info = {};
out_audio_info.codec = static_cast<SbMediaAudioCodec>(in_audio_info.codec);
out_audio_info.mime = in_audio_info.mime;
out_audio_info.number_of_channels = in_audio_info.number_of_channels;
out_audio_info.samples_per_second = in_audio_info.samples_per_second;
out_audio_info.bits_per_sample = in_audio_info.bits_per_sample;
out_audio_info.audio_specific_config_size =
in_audio_info.audio_specific_config_size;
out_audio_info.audio_specific_config = in_audio_info.audio_specific_config;
return out_audio_info;
}
// A concrete implementation of StarboardApiWrapper for Starboard version 15.
class StarboardApiWrapper15 : public StarboardApiWrapperBase {
public:
StarboardApiWrapper15() = default;
~StarboardApiWrapper15() override = default;
// StarboardApiWrapper impl:
void SeekTo(void* player, int64_t time, int seek_ticket) override {
SbPlayerSeek(static_cast<SbPlayer>(player), time, seek_ticket);
}
void GetPlayerInfo(void* player, StarboardPlayerInfo* player_info) override {
SbPlayerInfo sb_player_info = {};
SbPlayerGetInfo(static_cast<SbPlayer>(player), &sb_player_info);
player_info->current_media_timestamp_micros =
sb_player_info.current_media_timestamp;
player_info->duration_micros = sb_player_info.duration;
player_info->start_date = sb_player_info.start_date;
player_info->frame_width = sb_player_info.frame_width;
player_info->frame_height = sb_player_info.frame_height;
player_info->is_paused = sb_player_info.is_paused;
player_info->volume = sb_player_info.volume;
player_info->total_video_frames = sb_player_info.total_video_frames;
player_info->dropped_video_frames = sb_player_info.dropped_video_frames;
player_info->corrupted_video_frames = sb_player_info.corrupted_video_frames;
player_info->playback_rate = sb_player_info.playback_rate;
}
private:
// StarboardApiWrapperBase impl:
SbPlayerCreationParam ToSbPlayerCreationParam(
const StarboardPlayerCreationParam& in_param,
void* drm_system) override {
SbPlayerCreationParam out_param = {};
out_param.audio_stream_info =
ToSbMediaAudioStreamInfo(in_param.audio_sample_info);
out_param.video_stream_info =
ToSbMediaVideoStreamInfo(in_param.video_sample_info);
out_param.output_mode =
static_cast<SbPlayerOutputMode>(in_param.output_mode);
if (drm_system) {
LOG(INFO) << "Using an SbDrmSystem for decryption.";
out_param.drm_system = static_cast<SbDrmSystem>(drm_system);
} else {
LOG(INFO)
<< "No SbDrmSystem was created before SbPlayer; no decryption is "
"possible in starboard.";
out_param.drm_system = kSbDrmSystemInvalid;
}
return out_param;
}
SbMediaVideoSampleInfo ToSbMediaVideoSampleInfo(
const StarboardVideoSampleInfo& in_video_info) override {
SbMediaVideoSampleInfo out_video_info;
out_video_info.stream_info = ToSbMediaVideoStreamInfo(in_video_info);
out_video_info.is_key_frame = in_video_info.is_key_frame;
return out_video_info;
}
SbMediaAudioSampleInfo ToSbMediaAudioSampleInfo(
const StarboardAudioSampleInfo& in_audio_info) override {
SbMediaAudioSampleInfo out_audio_info = {};
out_audio_info.stream_info = ToSbMediaAudioStreamInfo(in_audio_info);
out_audio_info.discarded_duration_from_front = 0;
out_audio_info.discarded_duration_from_back = 0;
return out_audio_info;
}
void CallWriteSamples(SbPlayer player,
SbMediaType sample_type,
const SbPlayerSampleInfo* sample_infos,
int number_of_sample_infos) override {
SbPlayerWriteSamples(player, sample_type, sample_infos,
number_of_sample_infos);
}
};
} // namespace
// Note: declared in starboard_api_wrapper.h.
std::unique_ptr<StarboardApiWrapper> GetStarboardApiWrapper() {
return std::make_unique<StarboardApiWrapper15>();
}
} // namespace media
} // namespace chromecast