blob: fc6a3a0222e54a2c7d0850892206fd622e9eac07 [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 "starboard/shared/starboard/player/input_buffer_internal.h"
#include <cctype>
#include <numeric>
#include <sstream>
#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/memory.h"
namespace starboard {
namespace shared {
namespace starboard {
namespace player {
#if SB_API_VERSION >= 11
InputBuffer::InputBuffer(SbPlayerDeallocateSampleFunc deallocate_sample_func,
SbPlayer player,
void* context,
const SbPlayerSampleInfo& sample_info)
: deallocate_sample_func_(deallocate_sample_func),
player_(player),
context_(context),
sample_type_(sample_info.type),
data_(static_cast<const uint8_t*>(sample_info.buffer)),
size_(sample_info.buffer_size),
timestamp_(sample_info.timestamp) {
SB_DCHECK(deallocate_sample_func);
if (sample_type_ == kSbMediaTypeAudio) {
audio_sample_info_ = sample_info.audio_sample_info;
} else {
SB_DCHECK(sample_type_ == kSbMediaTypeVideo);
video_sample_info_ = sample_info.video_sample_info;
}
TryToAssignDrmSampleInfo(sample_info.drm_info);
if (sample_info.side_data_count > 0) {
SB_DCHECK(sample_info.side_data_count == 1);
SB_DCHECK(sample_info.side_data);
SB_DCHECK(sample_info.side_data->type == kMatroskaBlockAdditional);
SB_DCHECK(sample_info.side_data->data);
// Make a copy anyway as it is possible to release |data_| earlier in
// SetDecryptedContent().
side_data_.assign(
sample_info.side_data->data,
sample_info.side_data->data + sample_info.side_data->size);
}
}
#else // SB_API_VERSION >= 11
InputBuffer::InputBuffer(SbMediaType sample_type,
SbPlayerDeallocateSampleFunc dealloate_sample_func,
SbPlayer player,
void* context,
const SbPlayerSampleInfo& sample_info,
const SbMediaAudioSampleInfo* audio_sample_info)
: deallocate_sample_func_(dealloate_sample_func),
player_(player),
context_(context),
sample_type_(sample_type),
data_(static_cast<const uint8_t*>(sample_info.buffer)),
size_(sample_info.buffer_size),
timestamp_(sample_info.timestamp) {
SB_DCHECK(deallocate_sample_func_);
if (sample_type_ == kSbMediaTypeVideo) {
SB_DCHECK(sample_info.video_sample_info);
video_sample_info_ = *sample_info.video_sample_info;
} else {
SB_DCHECK(sample_type_ == kSbMediaTypeAudio && audio_sample_info);
audio_sample_info_ = *audio_sample_info;
}
TryToAssignDrmSampleInfo(sample_info.drm_info);
}
#endif // SB_API_VERSION >= 11
InputBuffer::~InputBuffer() {
DeallocateSampleBuffer(data_);
}
void InputBuffer::SetDecryptedContent(const void* buffer, int size) {
SB_DCHECK(size == size_);
DeallocateSampleBuffer(data_);
if (size > 0) {
flattened_data_.clear();
flattened_data_.assign(static_cast<const uint8_t*>(buffer),
static_cast<const uint8_t*>(buffer) + size);
data_ = flattened_data_.data();
} else {
data_ = NULL;
}
has_drm_info_ = false;
}
std::string InputBuffer::ToString() const {
std::stringstream ss;
ss << "========== " << (has_drm_info_ ? "encrypted " : "clear ")
<< (sample_type() == kSbMediaTypeAudio ? "audio" : "video")
<< " sample @ timestamp: " << timestamp() << " in " << size()
<< " bytes ==========\n";
if (sample_type() == kSbMediaTypeAudio) {
#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
ss << "codec: " << audio_sample_info().codec << ", mime: '"
<< audio_sample_info().mime << "'\n";
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
ss << audio_sample_info().samples_per_second << '\n';
} else {
SB_DCHECK(sample_type() == kSbMediaTypeVideo);
#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
ss << "codec: " << video_sample_info().codec << ", mime: '"
<< video_sample_info().mime << "'"
<< ", max_video_capabilities: '"
<< video_sample_info().max_video_capabilities << "'\n";
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
ss << video_sample_info().frame_width << " x "
<< video_sample_info().frame_height << '\n';
}
if (has_drm_info_) {
ss << "iv: "
<< HexEncode(drm_info_.initialization_vector,
drm_info_.initialization_vector_size)
<< "\nkey_id: "
<< HexEncode(drm_info_.identifier, drm_info_.identifier_size) << '\n';
ss << "subsamples\n";
for (int i = 0; i < drm_info_.subsample_count; ++i) {
ss << "\t" << drm_info_.subsample_mapping[i].clear_byte_count << ", "
<< drm_info_.subsample_mapping[i].encrypted_byte_count << "\n";
}
}
if (!side_data_.empty()) {
ss << "side data: "
<< HexEncode(side_data_.data(), static_cast<int>(side_data_.size()))
<< '\n';
}
ss << GetMixedRepresentation(data(), size(), 16) << '\n';
return ss.str();
}
void InputBuffer::TryToAssignDrmSampleInfo(
const SbDrmSampleInfo* sample_drm_info) {
has_drm_info_ = sample_drm_info != NULL;
if (!has_drm_info_) {
return;
}
SB_DCHECK(sample_drm_info->subsample_count > 0);
subsamples_.assign(
sample_drm_info->subsample_mapping,
sample_drm_info->subsample_mapping + sample_drm_info->subsample_count);
drm_info_ = *sample_drm_info;
drm_info_.subsample_mapping = subsamples_.empty() ? NULL : &subsamples_[0];
}
void InputBuffer::DeallocateSampleBuffer(const void* buffer) {
if (deallocate_sample_func_) {
deallocate_sample_func_(player_, context_, buffer);
deallocate_sample_func_ = NULL;
}
}
} // namespace player
} // namespace starboard
} // namespace shared
} // namespace starboard