17 #include <AudioToolbox/AudioToolbox.h> 18 #include <glog/logging.h> 34 struct RefTypeTraits<AudioQueueRef> {
35 static constexpr
const bool AcquireWithRaw =
false;
39 LOG(FATAL) <<
"Not reached";
43 AudioQueueDispose(arg,
true);
54 constexpr
const size_t kMaxNumBuffers = 8;
57 AudioStreamBasicDescription* desc) {
59 case SampleFormat::PackedU8:
60 case SampleFormat::PlanarU8:
61 desc->mFormatFlags = 0;
62 desc->mBitsPerChannel = 8;
64 case SampleFormat::PackedS16:
65 case SampleFormat::PlanarS16:
66 desc->mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
67 desc->mBitsPerChannel = 16;
69 case SampleFormat::PackedS32:
70 case SampleFormat::PlanarS32:
71 desc->mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
72 desc->mBitsPerChannel = 32;
74 case SampleFormat::PackedS64:
75 case SampleFormat::PlanarS64:
76 desc->mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
77 desc->mBitsPerChannel = 64;
79 case SampleFormat::PackedFloat:
80 case SampleFormat::PlanarFloat:
81 desc->mFormatFlags = kLinearPCMFormatFlagIsFloat;
82 desc->mBitsPerChannel = 32;
84 case SampleFormat::PackedDouble:
85 case SampleFormat::PlanarDouble:
86 desc->mFormatFlags = kLinearPCMFormatFlagIsFloat;
87 desc->mBitsPerChannel = 64;
91 LOG(DFATAL) <<
"Unsupported sample format: " << format;
103 class BufferList final {
105 BufferList() : mutex_(
"BufferList"), queue_(
nullptr) {}
110 void SetQueue(AudioQueueRef q) {
111 std::unique_lock<Mutex> lock(mutex_);
116 AudioQueueBufferRef FindBuffer(
size_t size) {
117 std::unique_lock<Mutex> lock(mutex_);
120 auto found = buffers_.end();
121 auto capacity = [](decltype(found) it) {
122 return (*it)->mAudioDataBytesCapacity;
124 for (
auto it = buffers_.begin(); it != buffers_.end(); it++) {
125 if (capacity(it) == size) {
128 }
else if (capacity(it) > size &&
129 (found == buffers_.end() || capacity(it) < capacity(found))) {
135 if (found != buffers_.end()) {
137 buffers_.erase(found);
141 AudioQueueBufferRef ret;
142 const auto status = AudioQueueAllocateBuffer(queue_, size, &ret);
144 LOG(DFATAL) <<
"Error creating AudioQueueBuffer: " << status;
150 void ReuseBuffer(AudioQueueBufferRef buffer) {
151 std::unique_lock<Mutex> lock(mutex_);
152 buffers_.emplace_front(buffer);
153 while (buffers_.size() > kMaxNumBuffers) {
154 FreeBuffer(buffers_.back());
161 for (
auto* buf : buffers_)
166 void FreeBuffer(AudioQueueBufferRef buffer) {
167 const auto status = AudioQueueFreeBuffer(queue_, buffer);
169 LOG(DFATAL) <<
"Error freeing AudioQueueBuffer: " << status;
173 AudioQueueRef queue_;
174 std::list<AudioQueueBufferRef> buffers_;
196 AudioStreamBasicDescription desc = {0};
197 if (!SetSampleFormatFields(get<SampleFormat>(frame->format), &desc))
199 desc.mFormatID = kAudioFormatLinearPCM;
200 desc.mSampleRate = frame->stream_info->sample_rate;
201 desc.mChannelsPerFrame = frame->stream_info->channel_count;
202 desc.mFramesPerPacket = 1;
203 desc.mBytesPerFrame = desc.mBitsPerChannel * desc.mChannelsPerFrame / 8;
204 desc.mBytesPerPacket = desc.mBytesPerFrame * desc.mFramesPerPacket;
207 auto status = AudioQueueNewOutput(
208 &desc, &OnAudioCallback,
this,
nullptr,
211 LOG(DFATAL) <<
"Error creating AudioQueue: " << status;
215 queue_size_.store(0, std::memory_order_relaxed);
216 buffers_.SetQueue(q);
220 UpdateVolume(volume);
225 auto* buffer = buffers_.FindBuffer(size);
229 memcpy(buffer->mAudioData, data, size);
230 queue_size_.fetch_add(size, std::memory_order_relaxed);
231 buffer->mAudioDataByteSize = size;
232 buffer->mPacketDescriptionCount = 0;
233 const auto status = AudioQueueEnqueueBuffer(queue_, buffer, 0,
nullptr);
235 LOG(DFATAL) <<
"Error queuing AudioQueueBuffer: " << status;
243 const auto status = AudioQueueReset(queue_);
245 LOG(DFATAL) <<
"Error clearing AudioQueue: " << status;
246 DCHECK_EQ(GetBytesBuffered(), 0);
250 return queue_size_.load(std::memory_order_relaxed);
259 status = AudioQueueStart(queue_,
nullptr);
261 status = AudioQueuePause(queue_);
263 LOG(DFATAL) <<
"Error changing AudioQueue pause state: " << status;
270 const auto status = AudioQueueSetParameter(queue_, kAudioQueueParam_Volume,
271 static_cast<float>(volume));
273 LOG(DFATAL) <<
"Error setting AudioQueue volume: " << status;
277 AudioQueueBufferRef buffer) {
278 auto* impl =
reinterpret_cast<Impl*
>(user_data);
279 DCHECK_EQ(queue, impl->queue_);
280 DCHECK_LE(buffer->mAudioDataByteSize, impl->GetBytesBuffered());
281 DCHECK_GT(buffer->mAudioDataByteSize, 0);
285 impl->queue_size_.fetch_sub(buffer->mAudioDataByteSize,
286 std::memory_order_relaxed);
288 impl->buffers_.ReuseBuffer(buffer);
297 AppleAudioRenderer::AppleAudioRenderer() : impl_(new
Impl) {}
302 impl_->SetPlayer(player);
306 impl_->Attach(stream);
314 return impl_->Volume();
318 impl_->SetVolume(volume);
322 return impl_->Muted();
326 impl_->SetMuted(muted);
std::shared_ptr< shaka::media::DecodedFrame > frame
static void Release(AudioQueueRef arg)
static AudioQueueRef Duplicate(AudioQueueRef arg)