blob: 0b49905a88b0fad09c7bc3134c624bd4b5784cbb [file] [log] [blame]
// Copyright 2020 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/filter/player_components.h"
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include "starboard/common/scoped_ptr.h"
#include "starboard/media.h"
#include "starboard/player.h"
#include "starboard/shared/starboard/player/filter/testing/test_util.h"
#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
#include "starboard/shared/starboard/player/job_queue.h"
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "starboard/testing/fake_graphics_context_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace starboard {
namespace shared {
namespace starboard {
namespace player {
namespace filter {
namespace testing {
namespace {
using ::starboard::testing::FakeGraphicsContextProvider;
using std::string;
using std::unique_ptr;
using std::vector;
using ::testing::ValuesIn;
using video_dmp::VideoDmpReader;
typedef VideoDmpReader::AudioAccessUnit AudioAccessUnit;
typedef VideoDmpReader::VideoAccessUnit VideoAccessUnit;
typedef PlayerComponents::Factory::CreationParameters CreationParameters;
typedef std::tuple<const char*, const char*, SbPlayerOutputMode>
PlayerComponentsTestParam;
const SbTimeMonotonic kDefaultPrerollTimeOut = 5 * kSbTimeSecond;
const SbTimeMonotonic kDefaultEndTimeOut = 5 * kSbTimeSecond;
const SbTimeMonotonic kDefaultWriteTimeOut = 5 * kSbTimeSecond;
const SbPlayer kDummyPlayer = reinterpret_cast<SbPlayer>(1);
class PlayerComponentsTest
: public ::testing::TestWithParam<PlayerComponentsTestParam> {
protected:
PlayerComponentsTest()
: audio_filename_(std::get<0>(GetParam())),
video_filename_(std::get<1>(GetParam())),
output_mode_(std::get<2>(GetParam())) {
SB_LOG(INFO) << "Testing: \"" << audio_filename_ << "\", \""
<< video_filename_
<< (output_mode_ == kSbPlayerOutputModeDecodeToTexture
? "\", kSbPlayerOutputModeDecodeToTexture."
: "\", kSbPlayerOutputModePunchOut.");
}
void SetUp() override {
if (audio_filename_.length() > 0) {
audio_reader_.reset(new VideoDmpReader(
ResolveTestFileName(audio_filename_.c_str()).c_str(),
VideoDmpReader::kEnableReadOnDemand));
}
if (video_filename_.length() > 0) {
video_reader_.reset(new VideoDmpReader(
ResolveTestFileName(video_filename_.c_str()).c_str(),
VideoDmpReader::kEnableReadOnDemand));
}
scoped_ptr<PlayerComponents::Factory> factory =
PlayerComponents::Factory::Create();
string error_message;
if (audio_reader_ && video_reader_) {
CreationParameters creation_parameters(
audio_reader_->audio_codec(), audio_reader_->audio_sample_info(),
video_reader_->video_codec(),
#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
video_reader_->GetPlayerSampleInfo(kSbMediaTypeVideo, 0)
.video_sample_info,
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
kDummyPlayer, output_mode_,
fake_graphics_context_provider_.decoder_target_provider());
player_components_ =
factory->CreateComponents(creation_parameters, &error_message);
} else if (audio_reader_) {
// Audio only
CreationParameters creation_parameters(
audio_reader_->audio_codec(), audio_reader_->audio_sample_info());
player_components_ =
factory->CreateComponents(creation_parameters, &error_message);
} else {
// Video only
ASSERT_TRUE(video_reader_);
CreationParameters creation_parameters(
video_reader_->video_codec(),
#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
video_reader_->GetPlayerSampleInfo(kSbMediaTypeVideo, 0)
.video_sample_info,
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
kDummyPlayer, output_mode_,
fake_graphics_context_provider_.decoder_target_provider());
player_components_ =
factory->CreateComponents(creation_parameters, &error_message);
}
ASSERT_TRUE(player_components_);
if (GetAudioRenderer()) {
GetAudioRenderer()->Initialize(
std::bind(&PlayerComponentsTest::OnError, this),
std::bind(&PlayerComponentsTest::OnPrerolled, this,
kSbMediaTypeAudio),
std::bind(&PlayerComponentsTest::OnEnded, this, kSbMediaTypeAudio));
}
SetPlaybackRate(playback_rate_);
if (GetVideoRenderer()) {
GetVideoRenderer()->Initialize(
std::bind(&PlayerComponentsTest::OnError, this),
std::bind(&PlayerComponentsTest::OnPrerolled, this,
kSbMediaTypeVideo),
std::bind(&PlayerComponentsTest::OnEnded, this, kSbMediaTypeVideo));
}
}
MediaTimeProvider* GetMediaTimeProvider() const {
return player_components_->GetMediaTimeProvider();
}
AudioRenderer* GetAudioRenderer() const {
return player_components_->GetAudioRenderer();
}
VideoRenderer* GetVideoRenderer() const {
return player_components_->GetVideoRenderer();
}
bool IsPlaybackPrerolled() {
if (GetAudioRenderer() && !audio_prerolled_) {
return false;
}
if (GetVideoRenderer() && !video_prerolled_) {
return false;
}
return true;
}
bool IsPlaybackEnded() {
if (GetAudioRenderer() && !audio_ended_) {
return false;
}
if (GetVideoRenderer() && !video_ended_) {
return false;
}
return true;
}
void Seek(SbTime seek_to_time) {
has_error_ = false;
audio_prerolled_ = false;
video_prerolled_ = false;
audio_ended_ = false;
video_ended_ = false;
audio_index_ = 0;
video_index_ = 0;
// Find the closest key frame prior to |seek_to_time|.
if (GetAudioRenderer()) {
for (int index = 1; index < audio_reader_->number_of_audio_buffers();
index++) {
SbPlayerSampleInfo sample_info =
audio_reader_->GetPlayerSampleInfo(kSbMediaTypeAudio, index);
if (sample_info.timestamp > seek_to_time) {
break;
}
audio_index_ = index;
}
}
if (GetVideoRenderer()) {
for (int index = 1; index < video_reader_->number_of_video_buffers();
index++) {
SbPlayerSampleInfo sample_info =
video_reader_->GetPlayerSampleInfo(kSbMediaTypeVideo, index);
if (sample_info.timestamp > seek_to_time) {
break;
}
if (sample_info.video_sample_info.is_key_frame) {
video_index_ = index;
}
}
}
GetMediaTimeProvider()->Pause();
if (GetVideoRenderer()) {
GetVideoRenderer()->Seek(seek_to_time);
}
GetMediaTimeProvider()->Seek(seek_to_time);
}
void Play() { GetMediaTimeProvider()->Play(); }
void Pause() { GetMediaTimeProvider()->Pause(); }
void SetPlaybackRate(double playback_rate) {
playback_rate_ = playback_rate;
GetMediaTimeProvider()->SetPlaybackRate(playback_rate_);
}
SbTime GetMediaTime() {
bool is_playing, is_eos_played, is_underflow;
double playback_rate;
return GetMediaTimeProvider()->GetCurrentMediaTime(
&is_playing, &is_eos_played, &is_underflow, &playback_rate);
}
bool IsPlaying() {
bool is_playing, is_eos_played, is_underflow;
double playback_rate;
GetMediaTimeProvider()->GetCurrentMediaTime(&is_playing, &is_eos_played,
&is_underflow, &playback_rate);
return is_playing;
}
SbTime GetCurrentAudioBufferTimestamp() const {
if (!GetAudioRenderer()) {
return 0;
}
if (audio_index_ >= audio_reader_->number_of_audio_buffers()) {
return audio_reader_->audio_duration();
}
return audio_reader_->GetPlayerSampleInfo(kSbMediaTypeAudio, audio_index_)
.timestamp;
}
SbTime GetCurrentVideoBufferTimestamp() const {
if (!GetVideoRenderer()) {
return 0;
}
if (video_index_ >= video_reader_->number_of_video_buffers()) {
return video_reader_->video_duration();
}
if (video_index_ >= video_reader_->number_of_video_buffers() - 1) {
return video_reader_->GetPlayerSampleInfo(kSbMediaTypeVideo, video_index_)
.timestamp;
}
// The buffers are ordered by decoding order. We need to find the
// presentation timestamp of next frame.
SbTime next_timestamps[2] = {
video_reader_->GetPlayerSampleInfo(kSbMediaTypeVideo, video_index_)
.timestamp,
video_reader_->GetPlayerSampleInfo(kSbMediaTypeVideo, video_index_ + 1)
.timestamp};
return std::min(next_timestamps[0], next_timestamps[1]);
}
void WriteDataUntilPrerolled(SbTime timeout = kDefaultPrerollTimeOut) {
SbTimeMonotonic start_time = SbTimeGetMonotonicNow();
while (!IsPlaybackPrerolled()) {
ASSERT_LE(SbTimeGetMonotonicNow() - start_time, timeout);
bool written =
TryToWriteOneInputBuffer(GetMediaTime() + kMaxWriteAheadDuration);
if (!written) {
ASSERT_NO_FATAL_FAILURE(RenderAndProcessPendingJobs());
SbThreadSleep(5 * kSbTimeMillisecond);
}
}
}
void WriteDataUntil(SbTime timestamp, SbTime timeout = kDefaultWriteTimeOut) {
SB_CHECK(playback_rate_ != 0);
SbTimeMonotonic last_input_filled_time = SbTimeGetMonotonicNow();
while (
(GetAudioRenderer() && GetCurrentAudioBufferTimestamp() < timestamp) ||
(GetVideoRenderer() && GetCurrentVideoBufferTimestamp() < timestamp)) {
if (last_input_filled_time != -1) {
ASSERT_LE(SbTimeGetMonotonicNow() - last_input_filled_time, timeout);
}
bool written = TryToWriteOneInputBuffer(timestamp);
if (written) {
last_input_filled_time = SbTimeGetMonotonicNow();
} else {
ASSERT_NO_FATAL_FAILURE(RenderAndProcessPendingJobs());
SbThreadSleep(5 * kSbTimeMillisecond);
}
}
}
void WriteEOS() {
if (GetAudioRenderer()) {
GetAudioRenderer()->WriteEndOfStream();
}
if (GetVideoRenderer()) {
GetVideoRenderer()->WriteEndOfStream();
}
}
void WaitUntilPlaybackEnded() {
SB_CHECK(playback_rate_ != 0);
SbTime duration = std::max(GetCurrentAudioBufferTimestamp(),
GetCurrentVideoBufferTimestamp());
SbTime current_time = GetMediaTime();
SbTime expected_end_time =
SbTimeGetMonotonicNow() +
static_cast<SbTime>((duration - current_time) / playback_rate_) +
kDefaultEndTimeOut;
while (!IsPlaybackEnded()) {
// If this fails, timeout must have been reached.
ASSERT_LE(SbTimeGetMonotonicNow(), expected_end_time);
ASSERT_NO_FATAL_FAILURE(RenderAndProcessPendingJobs());
SbThreadSleep(5 * kSbTimeMillisecond);
}
current_time = GetMediaTime();
// TODO: investigate and reduce the tolerance.
ASSERT_LE(std::abs(current_time - duration), 500 * kSbTimeMillisecond);
}
// This function needs to be called periodically to keep player components
// working.
void RenderAndProcessPendingJobs() {
// Call GetCurrentDecodeTarget() periodically for decode to texture mode.
if (output_mode_ == kSbPlayerOutputModeDecodeToTexture &&
GetVideoRenderer()) {
#if SB_HAS(GLES2)
fake_graphics_context_provider_.RunOnGlesContextThread(
std::bind(&PlayerComponentsTest::RenderOnGlesContextThread, this));
#endif // SB_HAS(GLES2)
}
// Process jobs in the job queue.
job_queue_.RunUntilIdle();
ASSERT_FALSE(has_error_);
}
private:
// We won't write audio data more than 1s ahead of current media time in
// cobalt. So, to test with the same condition, we limit max inputs ahead to
// 1s in the tests.
const SbTime kMaxWriteAheadDuration = kSbTimeSecond;
void OnError() { has_error_ = true; }
void OnPrerolled(SbMediaType media_type) {
if (media_type == kSbMediaTypeAudio) {
audio_prerolled_ = true;
} else {
EXPECT_EQ(media_type, kSbMediaTypeVideo);
video_prerolled_ = true;
}
}
void OnEnded(SbMediaType media_type) {
if (media_type == kSbMediaTypeAudio) {
audio_ended_ = true;
} else {
EXPECT_EQ(media_type, kSbMediaTypeVideo);
video_ended_ = true;
}
}
scoped_refptr<InputBuffer> GetAudioInputBuffer(size_t index) const {
auto player_sample_info =
audio_reader_->GetPlayerSampleInfo(kSbMediaTypeAudio, index);
#if SB_API_VERSION >= 11
auto input_buffer = new InputBuffer(StubDeallocateSampleFunc, nullptr,
nullptr, player_sample_info);
#else // SB_API_VERSION >= 11
SbMediaAudioSampleInfo audio_sample_info =
audio_reader_->GetAudioSampleInfo(index);
auto input_buffer =
new InputBuffer(kSbMediaTypeAudio, StubDeallocateSampleFunc, nullptr,
nullptr, player_sample_info, &audio_sample_info);
#endif // SB_API_VERSION >= 11
return input_buffer;
}
scoped_refptr<InputBuffer> GetVideoInputBuffer(size_t index) const {
auto video_sample_info =
video_reader_->GetPlayerSampleInfo(kSbMediaTypeVideo, index);
#if SB_API_VERSION >= 11
auto input_buffer = new InputBuffer(StubDeallocateSampleFunc, NULL, NULL,
video_sample_info);
#else // SB_API_VERSION >= 11
auto input_buffer =
new InputBuffer(kSbMediaTypeVideo, StubDeallocateSampleFunc, NULL, NULL,
video_sample_info, NULL);
#endif // SB_API_VERSION >= 11
return input_buffer;
}
void RenderOnGlesContextThread() {
SbDecodeTargetRelease(GetVideoRenderer()->GetCurrentDecodeTarget());
}
bool TryToWriteOneInputBuffer(SbTime max_timestamp) {
bool input_buffer_written = false;
if (GetAudioRenderer() && GetAudioRenderer()->CanAcceptMoreData() &&
audio_index_ < audio_reader_->number_of_audio_buffers() &&
GetCurrentAudioBufferTimestamp() < max_timestamp) {
GetAudioRenderer()->WriteSample(GetAudioInputBuffer(audio_index_++));
input_buffer_written = true;
}
if (GetVideoRenderer() && GetVideoRenderer()->CanAcceptMoreData() &&
video_index_ < video_reader_->number_of_video_buffers() &&
GetCurrentVideoBufferTimestamp() < max_timestamp) {
GetVideoRenderer()->WriteSample(GetVideoInputBuffer(video_index_++));
input_buffer_written = true;
}
if (input_buffer_written) {
job_queue_.RunUntilIdle();
}
return input_buffer_written;
}
const std::string audio_filename_;
const std::string video_filename_;
const SbPlayerOutputMode output_mode_;
JobQueue job_queue_;
FakeGraphicsContextProvider fake_graphics_context_provider_;
unique_ptr<VideoDmpReader> audio_reader_;
unique_ptr<VideoDmpReader> video_reader_;
scoped_ptr<PlayerComponents> player_components_;
double playback_rate_ = 1.0;
int audio_index_ = 0;
int video_index_ = 0;
bool has_error_ = false;
bool audio_prerolled_ = false;
bool video_prerolled_ = false;
bool audio_ended_ = false;
bool video_ended_ = false;
};
TEST_P(PlayerComponentsTest, Preroll) {
Seek(0);
ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
}
TEST_P(PlayerComponentsTest, SunnyDay) {
Seek(0);
ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
ASSERT_EQ(GetMediaTime(), 0);
ASSERT_FALSE(IsPlaying());
SbTimeMonotonic play_requested_at = SbTimeGetMonotonicNow();
Play();
SbTime media_duration = std::max(GetCurrentVideoBufferTimestamp(),
GetCurrentAudioBufferTimestamp());
media_duration = std::max(kSbTimeSecond, media_duration);
ASSERT_NO_FATAL_FAILURE(WriteDataUntil(media_duration));
ASSERT_NO_FATAL_FAILURE(WriteEOS());
ASSERT_NO_FATAL_FAILURE(WaitUntilPlaybackEnded());
// TODO: investigate and reduce the tolerance.
// ASSERT_LE(
// std::abs(SbTimeGetMonotonicNow() - (play_requested_at +
// media_duration)), 300 * kSbTimeMillisecond);
}
TEST_P(PlayerComponentsTest, ShortPlayback) {
Seek(0);
ASSERT_NO_FATAL_FAILURE(WriteDataUntil(50 * kSbTimeMillisecond));
ASSERT_NO_FATAL_FAILURE(WriteEOS());
Play();
ASSERT_NO_FATAL_FAILURE(WaitUntilPlaybackEnded());
}
TEST_P(PlayerComponentsTest, EOSWithoutInput) {
Seek(0);
ASSERT_NO_FATAL_FAILURE(WriteEOS());
Play();
ASSERT_NO_FATAL_FAILURE(WaitUntilPlaybackEnded());
// TODO: investigate and reduce the tolerance.
// ASSERT_LE(std::abs(GetMediaTime()), 100 * kSbTimeMillisecond);
}
TEST_P(PlayerComponentsTest, Pause) {
Seek(0);
ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
Play();
ASSERT_NO_FATAL_FAILURE(WriteDataUntil(kSbTimeSecond));
Pause();
ASSERT_FALSE(IsPlaying());
SbTimeMonotonic start_time = SbTimeGetMonotonicNow();
while (SbTimeGetMonotonicNow() < start_time + 200 * kSbTimeMillisecond) {
ASSERT_NO_FATAL_FAILURE(RenderAndProcessPendingJobs());
SbThreadSleep(5 * kSbTimeMillisecond);
}
SbTime media_time = GetMediaTime();
start_time = SbTimeGetMonotonicNow();
while (SbTimeGetMonotonicNow() < start_time + 200 * kSbTimeMillisecond) {
ASSERT_NO_FATAL_FAILURE(RenderAndProcessPendingJobs());
SbThreadSleep(5 * kSbTimeMillisecond);
}
ASSERT_EQ(media_time, GetMediaTime());
Play();
ASSERT_NO_FATAL_FAILURE(WriteDataUntil(std::max(
GetCurrentAudioBufferTimestamp(), GetCurrentVideoBufferTimestamp())));
ASSERT_NO_FATAL_FAILURE(WriteEOS());
ASSERT_NO_FATAL_FAILURE(WaitUntilPlaybackEnded());
}
// TODO: Enable variable playback rate tests
// TEST_P(PlayerComponentsTest, PlaybackRateHalf) {
// const double kPlaybackRate = 0.5;
// Seek(0);
// SetPlaybackRate(kPlaybackRate);
// ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
// ASSERT_EQ(GetMediaTime(), 0);
// ASSERT_FALSE(IsPlaying());
// SbTime media_duration_to_write = std::max(GetCurrentVideoBufferTimestamp(),
// GetCurrentAudioBufferTimestamp());
// media_duration_to_write = std::max(kSbTimeSecond, media_duration_to_write);
// SbTime media_duration_to_play =
// static_cast<SbTime>(media_duration_to_write / kPlaybackRate);
// SbTimeMonotonic play_requested_at = SbTimeGetMonotonicNow();
// Play();
// ASSERT_NO_FATAL_FAILURE(WriteDataUntil(media_duration_to_write));
// ASSERT_NO_FATAL_FAILURE(WriteEOS());
// ASSERT_NO_FATAL_FAILURE(WaitUntilPlaybackEnded());
// TODO: Enable the below check after we improve the accuracy of varied
// playback rate time reporting.
// ASSERT_GE(SbTimeGetMonotonicNow(),
// play_requested_at + media_duration_to_play - 200 *
// kSbTimeMillisecond);
// }
// TEST_P(PlayerComponentsTest, PlaybackRateDouble) {
// const double kPlaybackRate = 2.0;
// Seek(0);
// SetPlaybackRate(kPlaybackRate);
// ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
// ASSERT_EQ(GetMediaTime(), 0);
// ASSERT_FALSE(IsPlaying());
// SbTime media_duration_to_write = std::max(GetCurrentVideoBufferTimestamp(),
// GetCurrentAudioBufferTimestamp());
// media_duration_to_write =
// std::max(kSbTimeSecond * 2, media_duration_to_write);
// SbTime media_duration_to_play =
// static_cast<SbTime>(media_duration_to_write / kPlaybackRate);
// SbTimeMonotonic play_requested_at = SbTimeGetMonotonicNow();
// Play();
// ASSERT_NO_FATAL_FAILURE(WriteDataUntil(media_duration_to_write));
// ASSERT_NO_FATAL_FAILURE(WriteEOS());
// ASSERT_NO_FATAL_FAILURE(WaitUntilPlaybackEnded());
// playback rate time reporting.
// ASSERT_LE(SbTimeGetMonotonicNow(),
// play_requested_at + media_duration_to_play + 200 *
// kSbTimeMillisecond);
// }
TEST_P(PlayerComponentsTest, SeekForward) {
SbTime seek_to_time = 0;
Seek(seek_to_time);
ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
ASSERT_EQ(GetMediaTime(), seek_to_time);
ASSERT_FALSE(IsPlaying());
Play();
ASSERT_NO_FATAL_FAILURE(WriteDataUntil(kSbTimeSecond));
Pause();
seek_to_time = 2 * kSbTimeSecond;
Seek(seek_to_time);
ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
ASSERT_EQ(GetMediaTime(), seek_to_time);
ASSERT_FALSE(IsPlaying());
Play();
ASSERT_NO_FATAL_FAILURE(WriteDataUntil(seek_to_time + kSbTimeSecond));
ASSERT_NO_FATAL_FAILURE(WriteEOS());
ASSERT_NO_FATAL_FAILURE(WaitUntilPlaybackEnded());
}
TEST_P(PlayerComponentsTest, SeekBackward) {
SbTime seek_to_time = 3 * kSbTimeSecond;
Seek(seek_to_time);
ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
ASSERT_EQ(GetMediaTime(), seek_to_time);
ASSERT_FALSE(IsPlaying());
Play();
ASSERT_NO_FATAL_FAILURE(WriteDataUntil(seek_to_time + kSbTimeSecond));
Pause();
seek_to_time = 1 * kSbTimeSecond;
Seek(seek_to_time);
ASSERT_NO_FATAL_FAILURE(WriteDataUntilPrerolled());
ASSERT_EQ(GetMediaTime(), seek_to_time);
ASSERT_FALSE(IsPlaying());
Play();
ASSERT_NO_FATAL_FAILURE(WriteDataUntil(seek_to_time + kSbTimeSecond));
ASSERT_NO_FATAL_FAILURE(WriteEOS());
ASSERT_NO_FATAL_FAILURE(WaitUntilPlaybackEnded());
}
PlayerComponentsTestParam CreateParam(const char* audio_file,
const VideoTestParam& video_param) {
return std::make_tuple(audio_file, std::get<0>(video_param),
std::get<1>(video_param));
}
vector<PlayerComponentsTestParam> GetSupportedCreationParameters() {
vector<PlayerComponentsTestParam> supported_parameters;
// TODO: Enable tests of "heaac.dmp".
vector<const char*> audio_files = GetSupportedAudioTestFiles(false, false);
vector<VideoTestParam> video_params = GetSupportedVideoTests();
// Filter too short dmp files, as the tests need at least 4s of data.
for (auto iter = audio_files.begin(); iter != audio_files.end();) {
VideoDmpReader audio_dmp_reader(ResolveTestFileName(*iter).c_str(),
VideoDmpReader::kEnableReadOnDemand);
if (audio_dmp_reader.audio_duration() < 5 * kSbTimeSecond) {
iter = audio_files.erase(iter);
} else {
iter++;
}
}
for (auto iter = video_params.begin(); iter != video_params.end();) {
VideoDmpReader video_dmp_reader(
ResolveTestFileName(std::get<0>(*iter)).c_str(),
VideoDmpReader::kEnableReadOnDemand);
if (video_dmp_reader.video_duration() < 5 * kSbTimeSecond) {
iter = video_params.erase(iter);
} else {
iter++;
}
}
for (size_t i = 0; i < video_params.size(); i++) {
supported_parameters.push_back(CreateParam("", video_params[i]));
for (size_t j = 0; j < audio_files.size(); j++) {
supported_parameters.push_back(
CreateParam(audio_files[j], video_params[i]));
}
}
SB_DCHECK(supported_parameters.size() < 50)
<< "There're " << supported_parameters.size()
<< " tests added. It may take too long time to run and result in timeout";
for (size_t i = 0; i < audio_files.size(); i++) {
if (VideoDecoder::OutputModeSupported(kSbPlayerOutputModeDecodeToTexture,
kSbMediaVideoCodecNone,
kSbDrmSystemInvalid)) {
supported_parameters.push_back(std::make_tuple(
audio_files[i], "", kSbPlayerOutputModeDecodeToTexture));
}
if (VideoDecoder::OutputModeSupported(kSbPlayerOutputModePunchOut,
kSbMediaVideoCodecNone,
kSbDrmSystemInvalid)) {
supported_parameters.push_back(
std::make_tuple(audio_files[i], "", kSbPlayerOutputModePunchOut));
}
}
return supported_parameters;
}
INSTANTIATE_TEST_CASE_P(PlayerComponentsTests,
PlayerComponentsTest,
ValuesIn(GetSupportedCreationParameters()));
} // namespace
} // namespace testing
} // namespace filter
} // namespace player
} // namespace starboard
} // namespace shared
} // namespace starboard