// 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 "starboard/shared/starboard/player/input_buffer_internal.h" | |
#include <vector> | |
#include "starboard/atomic.h" | |
#include "starboard/log.h" | |
#include "starboard/memory.h" | |
namespace starboard { | |
namespace shared { | |
namespace starboard { | |
namespace player { | |
class InputBuffer::ReferenceCountedBuffer { | |
public: | |
ReferenceCountedBuffer(SbPlayerDeallocateSampleFunc deallocate_sample_func, | |
SbPlayer player, | |
void* context, | |
const void* sample_buffer, | |
int sample_buffer_size, | |
SbMediaTime sample_pts, | |
const SbMediaVideoSampleInfo* video_sample_info, | |
const SbDrmSampleInfo* sample_drm_info) | |
: ref_count_(0), | |
deallocate_sample_func_(deallocate_sample_func), | |
player_(player), | |
context_(context), | |
data_(reinterpret_cast<const uint8_t*>(sample_buffer)), | |
size_(sample_buffer_size), | |
pts_(sample_pts), | |
has_video_sample_info_(video_sample_info != NULL), | |
has_drm_info_(sample_drm_info != NULL) { | |
SB_DCHECK(deallocate_sample_func); | |
if (has_video_sample_info_) { | |
video_sample_info_ = *video_sample_info; | |
} | |
if (has_drm_info_) { | |
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 AddRef() const { SbAtomicBarrier_Increment(&ref_count_, 1); } | |
void Release() const { | |
if (SbAtomicBarrier_Increment(&ref_count_, -1) == 0) { | |
delete this; | |
} | |
} | |
const uint8_t* data() const { return data_; } | |
int size() const { return size_; } | |
SbMediaTime pts() const { return pts_; } | |
const SbMediaVideoSampleInfo* video_sample_info() const { | |
return has_video_sample_info_ ? &video_sample_info_ : NULL; | |
} | |
const SbDrmSampleInfo* drm_info() const { | |
return has_drm_info_ ? &drm_info_ : NULL; | |
} | |
void SetDecryptedContent(const void* buffer, int size) { | |
SB_DCHECK(size == size_); | |
SB_DCHECK(deallocate_sample_func_); | |
DeallocateSampleBuffer(); | |
if (size > 0) { | |
decrypted_data_.resize(size); | |
SbMemoryCopy(&decrypted_data_[0], buffer, size); | |
data_ = &decrypted_data_[0]; | |
} else { | |
data_ = NULL; | |
} | |
size_ = size; | |
has_drm_info_ = false; | |
} | |
private: | |
~ReferenceCountedBuffer() { DeallocateSampleBuffer(); } | |
void DeallocateSampleBuffer() { | |
if (deallocate_sample_func_) { | |
deallocate_sample_func_(player_, context_, const_cast<uint8_t*>(data_)); | |
deallocate_sample_func_ = NULL; | |
} | |
} | |
mutable SbAtomic32 ref_count_; | |
SbPlayerDeallocateSampleFunc deallocate_sample_func_; | |
SbPlayer player_; | |
void* context_; | |
const uint8_t* data_; | |
int size_; | |
SbMediaTime pts_; | |
bool has_video_sample_info_; | |
SbMediaVideoSampleInfo video_sample_info_; | |
bool has_drm_info_; | |
SbDrmSampleInfo drm_info_; | |
std::vector<uint8_t> decrypted_data_; | |
std::vector<SbDrmSubSampleMapping> subsamples_; | |
SB_DISALLOW_COPY_AND_ASSIGN(ReferenceCountedBuffer); | |
}; | |
InputBuffer::InputBuffer() : buffer_(NULL) {} | |
InputBuffer::InputBuffer(SbPlayerDeallocateSampleFunc deallocate_sample_func, | |
SbPlayer player, | |
void* context, | |
const void* sample_buffer, | |
int sample_buffer_size, | |
SbMediaTime sample_pts, | |
const SbMediaVideoSampleInfo* video_sample_info, | |
const SbDrmSampleInfo* sample_drm_info) { | |
buffer_ = new ReferenceCountedBuffer( | |
deallocate_sample_func, player, context, sample_buffer, | |
sample_buffer_size, sample_pts, video_sample_info, sample_drm_info); | |
buffer_->AddRef(); | |
} | |
InputBuffer::InputBuffer(const InputBuffer& that) { | |
buffer_ = that.buffer_; | |
if (buffer_) { | |
buffer_->AddRef(); | |
} | |
} | |
InputBuffer::~InputBuffer() { | |
if (buffer_) { | |
buffer_->Release(); | |
} | |
} | |
InputBuffer& InputBuffer::operator=(const InputBuffer& that) { | |
if (that.buffer_) { | |
that.buffer_->AddRef(); | |
} | |
if (buffer_) { | |
buffer_->Release(); | |
} | |
buffer_ = that.buffer_; | |
return *this; | |
} | |
const uint8_t* InputBuffer::data() const { | |
SB_DCHECK(buffer_); | |
return buffer_->data(); | |
} | |
int InputBuffer::size() const { | |
SB_DCHECK(buffer_); | |
return buffer_->size(); | |
} | |
SbMediaTime InputBuffer::pts() const { | |
SB_DCHECK(buffer_); | |
return buffer_->pts(); | |
} | |
const SbMediaVideoSampleInfo* InputBuffer::video_sample_info() const { | |
SB_DCHECK(buffer_); | |
return buffer_->video_sample_info(); | |
} | |
const SbDrmSampleInfo* InputBuffer::drm_info() const { | |
SB_DCHECK(buffer_); | |
return buffer_->drm_info(); | |
} | |
void InputBuffer::SetDecryptedContent(const void* buffer, int size) { | |
SB_DCHECK(buffer_); | |
buffer_->SetDecryptedContent(buffer, size); | |
} | |
} // namespace player | |
} // namespace starboard | |
} // namespace shared | |
} // namespace starboard |