blob: 298170afd489bff678a835800ec15bac19b09038 [file] [log] [blame]
The Android Open Source Project2729ea92008-10-21 07:00:00 -07001/* //device/extlibs/pv/android/AudioTrack.cpp
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19//#define LOG_NDEBUG 0
20#define LOG_TAG "AudioTrack"
21
22#include <stdint.h>
23#include <sys/types.h>
24
25#include <sched.h>
26#include <sys/resource.h>
27
28#include <private/media/AudioTrackShared.h>
29
30#include <media/AudioSystem.h>
31#include <media/AudioTrack.h>
32
33#include <utils/Log.h>
34#include <utils/MemoryDealer.h>
35#include <utils/Parcel.h>
36#include <utils/IPCThreadState.h>
37#include <utils/Timers.h>
38#include <cutils/atomic.h>
39
40#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
41#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
42
43namespace android {
44
45// ---------------------------------------------------------------------------
46
47static volatile size_t gFrameCount = 0;
48
49size_t AudioTrack::frameCount()
50{
51 if (gFrameCount) return gFrameCount;
52 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
53 if (af == 0) return PERMISSION_DENIED;
54 gFrameCount = af->frameCount();
55 return gFrameCount;
56}
57
58// ---------------------------------------------------------------------------
59
60AudioTrack::AudioTrack()
61 : mStatus(NO_INIT)
62{
63}
64
65AudioTrack::AudioTrack(
66 int streamType,
67 uint32_t sampleRate,
68 int format,
69 int channelCount,
70 int bufferCount,
71 uint32_t flags,
72 callback_t cbf, void* user)
73 : mStatus(NO_INIT)
74{
75 mStatus = set(streamType, sampleRate, format, channelCount,
76 bufferCount, flags, cbf, user);
77}
78
79AudioTrack::~AudioTrack()
80{
81 if (mStatus == NO_ERROR) {
82 if (mPosition) {
83 releaseBuffer(&mAudioBuffer);
84 }
85 // obtainBuffer() will give up with an error
86 mAudioTrack->stop();
87 if (mAudioTrackThread != 0) {
88 mAudioTrackThread->requestExitAndWait();
89 mAudioTrackThread.clear();
90 }
91 mAudioTrack.clear();
92 IPCThreadState::self()->flushCommands();
93 }
94}
95
96status_t AudioTrack::set(
97 int streamType,
98 uint32_t sampleRate,
99 int format,
100 int channelCount,
101 int bufferCount,
102 uint32_t flags,
103 callback_t cbf, void* user)
104{
105
106 if (mAudioFlinger != 0) {
107 LOGE("Track already in use");
108 return INVALID_OPERATION;
109 }
110
111 const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
112 if (audioFlinger == 0) {
113 LOGE("Could not get audioflinger");
114 return NO_INIT;
115 }
116
117 // handle default values first.
118 if (streamType == DEFAULT) {
119 streamType = MUSIC;
120 }
121 if (sampleRate == 0) {
122 sampleRate = audioFlinger->sampleRate();
123 }
124 // these below should probably come from the audioFlinger too...
125 if (format == 0) {
126 format = AudioSystem::PCM_16_BIT;
127 }
128 if (channelCount == 0) {
129 channelCount = 2;
130 }
131 if (bufferCount == 0) {
132 bufferCount = 2;
133 }
134
135 // validate parameters
136 if (format != AudioSystem::PCM_16_BIT) {
137 LOGE("Invalid format");
138 return BAD_VALUE;
139 }
140 if (channelCount != 1 && channelCount != 2) {
141 LOGE("Invalid channel number");
142 return BAD_VALUE;
143 }
144 if (bufferCount < 2) {
145 LOGE("Invalid buffer count");
146 return BAD_VALUE;
147 }
148
149 // create the track
150 sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
151 streamType, sampleRate, format, channelCount, bufferCount, flags);
152 if (track == 0) {
153 LOGE("AudioFlinger could not create track");
154 return NO_INIT;
155 }
156 sp<IMemory> cblk = track->getCblk();
157 if (cblk == 0) {
158 LOGE("Could not get control block");
159 return NO_INIT;
160 }
161 if (cbf != 0) {
162 mAudioTrackThread = new AudioTrackThread(*this);
163 if (mAudioTrackThread == 0) {
164 LOGE("Could not create callback thread");
165 return NO_INIT;
166 }
167 }
168
169 mStatus = NO_ERROR;
170
171 mAudioFlinger = audioFlinger;
172 mAudioTrack = track;
173 mCblkMemory = cblk;
174 mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
175 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
176 mCblk->volume[0] = mCblk->volume[1] = 0x1000;
177 mVolume[LEFT] = 1.0f;
178 mVolume[RIGHT] = 1.0f;
179 mSampleRate = sampleRate;
180 mFrameCount = audioFlinger->frameCount();
181 mStreamType = streamType;
182 mFormat = format;
183 mBufferCount = bufferCount;
184 mChannelCount = channelCount;
185 mMuted = false;
186 mActive = 0;
187 mReserved = 0;
188 mCbf = cbf;
189 mUserData = user;
190 mLatency = seconds(mFrameCount) / mSampleRate;
191 mPosition = 0;
192 return NO_ERROR;
193}
194
195status_t AudioTrack::initCheck() const
196{
197 return mStatus;
198}
199
200// -------------------------------------------------------------------------
201
202nsecs_t AudioTrack::latency() const
203{
204 return mLatency;
205}
206
207int AudioTrack::streamType() const
208{
209 return mStreamType;
210}
211
212uint32_t AudioTrack::sampleRate() const
213{
214 return mSampleRate;
215}
216
217int AudioTrack::format() const
218{
219 return mFormat;
220}
221
222int AudioTrack::channelCount() const
223{
224 return mChannelCount;
225}
226
227int AudioTrack::bufferCount() const
228{
229 return mBufferCount;
230}
231
232// -------------------------------------------------------------------------
233
234void AudioTrack::start()
235{
236 sp<AudioTrackThread> t = mAudioTrackThread;
237
238 LOGV("start");
239 if (t != 0) {
240 if (t->exitPending()) {
241 if (t->requestExitAndWait() == WOULD_BLOCK) {
242 LOGE("AudioTrack::start called from thread");
243 return;
244 }
245 }
246 t->mLock.lock();
247 }
248
249 if (android_atomic_or(1, &mActive) == 0) {
250 if (t != 0) {
251 t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
252 } else {
253 setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
254 }
255 mAudioTrack->start();
256 }
257
258 if (t != 0) {
259 t->mLock.unlock();
260 }
261}
262
263void AudioTrack::stop()
264{
265 sp<AudioTrackThread> t = mAudioTrackThread;
266
267 LOGV("stop");
268 if (t != 0) {
269 t->mLock.lock();
270 }
271
272 if (android_atomic_and(~1, &mActive) == 1) {
273 if (mPosition) {
274 releaseBuffer(&mAudioBuffer);
275 }
276 mAudioTrack->stop();
277 if (t != 0) {
278 t->requestExit();
279 } else {
280 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
281 }
282 }
283
284 if (t != 0) {
285 t->mLock.unlock();
286 }
287}
288
289bool AudioTrack::stopped() const
290{
291 return !mActive;
292}
293
294void AudioTrack::flush()
295{
296 LOGV("flush");
297 if (!mActive) {
298 mCblk->lock.lock();
299 mAudioTrack->flush();
300 // Release AudioTrack callback thread in case it was waiting for new buffers
301 // in AudioTrack::obtainBuffer()
302 mCblk->cv.signal();
303 mCblk->lock.unlock();
304 }
305}
306
307void AudioTrack::pause()
308{
309 LOGV("pause");
310 if (android_atomic_and(~1, &mActive) == 1) {
311 mActive = 0;
312 mAudioTrack->pause();
313 }
314}
315
316void AudioTrack::mute(bool e)
317{
318 mAudioTrack->mute(e);
319 mMuted = e;
320}
321
322bool AudioTrack::muted() const
323{
324 return mMuted;
325}
326
327void AudioTrack::setVolume(float left, float right)
328{
329 mVolume[LEFT] = left;
330 mVolume[RIGHT] = right;
331
332 // write must be atomic
333 mCblk->volumeLR = (int32_t(int16_t(left * 0x1000)) << 16) | int16_t(right * 0x1000);
334}
335
336void AudioTrack::getVolume(float* left, float* right)
337{
338 *left = mVolume[LEFT];
339 *right = mVolume[RIGHT];
340}
341
342void AudioTrack::setSampleRate(int rate)
343{
344 if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
345 mCblk->sampleRate = rate;
346}
347
348uint32_t AudioTrack::getSampleRate()
349{
350 return uint32_t(mCblk->sampleRate);
351}
352
353// -------------------------------------------------------------------------
354
355status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking)
356{
357 int active;
358 int timeout = 0;
359 status_t result;
360 audio_track_cblk_t* cblk = mCblk;
361
362 uint32_t u = cblk->user;
363 uint32_t u_seq = u & audio_track_cblk_t::SEQUENCE_MASK;
364 uint32_t u_buf = u & audio_track_cblk_t::BUFFER_MASK;
365
366 uint32_t s = cblk->server;
367 uint32_t s_seq = s & audio_track_cblk_t::SEQUENCE_MASK;
368 uint32_t s_buf = s & audio_track_cblk_t::BUFFER_MASK;
369
370 LOGW_IF(u_seq < s_seq, "user doesn't fill buffers fast enough");
371
372 if (u_seq > s_seq && u_buf == s_buf) {
373 Mutex::Autolock _l(cblk->lock);
374 goto start_loop_here;
375 while (u_seq > s_seq && u_buf == s_buf) {
376 active = mActive;
377 if (UNLIKELY(!active)) {
378 LOGV("Not active and NO_MORE_BUFFERS");
379 return NO_MORE_BUFFERS;
380 }
381 if (UNLIKELY(!blocking))
382 return WOULD_BLOCK;
383 timeout = 0;
384 result = cblk->cv.waitRelative(cblk->lock, seconds(1));
385 if (__builtin_expect(result!=NO_ERROR, false)) {
386 LOGW( "obtainBuffer timed out (is the CPU pegged?) "
387 "user=%08x, server=%08x", u, s);
388 mAudioTrack->start(); // FIXME: Wake up audioflinger
389 timeout = 1;
390 }
391 // Read user count in case a flush has reset while we where waiting on cv.
392 u = cblk->user;
393 u_seq = u & audio_track_cblk_t::SEQUENCE_MASK;
394 u_buf = u & audio_track_cblk_t::BUFFER_MASK;
395
396 // read the server count again
397 start_loop_here:
398 s = cblk->server;
399 s_seq = s & audio_track_cblk_t::SEQUENCE_MASK;
400 s_buf = s & audio_track_cblk_t::BUFFER_MASK;
401 }
402 }
403
404 LOGW_IF(timeout,
405 "*** SERIOUS WARNING *** obtainBuffer() timed out "
406 "but didn't need to be locked. We recovered, but "
407 "this shouldn't happen (user=%08x, server=%08x)", u, s);
408
409 audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
410 audioBuffer->channelCount= mChannelCount;
411 audioBuffer->format = mFormat;
412 audioBuffer->frameCount = mFrameCount;
413 audioBuffer->size = cblk->size;
414 audioBuffer->raw = (int8_t *)cblk->buffer(u_buf);
415 active = mActive;
416 return active ? status_t(NO_ERROR) : status_t(STOPPED);
417}
418
419void AudioTrack::releaseBuffer(Buffer* audioBuffer)
420{
421 // next buffer...
422 if (UNLIKELY(mPosition)) {
423 // clean the remaining part of the buffer
424 size_t capacity = mAudioBuffer.size - mPosition;
425 memset(mAudioBuffer.i8 + mPosition, 0, capacity);
426 mPosition = 0;
427 }
428 audio_track_cblk_t* cblk = mCblk;
429 cblk->stepUser(mBufferCount);
430}
431
432// -------------------------------------------------------------------------
433
434ssize_t AudioTrack::write(const void* buffer, size_t userSize)
435{
436 if (ssize_t(userSize) < 0) {
437 // sanity-check. user is most-likely passing an error code.
438 LOGE("AudioTrack::write(buffer=%p, size=%u (%d)",
439 buffer, userSize, userSize);
440 return BAD_VALUE;
441 }
442
443 LOGV("write %d bytes, mActive=%d", userSize, mActive);
444 ssize_t written = 0;
445 do {
446 if (mPosition == 0) {
447 status_t err = obtainBuffer(&mAudioBuffer, true);
448 if (err < 0) {
449 // out of buffers, return #bytes written
450 if (err == status_t(NO_MORE_BUFFERS))
451 break;
452 return ssize_t(err);
453 }
454 }
455
456 size_t capacity = mAudioBuffer.size - mPosition;
457 size_t toWrite = userSize < capacity ? userSize : capacity;
458
459 memcpy(mAudioBuffer.i8 + mPosition, buffer, toWrite);
460 buffer = static_cast<const int8_t*>(buffer) + toWrite;
461 mPosition += toWrite;
462 userSize -= toWrite;
463 capacity -= toWrite;
464 written += toWrite;
465
466 if (capacity == 0) {
467 mPosition = 0;
468 releaseBuffer(&mAudioBuffer);
469 }
470 } while (userSize);
471
472 return written;
473}
474
475// -------------------------------------------------------------------------
476
477bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
478{
479 Buffer audioBuffer;
480
481 status_t err = obtainBuffer(&audioBuffer, true);
482 if (err < NO_ERROR) {
483 LOGE("Error obtaining an audio buffer, giving up.");
484 return false;
485 }
486 if (err == status_t(STOPPED)) return false;
487 mCbf(mUserData, audioBuffer);
488 releaseBuffer(&audioBuffer);
489
490 return true;
491}
492
493status_t AudioTrack::dump(int fd, const Vector<String16>& args) const
494{
495
496 const size_t SIZE = 256;
497 char buffer[SIZE];
498 String8 result;
499
500 result.append(" AudioTrack::dump\n");
501 snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]);
502 result.append(buffer);
503 snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d), buffer count(%d)\n", mFormat, mChannelCount, mFrameCount, mBufferCount);
504 result.append(buffer);
505 snprintf(buffer, 255, " sample rate(%d), status(%d), muted(%d), reserved(%d)\n", mSampleRate, mStatus, mMuted, mReserved);
506 result.append(buffer);
507 snprintf(buffer, 255, " active(%d), latency (%lld), position(%d)\n", mActive, mLatency, mPosition);
508 result.append(buffer);
509 ::write(fd, result.string(), result.size());
510 return NO_ERROR;
511}
512
513// =========================================================================
514
515AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver)
516 : Thread(false), mReceiver(receiver)
517{
518}
519
520bool AudioTrack::AudioTrackThread::threadLoop()
521{
522 return mReceiver.processAudioBuffer(this);
523}
524
525status_t AudioTrack::AudioTrackThread::readyToRun()
526{
527 return NO_ERROR;
528}
529
530void AudioTrack::AudioTrackThread::onFirstRef()
531{
532}
533
534// =========================================================================
535
536audio_track_cblk_t::audio_track_cblk_t()
537 : user(0), server(0), volumeLR(0), buffers(0), size(0)
538{
539}
540
541uint32_t audio_track_cblk_t::stepUser(int bufferCount)
542{
543 uint32_t u = this->user;
544 uint32_t u_seq = u & audio_track_cblk_t::SEQUENCE_MASK;
545 uint32_t u_buf = u & audio_track_cblk_t::BUFFER_MASK;
546 if (++u_buf >= uint32_t(bufferCount)) {
547 u_seq += 0x100;
548 u_buf = 0;
549 }
550 u = u_seq | u_buf;
551 this->user = u;
552 return u;
553}
554
555bool audio_track_cblk_t::stepServer(int bufferCount)
556{
557 // the code below simulates lock-with-timeout
558 // we MUST do this to protect the AudioFlinger server
559 // as this lock is shared with the client.
560 status_t err;
561
562 err = lock.tryLock();
563 if (err == -EBUSY) { // just wait a bit
564 usleep(1000);
565 err = lock.tryLock();
566 }
567 if (err != NO_ERROR) {
568 // probably, the client just died.
569 return false;
570 }
571
572 uint32_t s = this->server;
573 uint32_t s_seq = s & audio_track_cblk_t::SEQUENCE_MASK;
574 uint32_t s_buf = s & audio_track_cblk_t::BUFFER_MASK;
575 s_buf++;
576 if (s_buf >= uint32_t(bufferCount)) {
577 s_seq += 0x100;
578 s_buf = 0;
579 }
580 s = s_seq | s_buf;
581
582 this->server = s;
583 cv.signal();
584 lock.unlock();
585 return true;
586}
587
588void* audio_track_cblk_t::buffer(int id) const
589{
590 return (char*)this->buffers + id * this->size;
591}
592
593// -------------------------------------------------------------------------
594
595}; // namespace android
596