blob: bc9d74de57ca265ee469d8657d3fc0fcf7c9e6b3 [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 "starboard/shared/starboard/player/player_internal.h"
#include "starboard/log.h"
using starboard::shared::starboard::player::InputBuffer;
namespace {
const SbTime kUpdateInterval = 5 * kSbTimeMillisecond;
SbMediaTime GetMediaTime(SbMediaTime media_pts,
SbTimeMonotonic media_pts_update_time) {
SbTimeMonotonic elapsed = SbTimeGetMonotonicNow() - media_pts_update_time;
return media_pts + elapsed * kSbMediaTimeSecond / kSbTimeSecond;
}
} // namespace
SbPlayerPrivate::SbPlayerPrivate(
SbMediaTime duration_pts,
SbPlayerDeallocateSampleFunc sample_deallocate_func,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
void* context,
starboard::scoped_ptr<PlayerWorker::Handler> player_worker_handler)
: sample_deallocate_func_(sample_deallocate_func),
context_(context),
ticket_(SB_PLAYER_INITIAL_TICKET),
duration_pts_(duration_pts),
media_pts_(0),
media_pts_update_time_(SbTimeGetMonotonicNow()),
frame_width_(0),
frame_height_(0),
is_paused_(true),
volume_(1.0),
total_video_frames_(0),
worker_(new PlayerWorker(this,
player_worker_handler.Pass(),
decoder_status_func,
player_status_func,
this,
kUpdateInterval,
context)) {}
void SbPlayerPrivate::Seek(SbMediaTime seek_to_pts, int ticket) {
{
starboard::ScopedLock lock(mutex_);
SB_DCHECK(ticket_ != ticket);
media_pts_ = seek_to_pts;
media_pts_update_time_ = SbTimeGetMonotonicNow();
ticket_ = ticket;
}
PlayerWorker::SeekEventData data = {seek_to_pts, ticket};
worker_->EnqueueEvent(data);
}
void SbPlayerPrivate::WriteSample(
SbMediaType sample_type,
const void* sample_buffer,
int sample_buffer_size,
SbMediaTime sample_pts,
const SbMediaVideoSampleInfo* video_sample_info,
const SbDrmSampleInfo* sample_drm_info) {
if (sample_type == kSbMediaTypeVideo) {
++total_video_frames_;
}
InputBuffer* input_buffer = new InputBuffer(
sample_deallocate_func_, this, context_, sample_buffer,
sample_buffer_size, sample_pts, video_sample_info, sample_drm_info);
PlayerWorker::WriteSampleEventData data = {sample_type, input_buffer};
worker_->EnqueueEvent(data);
}
void SbPlayerPrivate::WriteEndOfStream(SbMediaType stream_type) {
PlayerWorker::WriteEndOfStreamEventData data = {stream_type};
worker_->EnqueueEvent(data);
}
#if SB_IS(PLAYER_PUNCHED_OUT)
void SbPlayerPrivate::SetBounds(int x, int y, int width, int height) {
PlayerWorker::SetBoundsEventData data = {x, y, width, height};
worker_->EnqueueEvent(data);
// TODO: Wait until a frame is rendered with the updated bounds.
}
#endif
void SbPlayerPrivate::GetInfo(SbPlayerInfo* out_player_info) {
SB_DCHECK(out_player_info != NULL);
starboard::ScopedLock lock(mutex_);
out_player_info->duration_pts = duration_pts_;
if (is_paused_) {
out_player_info->current_media_pts = media_pts_;
} else {
out_player_info->current_media_pts =
GetMediaTime(media_pts_, media_pts_update_time_);
}
out_player_info->frame_width = frame_width_;
out_player_info->frame_height = frame_height_;
out_player_info->is_paused = is_paused_;
out_player_info->volume = volume_;
out_player_info->total_video_frames = total_video_frames_;
out_player_info->dropped_video_frames = 0;
out_player_info->corrupted_video_frames = 0;
}
void SbPlayerPrivate::SetPause(bool pause) {
PlayerWorker::SetPauseEventData data = {pause};
worker_->EnqueueEvent(data);
}
void SbPlayerPrivate::SetVolume(double volume) {
SB_NOTIMPLEMENTED();
}
void SbPlayerPrivate::UpdateMediaTime(SbMediaTime media_time, int ticket) {
starboard::ScopedLock lock(mutex_);
if (ticket_ != ticket) {
return;
}
media_pts_ = media_time;
media_pts_update_time_ = SbTimeGetMonotonicNow();
}