blob: 27506202664afce58bb2b750a04d8d96f3fa794e [file] [log] [blame]
// Copyright 2019 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 <string>
#include "starboard/common/log.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/configuration_constants.h"
#include "starboard/directory.h"
#include "starboard/event.h"
#include "starboard/player.h"
#include "starboard/shared/starboard/player/filter/audio_renderer_internal.h"
#include "starboard/shared/starboard/player/filter/player_components.h"
#include "starboard/shared/starboard/player/input_buffer_internal.h"
#include "starboard/shared/starboard/player/job_thread.h"
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "starboard/system.h"
#if SB_HAS(PLAYER_FILTER_TESTS)
namespace {
using starboard::shared::starboard::player::video_dmp::VideoDmpReader;
using starboard::shared::starboard::player::filter::AudioRenderer;
using starboard::shared::starboard::player::filter::PlayerComponents;
using starboard::shared::starboard::player::InputBuffer;
using starboard::shared::starboard::player::JobThread;
using starboard::scoped_ptr;
// TODO: Merge test file resolving function with the ones used in the player
// filter tests.
std::string GetTestInputDirectory() {
const size_t kPathSize = kSbFileMaxPath + 1;
std::vector<char> content_path(kPathSize);
SB_CHECK(SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
kPathSize));
std::string directory_path =
std::string(content_path.data()) + kSbFileSepChar + "test" +
kSbFileSepChar + "starboard" + kSbFileSepChar + "shared" +
kSbFileSepChar + "starboard" + kSbFileSepChar + "player" +
kSbFileSepChar + "testdata";
SB_CHECK(SbDirectoryCanOpen(directory_path.c_str()))
<< "Cannot open directory " << directory_path;
return directory_path;
}
std::string ResolveTestFileName(const char* filename) {
return GetTestInputDirectory() + kSbFileSepChar + filename;
}
scoped_ptr<VideoDmpReader> s_video_dmp_reader;
scoped_ptr<AudioRenderer> s_audio_renderer;
int s_audio_sample_index;
scoped_ptr<JobThread> s_job_thread;
SbTime s_duration;
static void DeallocateSampleFunc(SbPlayer player,
void* context,
const void* sample_buffer) {
SB_UNREFERENCED_PARAMETER(player);
SB_UNREFERENCED_PARAMETER(context);
SB_UNREFERENCED_PARAMETER(sample_buffer);
}
starboard::scoped_refptr<InputBuffer> GetAudioInputBuffer(size_t index) {
auto player_sample_info =
s_video_dmp_reader->GetPlayerSampleInfo(kSbMediaTypeAudio, index);
#if SB_API_VERSION >= 11
return new InputBuffer(DeallocateSampleFunc, NULL, NULL, player_sample_info);
#else // SB_API_VERSION >= 11
SbMediaAudioSampleInfo audio_sample_info =
s_video_dmp_reader->GetAudioSampleInfo(index);
return new InputBuffer(kSbMediaTypeAudio, DeallocateSampleFunc, NULL, NULL,
player_sample_info, &audio_sample_info);
#endif // SB_API_VERSION >= 11
}
void OnTimer() {
if (!s_audio_renderer->CanAcceptMoreData()) {
s_job_thread->job_queue()->Schedule(std::bind(OnTimer), kSbTimeMillisecond);
return;
}
if (s_audio_sample_index == s_video_dmp_reader->number_of_audio_buffers()) {
SB_LOG(INFO) << "EOS written, duration " << s_duration << " microseconds.";
s_audio_renderer->WriteEndOfStream();
return;
} else {
auto input_buffer = GetAudioInputBuffer(s_audio_sample_index);
s_duration = input_buffer->timestamp();
s_audio_renderer->WriteSample(input_buffer);
++s_audio_sample_index;
}
s_job_thread->job_queue()->Schedule(std::bind(OnTimer));
}
void ErrorCB(SbPlayerError error, const std::string& error_message) {
SB_NOTREACHED() << "ErrorCB is called with error " << error << ", "
<< error_message;
}
void PrerolledCB() {
SB_LOG(INFO) << "Playback started.";
s_audio_renderer->Play();
}
void EndedCB() {
SB_LOG(INFO) << "Playback finished.";
s_audio_renderer.reset();
s_video_dmp_reader.reset();
SbSystemRequestStop(0);
}
void Start(const char* filename) {
SB_LOG(INFO) << "Loading " << filename;
s_video_dmp_reader.reset(
new VideoDmpReader(ResolveTestFileName(filename).c_str()));
scoped_ptr<PlayerComponents> player_components = PlayerComponents::Create();
PlayerComponents::AudioParameters audio_parameters = {
s_video_dmp_reader->audio_codec(),
s_video_dmp_reader->audio_sample_info(), kSbDrmSystemInvalid};
std::string error_message;
s_audio_renderer =
player_components->CreateAudioRenderer(audio_parameters, &error_message);
SB_DCHECK(s_audio_renderer);
using std::placeholders::_1;
using std::placeholders::_2;
s_audio_renderer->Initialize(std::bind(ErrorCB, _1, _2),
std::bind(PrerolledCB), std::bind(EndedCB));
s_audio_renderer->SetPlaybackRate(1.0);
s_audio_renderer->SetVolume(1.0);
s_audio_renderer->Seek(0);
s_job_thread->job_queue()->Schedule(std::bind(OnTimer));
}
} // namespace
void SbEventHandle(const SbEvent* event) {
switch (event->type) {
case kSbEventTypeStart: {
SbEventStartData* data = static_cast<SbEventStartData*>(event->data);
SB_DCHECK(data);
if (data->argument_count < 2) {
SB_LOG(INFO) << "Usage: audio_dmp_player <dmp file name>";
SB_LOG(INFO)
<< "e.g. audio_dmp_player beneath_the_canopy_aac_stereo.dmp";
SB_LOG(INFO)
<< " audio_dmp_player beneath_the_canopy_opus_stereo.dmp";
SbSystemRequestStop(0);
return;
}
s_job_thread.reset(new JobThread("audio"));
s_job_thread->job_queue()->Schedule(
std::bind(Start, data->argument_values[1]));
break;
}
case kSbEventTypeStop: {
s_job_thread.reset();
break;
}
default:
break;
}
}
#else // SB_HAS(PLAYER_FILTER_TESTS)
void SbEventHandle(const SbEvent* event) {
switch (event->type) {
case kSbEventTypeStart:
SB_LOG(INFO) << "\"audio_dmp_player\" is only support in SB_API_VERSION"
<< " 10 or later, or when SB_HAS_PLAYER_FILTER_TESTS is"
<< " defined.";
SbSystemRequestStop(0);
break;
default:
break;
}
}
#endif // SB_HAS(PLAYER_FILTER_TESTS)