28 bool SDLFormatFromShaka(variant<PixelFormat, SampleFormat> format,
29 SDL_AudioFormat* result) {
31 switch (get<SampleFormat>(format)) {
38 *result = AUDIO_S16SYS;
42 *result = AUDIO_S32SYS;
46 *result = AUDIO_F32SYS;
51 LOG(DFATAL) <<
"SDL doesn't support double-precision audio.";
56 LOG(DFATAL) <<
"SDL doesn't support 64-bit audio.";
60 LOG(DFATAL) <<
"Unknown audio sample format: " << format;
66 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
68 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
69 LOG(ERROR) <<
"Error initializing SDL: " << SDL_GetError();
80 explicit Impl(
const std::string& device_name)
81 : device_name_(device_name), audio_device_(0), volume_(0) {
84 SDL_SetHint(SDL_HINT_AUDIO_CATEGORY,
"playback");
100 bool InitDevice(std::shared_ptr<DecodedFrame>
frame,
double volume)
override {
105 SDL_AudioSpec obtained_audio_spec;
106 SDL_AudioSpec audio_spec;
107 memset(&audio_spec, 0,
sizeof(audio_spec));
108 if (!SDLFormatFromShaka(frame->format, &audio_spec.format))
110 audio_spec.freq = frame->stream_info->sample_rate;
111 audio_spec.channels =
static_cast<Uint8
>(frame->stream_info->channel_count);
112 audio_spec.samples =
static_cast<Uint16
>(frame->sample_count);
114 const char* device = device_name_.empty() ?
nullptr : device_name_.c_str();
116 SDL_OpenAudioDevice(device, 0, &audio_spec, &obtained_audio_spec, 0);
117 if (audio_device_ == 0) {
118 LOG(DFATAL) <<
"Error opening audio device: " << SDL_GetError();
122 format_ = obtained_audio_spec.format;
127 bool AppendBuffer(
const uint8_t* data,
size_t size)
override {
128 std::vector<uint8_t> temp(size);
129 SDL_MixAudioFormat(temp.data(), data, format_, size,
130 static_cast<int>(volume_ * SDL_MIX_MAXVOLUME));
131 if (SDL_QueueAudio(audio_device_, temp.data(), size) != 0) {
132 LOG(DFATAL) <<
"Error appending audio: " << SDL_GetError();
138 void ClearBuffer()
override {
139 if (audio_device_ != 0)
140 SDL_ClearQueuedAudio(audio_device_);
143 size_t GetBytesBuffered()
const override {
144 if (audio_device_ != 0)
145 return SDL_GetQueuedAudioSize(audio_device_);
150 void SetDeviceState(
bool is_playing)
override {
151 if (audio_device_ != 0)
152 SDL_PauseAudioDevice(audio_device_, is_playing ? 0 : 1);
155 void UpdateVolume(
double volume)
override {
160 if (audio_device_ > 0) {
161 SDL_CloseAudioDevice(audio_device_);
166 const std::string device_name_;
167 SDL_AudioDeviceID audio_device_;
168 SDL_AudioFormat format_;
174 : impl_(new
Impl(device_name)) {}
181 std::vector<std::string> ret(SDL_GetNumAudioDevices( 0));
182 for (
size_t i = 0; i < ret.size(); i++)
183 ret[i] = SDL_GetAudioDeviceName(i, 0);
188 impl_->SetPlayer(player);
191 impl_->Attach(stream);
198 return impl_->Volume();
201 impl_->SetVolume(volume);
204 return impl_->Muted();
207 impl_->SetMuted(muted);
std::shared_ptr< shaka::media::DecodedFrame > frame