// Copyright 2022 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. | |
#ifndef STARBOARD_SHARED_UWP_AUDIO_RENDERER_PASSTHROUGH_H_ | |
#define STARBOARD_SHARED_UWP_AUDIO_RENDERER_PASSTHROUGH_H_ | |
#include <functional> | |
#include <queue> | |
#include "starboard/atomic.h" | |
#include "starboard/common/mutex.h" | |
#include "starboard/common/ref_counted.h" | |
#include "starboard/media.h" | |
#include "starboard/shared/internal_only.h" | |
#include "starboard/shared/starboard/media/media_util.h" | |
#include "starboard/shared/starboard/player/decoded_audio_internal.h" | |
#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h" | |
#include "starboard/shared/starboard/player/filter/audio_renderer_internal.h" | |
#include "starboard/shared/starboard/player/filter/media_time_provider.h" | |
#include "starboard/shared/starboard/player/input_buffer_internal.h" | |
#include "starboard/shared/starboard/player/job_queue.h" | |
#include "starboard/shared/uwp/wasapi_audio_sink.h" | |
#include "starboard/types.h" | |
namespace starboard { | |
namespace shared { | |
namespace uwp { | |
using ::starboard::shared::starboard::player::DecodedAudio; | |
using ::starboard::shared::starboard::player::JobQueue; | |
using ::starboard::shared::starboard::player::filter::AudioDecoder; | |
using ::starboard::shared::starboard::player::filter::AudioRenderer; | |
using ::starboard::shared::starboard::player::filter::MediaTimeProvider; | |
class AudioRendererPassthrough : public AudioRenderer, | |
public MediaTimeProvider, | |
private JobQueue::JobOwner { | |
public: | |
typedef starboard::media::AudioStreamInfo AudioStreamInfo; | |
AudioRendererPassthrough(scoped_ptr<AudioDecoder> audio_decoder, | |
const AudioStreamInfo& audio_stream_info); | |
~AudioRendererPassthrough() override; | |
void Initialize(const ErrorCB& error_cb, | |
const PrerolledCB& prerolled_cb, | |
const EndedCB& ended_cb) override; | |
void WriteSamples(const InputBuffers& input_buffers) override; | |
void WriteEndOfStream() override; | |
void SetVolume(double volume) override; | |
bool IsEndOfStreamWritten() const override; | |
bool IsEndOfStreamPlayed() const override; | |
bool CanAcceptMoreData() const override; | |
// MediaTimeProvider methods | |
void Play() override; | |
void Pause() override; | |
void SetPlaybackRate(double playback_rate) override; | |
void Seek(int64_t seek_to_time) override; | |
int64_t GetCurrentMediaTime(bool* is_playing, | |
bool* is_eos_played, | |
bool* is_underflow, | |
double* playback_rate) override; | |
private: | |
void OnDecoderConsumed(); | |
void OnDecoderOutput(); | |
void ProcessAudioBuffers(); | |
bool TryToWriteAudioBufferToSink(scoped_refptr<DecodedAudio> decoded_audio); | |
// After end of stream is written, stop the audio sink after it finishes audio | |
// output. | |
void TryToEndStream(); | |
// Calculates the playback time elapsed (microseconds) since the last time the | |
// timestamp was queried using WASAPIAudioSink::GetCurrentPlaybackTime(). | |
int64_t CalculateElapsedPlaybackTime(uint64_t update_time); | |
// Calculates the final output timestamp (microseconds) of a DecodedAudio. | |
int64_t CalculateLastOutputTime(scoped_refptr<DecodedAudio>& decoded_audio); | |
const int kMaxDecodedAudios = 16; | |
// About 250 ms of (E)AC3 audio. | |
const int kNumPrerollDecodedAudios = 8; | |
ErrorCB error_cb_; | |
PrerolledCB prerolled_cb_; | |
EndedCB ended_cb_; | |
Mutex mutex_; | |
bool paused_ = true; | |
bool seeking_ = false; | |
double playback_rate_ = 1.0; | |
int64_t seeking_to_time_ = 0; | |
atomic_bool end_of_stream_written_{false}; | |
atomic_bool end_of_stream_played_{false}; | |
// Use DecodedAudio to store decrypted and formatted encoded audio data. | |
std::queue<scoped_refptr<DecodedAudio>> pending_inputs_; | |
atomic_bool can_accept_more_data_; | |
JobQueue::JobToken process_audio_buffers_job_token_; | |
std::function<void()> process_audio_buffers_job_; | |
int64_t total_frames_sent_to_sink_ = 0; | |
int total_buffers_sent_to_sink_ = 0; | |
const int channels_; | |
const SbMediaAudioCodec codec_ = kSbMediaAudioCodecNone; | |
scoped_ptr<AudioDecoder> decoder_; | |
scoped_ptr<WASAPIAudioSink> sink_; | |
// |iec_sample_rate_| is the sample rate of the stream when stored in an IEC | |
// 61937 format. This may be different from the decoded sample rate. | |
const int iec_sample_rate_; | |
// Used to calculate the media time in GetCurrentMediaTime(). | |
LARGE_INTEGER performance_frequency_; | |
}; | |
} // namespace uwp | |
} // namespace shared | |
} // namespace starboard | |
#endif // STARBOARD_SHARED_UWP_AUDIO_RENDERER_PASSTHROUGH_H_ |