blob: f9dd491e0636a7acf27e3cd2aa62bb63f28c1dfe [file] [log] [blame]
// Copyright 2017 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/audio_renderer_sink_impl.h"
#include "starboard/audio_sink.h"
#include "starboard/log.h"
#include "starboard/shared/starboard/thread_checker.h"
namespace starboard {
namespace shared {
namespace starboard {
namespace player {
namespace filter {
AudioRendererSinkImpl::AudioRendererSinkImpl()
: audio_sink_(kSbAudioSinkInvalid),
render_callback_(NULL),
playback_rate_(1.0),
volume_(1.0) {}
AudioRendererSinkImpl::~AudioRendererSinkImpl() {
SB_DCHECK(thread_checker_.CalledOnValidThread());
Stop();
}
bool AudioRendererSinkImpl::IsAudioSampleTypeSupported(
SbMediaAudioSampleType audio_sample_type) const {
return SbAudioSinkIsAudioSampleTypeSupported(audio_sample_type);
}
bool AudioRendererSinkImpl::IsAudioFrameStorageTypeSupported(
SbMediaAudioFrameStorageType audio_frame_storage_type) const {
return SbAudioSinkIsAudioFrameStorageTypeSupported(audio_frame_storage_type);
}
int AudioRendererSinkImpl::GetNearestSupportedSampleFrequency(
int sampling_frequency_hz) const {
return SbAudioSinkGetNearestSupportedSampleFrequency(sampling_frequency_hz);
}
bool AudioRendererSinkImpl::HasStarted() const {
return SbAudioSinkIsValid(audio_sink_);
}
void AudioRendererSinkImpl::Start(
int channels,
int sampling_frequency_hz,
SbMediaAudioSampleType audio_sample_type,
SbMediaAudioFrameStorageType audio_frame_storage_type,
SbAudioSinkFrameBuffers frame_buffers,
int frames_per_channel,
RenderCallback* render_callback) {
SB_DCHECK(thread_checker_.CalledOnValidThread());
SB_DCHECK(!HasStarted());
Stop();
render_callback_ = render_callback;
audio_sink_ = SbAudioSinkCreate(
channels, sampling_frequency_hz, audio_sample_type,
audio_frame_storage_type, frame_buffers, frames_per_channel,
&AudioRendererSinkImpl::UpdateSourceStatusFunc,
&AudioRendererSinkImpl::ConsumeFramesFunc, this);
if (!SbAudioSinkIsValid(audio_sink_)) {
return;
}
// TODO: Remove SetPlaybackRate() support from audio sink as it only need to
// support play/pause.
audio_sink_->SetPlaybackRate(playback_rate_);
audio_sink_->SetVolume(volume_);
}
void AudioRendererSinkImpl::Stop() {
SB_DCHECK(thread_checker_.CalledOnValidThread());
if (HasStarted()) {
SbAudioSinkDestroy(audio_sink_);
audio_sink_ = kSbAudioSinkInvalid;
render_callback_ = NULL;
}
}
void AudioRendererSinkImpl::SetVolume(double volume) {
SB_DCHECK(thread_checker_.CalledOnValidThread());
volume_ = volume;
if (HasStarted()) {
audio_sink_->SetVolume(volume);
}
}
void AudioRendererSinkImpl::SetPlaybackRate(double playback_rate) {
SB_DCHECK(thread_checker_.CalledOnValidThread());
SB_DCHECK(playback_rate == 0.0 || playback_rate == 1.0)
<< "Playback rate on audio sink can only be set to 0 or 1, "
<< "but is now set to " << playback_rate;
playback_rate_ = playback_rate;
if (HasStarted()) {
// TODO: Remove SetPlaybackRate() support from audio sink as it only need to
// support play/pause.
audio_sink_->SetPlaybackRate(playback_rate);
}
}
// static
void AudioRendererSinkImpl::UpdateSourceStatusFunc(int* frames_in_buffer,
int* offset_in_frames,
bool* is_playing,
bool* is_eos_reached,
void* context) {
AudioRendererSinkImpl* audio_renderer_sink =
static_cast<AudioRendererSinkImpl*>(context);
SB_DCHECK(audio_renderer_sink);
SB_DCHECK(audio_renderer_sink->render_callback_);
SB_DCHECK(frames_in_buffer);
SB_DCHECK(offset_in_frames);
SB_DCHECK(is_playing);
SB_DCHECK(is_eos_reached);
audio_renderer_sink->render_callback_->GetSourceStatus(
frames_in_buffer, offset_in_frames, is_playing, is_eos_reached);
}
// static
void AudioRendererSinkImpl::ConsumeFramesFunc(int frames_consumed,
#if SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
SbTime frames_consumed_at,
#endif // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
void* context) {
AudioRendererSinkImpl* audio_renderer_sink =
static_cast<AudioRendererSinkImpl*>(context);
SB_DCHECK(audio_renderer_sink);
SB_DCHECK(audio_renderer_sink->render_callback_);
#if SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
audio_renderer_sink->render_callback_->ConsumeFrames(frames_consumed,
frames_consumed_at);
#else // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
audio_renderer_sink->render_callback_->ConsumeFrames(frames_consumed);
#endif // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
}
} // namespace filter
} // namespace player
} // namespace starboard
} // namespace shared
} // namespace starboard