blob: 50ac184e2a40a7a3cd2a88352c7a5484d956e3e3 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/test/video_player/video_player.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "media/gpu/macros.h"
#include "media/gpu/test/video.h"
#include "media/gpu/test/video_player/video_decoder_client.h"
namespace media {
namespace test {
namespace {
// Get the name of the specified video player |event|.
const char* EventName(VideoPlayerEvent event) {
switch (event) {
case VideoPlayerEvent::kInitialized:
return "Initialized";
case VideoPlayerEvent::kFrameDecoded:
return "FrameDecoded";
case VideoPlayerEvent::kFlushing:
return "Flushing";
case VideoPlayerEvent::kFlushDone:
return "FlushDone";
case VideoPlayerEvent::kResetting:
return "Resetting";
case VideoPlayerEvent::kResetDone:
return "ResetDone";
case VideoPlayerEvent::kConfigInfo:
return "ConfigInfo";
default:
return "Unknown";
}
}
} // namespace
VideoPlayer::VideoPlayer()
: event_cv_(&event_lock_), video_player_event_counts_{}, event_id_(0) {}
VideoPlayer::~VideoPlayer() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOGF(4);
Destroy();
}
// static
std::unique_ptr<VideoPlayer> VideoPlayer::Create(
const VideoDecoderClientConfig& config,
gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
std::unique_ptr<FrameRenderer> frame_renderer,
std::vector<std::unique_ptr<VideoFrameProcessor>> frame_processors) {
auto video_player = base::WrapUnique(new VideoPlayer());
if (!video_player->CreateDecoderClient(config, gpu_memory_buffer_factory,
std::move(frame_renderer),
std::move(frame_processors))) {
return nullptr;
}
return video_player;
}
bool VideoPlayer::CreateDecoderClient(
const VideoDecoderClientConfig& config,
gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
std::unique_ptr<FrameRenderer> frame_renderer,
std::vector<std::unique_ptr<VideoFrameProcessor>> frame_processors) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(video_player_state_, VideoPlayerState::kUninitialized);
DCHECK(frame_renderer);
DVLOGF(4);
// base::Unretained is safe here as we will never receive callbacks after
// destroying the video player, since the video decoder client will be
// destroyed first.
EventCallback event_cb =
base::BindRepeating(&VideoPlayer::NotifyEvent, base::Unretained(this));
decoder_client_ = VideoDecoderClient::Create(
event_cb, gpu_memory_buffer_factory, std::move(frame_renderer),
std::move(frame_processors), config);
if (!decoder_client_) {
VLOGF(1) << "Failed to create video decoder client";
return false;
}
return true;
}
void VideoPlayer::Destroy() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_NE(video_player_state_, VideoPlayerState::kDestroyed);
DVLOGF(4);
decoder_client_.reset();
video_player_state_ = VideoPlayerState::kDestroyed;
}
void VideoPlayer::SetEventWaitTimeout(base::TimeDelta timeout) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOGF(4);
event_timeout_ = timeout;
}
bool VideoPlayer::Initialize(const Video* video) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(video_player_state_ == VideoPlayerState::kUninitialized ||
video_player_state_ == VideoPlayerState::kIdle);
DCHECK(video);
DVLOGF(4);
decoder_client_->Initialize(video);
// Wait until the video decoder is initialized.
if (!WaitForEvent(VideoPlayerEvent::kInitialized))
return false;
video_ = video;
video_player_state_ = VideoPlayerState::kIdle;
return true;
}
void VideoPlayer::Play() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(video_player_state_, VideoPlayerState::kIdle);
DVLOGF(4);
// Play until the end of the video.
PlayUntil(VideoPlayerEvent::kNumEvents, std::numeric_limits<size_t>::max());
}
void VideoPlayer::PlayUntil(VideoPlayerEvent event, size_t event_count) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(video_player_state_, VideoPlayerState::kIdle);
DCHECK(video_);
DVLOGF(4);
// Start decoding the video.
play_until_ = std::make_pair(event, event_count);
video_player_state_ = VideoPlayerState::kDecoding;
decoder_client_->Play();
}
void VideoPlayer::Reset() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOGF(4);
decoder_client_->Reset();
}
void VideoPlayer::Flush() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOGF(4);
decoder_client_->Flush();
}
base::TimeDelta VideoPlayer::GetCurrentTime() const {
NOTIMPLEMENTED();
return base::TimeDelta();
}
size_t VideoPlayer::GetCurrentFrame() const {
NOTIMPLEMENTED();
return 0;
}
VideoPlayerState VideoPlayer::GetState() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::AutoLock auto_lock(event_lock_);
return video_player_state_;
}
FrameRenderer* VideoPlayer::GetFrameRenderer() const {
return decoder_client_->GetFrameRenderer();
}
bool VideoPlayer::WaitForEvent(VideoPlayerEvent event, size_t times) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GE(times, 1u);
DVLOGF(4) << "Event: " << EventName(event);
base::TimeDelta time_waiting;
base::AutoLock auto_lock(event_lock_);
while (true) {
// TODO(dstaessens@) Investigate whether we really need to keep the full
// list of events for more complex testcases.
// Go through list of events since last wait, looking for the event we're
// interested in.
for (; event_id_ < video_player_events_.size(); ++event_id_) {
if (video_player_events_[event_id_] == event)
times--;
if (times == 0) {
event_id_++;
return true;
}
}
// Check whether we've exceeded the maximum time we're allowed to wait.
if (time_waiting >= event_timeout_) {
LOG(ERROR) << "Timeout while waiting for '" << EventName(event)
<< "' event";
return false;
}
const base::TimeTicks start_time = base::TimeTicks::Now();
event_cv_.TimedWait(event_timeout_ - time_waiting);
time_waiting += base::TimeTicks::Now() - start_time;
}
}
bool VideoPlayer::WaitForFlushDone() {
return WaitForEvent(VideoPlayerEvent::kFlushDone);
}
bool VideoPlayer::WaitForResetDone() {
return WaitForEvent(VideoPlayerEvent::kResetDone);
}
bool VideoPlayer::WaitForFrameDecoded(size_t times) {
return WaitForEvent(VideoPlayerEvent::kFrameDecoded, times);
}
size_t VideoPlayer::GetEventCount(VideoPlayerEvent event) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::AutoLock auto_lock(event_lock_);
return video_player_event_counts_[static_cast<size_t>(event)];
}
bool VideoPlayer::WaitForFrameProcessors() {
return !decoder_client_ || decoder_client_->WaitForFrameProcessors();
}
void VideoPlayer::WaitForRenderer() {
if (decoder_client_)
decoder_client_->WaitForRenderer();
}
size_t VideoPlayer::GetFlushDoneCount() const {
return GetEventCount(VideoPlayerEvent::kFlushDone);
}
size_t VideoPlayer::GetResetDoneCount() const {
return GetEventCount(VideoPlayerEvent::kResetDone);
}
size_t VideoPlayer::GetFrameDecodedCount() const {
return GetEventCount(VideoPlayerEvent::kFrameDecoded);
}
bool VideoPlayer::NotifyEvent(VideoPlayerEvent event) {
base::AutoLock auto_lock(event_lock_);
if (event == VideoPlayerEvent::kFlushDone ||
event == VideoPlayerEvent::kResetDone) {
video_player_state_ = VideoPlayerState::kIdle;
}
video_player_events_.push_back(event);
video_player_event_counts_[static_cast<size_t>(event)]++;
event_cv_.Signal();
// Check whether video playback should be paused after this event.
if (play_until_.first == event &&
play_until_.second ==
video_player_event_counts_[static_cast<size_t>(event)]) {
video_player_state_ = VideoPlayerState::kIdle;
return false;
}
return true;
}
} // namespace test
} // namespace media