blob: 52518aea6b78fd7e0bb32cf6ccd14bc2013db767 [file] [log] [blame]
Eric Laurent81784c32012-11-19 14:55:58 -08001/*
2**
3** Copyright 2012, 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_TAG "AudioFlinger"
20//#define LOG_NDEBUG 0
21
Glenn Kasten153b9fe2013-07-15 11:23:36 -070022#include "Configuration.h"
Eric Laurent81784c32012-11-19 14:55:58 -080023#include <math.h>
24#include <cutils/compiler.h>
25#include <utils/Log.h>
26
27#include <private/media/AudioTrackShared.h>
28
29#include <common_time/cc_helper.h>
30#include <common_time/local_clock.h>
31
32#include "AudioMixer.h"
33#include "AudioFlinger.h"
34#include "ServiceUtilities.h"
35
Glenn Kastenda6ef132013-01-10 12:31:01 -080036#include <media/nbaio/Pipe.h>
37#include <media/nbaio/PipeReader.h>
38
Eric Laurent81784c32012-11-19 14:55:58 -080039// ----------------------------------------------------------------------------
40
41// Note: the following macro is used for extremely verbose logging message. In
42// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
43// 0; but one side effect of this is to turn all LOGV's as well. Some messages
44// are so verbose that we want to suppress them even when we have ALOG_ASSERT
45// turned on. Do not uncomment the #def below unless you really know what you
46// are doing and want to see all of the extremely verbose messages.
47//#define VERY_VERY_VERBOSE_LOGGING
48#ifdef VERY_VERY_VERBOSE_LOGGING
49#define ALOGVV ALOGV
50#else
51#define ALOGVV(a...) do { } while(0)
52#endif
53
54namespace android {
55
56// ----------------------------------------------------------------------------
57// TrackBase
58// ----------------------------------------------------------------------------
59
Glenn Kastenda6ef132013-01-10 12:31:01 -080060static volatile int32_t nextTrackId = 55;
61
Eric Laurent81784c32012-11-19 14:55:58 -080062// TrackBase constructor must be called with AudioFlinger::mLock held
63AudioFlinger::ThreadBase::TrackBase::TrackBase(
64 ThreadBase *thread,
65 const sp<Client>& client,
66 uint32_t sampleRate,
67 audio_format_t format,
68 audio_channel_mask_t channelMask,
69 size_t frameCount,
70 const sp<IMemory>& sharedBuffer,
Glenn Kastene3aa6592012-12-04 12:22:46 -080071 int sessionId,
72 bool isOut)
Eric Laurent81784c32012-11-19 14:55:58 -080073 : RefBase(),
74 mThread(thread),
75 mClient(client),
76 mCblk(NULL),
77 // mBuffer
78 // mBufferEnd
79 mStepCount(0),
80 mState(IDLE),
81 mSampleRate(sampleRate),
82 mFormat(format),
83 mChannelMask(channelMask),
84 mChannelCount(popcount(channelMask)),
85 mFrameSize(audio_is_linear_pcm(format) ?
86 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
87 mFrameCount(frameCount),
88 mStepServerFailed(false),
Glenn Kastene3aa6592012-12-04 12:22:46 -080089 mSessionId(sessionId),
90 mIsOut(isOut),
Glenn Kastenda6ef132013-01-10 12:31:01 -080091 mServerProxy(NULL),
Eric Laurentbfb1b832013-01-07 09:53:42 -080092 mId(android_atomic_inc(&nextTrackId)),
93 mTerminated(false)
Eric Laurent81784c32012-11-19 14:55:58 -080094{
95 // client == 0 implies sharedBuffer == 0
96 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
97
98 ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
99 sharedBuffer->size());
100
101 // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
102 size_t size = sizeof(audio_track_cblk_t);
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800103 size_t bufferSize = (sharedBuffer == 0 ? roundup(frameCount) : frameCount) * mFrameSize;
Eric Laurent81784c32012-11-19 14:55:58 -0800104 if (sharedBuffer == 0) {
105 size += bufferSize;
106 }
107
108 if (client != 0) {
109 mCblkMemory = client->heap()->allocate(size);
110 if (mCblkMemory != 0) {
111 mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
112 // can't assume mCblk != NULL
113 } else {
114 ALOGE("not enough memory for AudioTrack size=%u", size);
115 client->heap()->dump("AudioTrack");
116 return;
117 }
118 } else {
Glenn Kastene3aa6592012-12-04 12:22:46 -0800119 // this syntax avoids calling the audio_track_cblk_t constructor twice
120 mCblk = (audio_track_cblk_t *) new uint8_t[size];
Eric Laurent81784c32012-11-19 14:55:58 -0800121 // assume mCblk != NULL
122 }
123
124 // construct the shared structure in-place.
125 if (mCblk != NULL) {
126 new(mCblk) audio_track_cblk_t();
127 // clear all buffers
128 mCblk->frameCount_ = frameCount;
Eric Laurent81784c32012-11-19 14:55:58 -0800129 if (sharedBuffer == 0) {
130 mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
131 memset(mBuffer, 0, bufferSize);
Eric Laurent81784c32012-11-19 14:55:58 -0800132 } else {
133 mBuffer = sharedBuffer->pointer();
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800134#if 0
135 mCblk->flags = CBLK_FORCEREADY; // FIXME hack, need to fix the track ready logic
136#endif
Eric Laurent81784c32012-11-19 14:55:58 -0800137 }
138 mBufferEnd = (uint8_t *)mBuffer + bufferSize;
Glenn Kastenda6ef132013-01-10 12:31:01 -0800139
Glenn Kasten46909e72013-02-26 09:20:22 -0800140#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -0800141 if (mTeeSinkTrackEnabled) {
Glenn Kasten46909e72013-02-26 09:20:22 -0800142 NBAIO_Format pipeFormat = Format_from_SR_C(mSampleRate, mChannelCount);
143 if (pipeFormat != Format_Invalid) {
144 Pipe *pipe = new Pipe(mTeeSinkTrackFrames, pipeFormat);
145 size_t numCounterOffers = 0;
146 const NBAIO_Format offers[1] = {pipeFormat};
147 ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
148 ALOG_ASSERT(index == 0);
149 PipeReader *pipeReader = new PipeReader(*pipe);
150 numCounterOffers = 0;
151 index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
152 ALOG_ASSERT(index == 0);
153 mTeeSink = pipe;
154 mTeeSource = pipeReader;
155 }
Glenn Kastenda6ef132013-01-10 12:31:01 -0800156 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800157#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800158
Eric Laurent81784c32012-11-19 14:55:58 -0800159 }
160}
161
162AudioFlinger::ThreadBase::TrackBase::~TrackBase()
163{
Glenn Kasten46909e72013-02-26 09:20:22 -0800164#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -0800165 dumpTee(-1, mTeeSource, mId);
Glenn Kasten46909e72013-02-26 09:20:22 -0800166#endif
Glenn Kastene3aa6592012-12-04 12:22:46 -0800167 // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
168 delete mServerProxy;
Eric Laurent81784c32012-11-19 14:55:58 -0800169 if (mCblk != NULL) {
170 if (mClient == 0) {
171 delete mCblk;
172 } else {
173 mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
174 }
175 }
176 mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
177 if (mClient != 0) {
178 // Client destructor must run with AudioFlinger mutex locked
179 Mutex::Autolock _l(mClient->audioFlinger()->mLock);
180 // If the client's reference count drops to zero, the associated destructor
181 // must run with AudioFlinger lock held. Thus the explicit clear() rather than
182 // relying on the automatic clear() at end of scope.
183 mClient.clear();
184 }
185}
186
187// AudioBufferProvider interface
188// getNextBuffer() = 0;
189// This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack
190void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
191{
Glenn Kasten46909e72013-02-26 09:20:22 -0800192#ifdef TEE_SINK
Glenn Kastenda6ef132013-01-10 12:31:01 -0800193 if (mTeeSink != 0) {
194 (void) mTeeSink->write(buffer->raw, buffer->frameCount);
195 }
Glenn Kasten46909e72013-02-26 09:20:22 -0800196#endif
Glenn Kastenda6ef132013-01-10 12:31:01 -0800197
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800198 ServerProxy::Buffer buf;
199 buf.mFrameCount = buffer->frameCount;
200 buf.mRaw = buffer->raw;
Eric Laurent81784c32012-11-19 14:55:58 -0800201 buffer->frameCount = 0;
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800202 buffer->raw = NULL;
203 mServerProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -0800204}
205
Eric Laurent81784c32012-11-19 14:55:58 -0800206status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
207{
208 mSyncEvents.add(event);
209 return NO_ERROR;
210}
211
212// ----------------------------------------------------------------------------
213// Playback
214// ----------------------------------------------------------------------------
215
216AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
217 : BnAudioTrack(),
218 mTrack(track)
219{
220}
221
222AudioFlinger::TrackHandle::~TrackHandle() {
223 // just stop the track on deletion, associated resources
224 // will be freed from the main thread once all pending buffers have
225 // been played. Unless it's not in the active track list, in which
226 // case we free everything now...
227 mTrack->destroy();
228}
229
230sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
231 return mTrack->getCblk();
232}
233
234status_t AudioFlinger::TrackHandle::start() {
235 return mTrack->start();
236}
237
238void AudioFlinger::TrackHandle::stop() {
239 mTrack->stop();
240}
241
242void AudioFlinger::TrackHandle::flush() {
243 mTrack->flush();
244}
245
Eric Laurent81784c32012-11-19 14:55:58 -0800246void AudioFlinger::TrackHandle::pause() {
247 mTrack->pause();
248}
249
Richard Fitzgeraldad3af332013-03-25 16:54:37 +0000250status_t AudioFlinger::TrackHandle::setParameters(const String8& keyValuePairs) {
Eric Laurentbfb1b832013-01-07 09:53:42 -0800251 return mTrack->setParameters(keyValuePairs);
Richard Fitzgeraldad3af332013-03-25 16:54:37 +0000252}
253
Eric Laurent81784c32012-11-19 14:55:58 -0800254status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
255{
256 return mTrack->attachAuxEffect(EffectId);
257}
258
259status_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size,
260 sp<IMemory>* buffer) {
261 if (!mTrack->isTimedTrack())
262 return INVALID_OPERATION;
263
264 PlaybackThread::TimedTrack* tt =
265 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
266 return tt->allocateTimedBuffer(size, buffer);
267}
268
269status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer,
270 int64_t pts) {
271 if (!mTrack->isTimedTrack())
272 return INVALID_OPERATION;
273
274 PlaybackThread::TimedTrack* tt =
275 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
276 return tt->queueTimedBuffer(buffer, pts);
277}
278
279status_t AudioFlinger::TrackHandle::setMediaTimeTransform(
280 const LinearTransform& xform, int target) {
281
282 if (!mTrack->isTimedTrack())
283 return INVALID_OPERATION;
284
285 PlaybackThread::TimedTrack* tt =
286 reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
287 return tt->setMediaTimeTransform(
288 xform, static_cast<TimedAudioTrack::TargetTimeline>(target));
289}
290
291status_t AudioFlinger::TrackHandle::onTransact(
292 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
293{
294 return BnAudioTrack::onTransact(code, data, reply, flags);
295}
296
297// ----------------------------------------------------------------------------
298
299// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
300AudioFlinger::PlaybackThread::Track::Track(
301 PlaybackThread *thread,
302 const sp<Client>& client,
303 audio_stream_type_t streamType,
304 uint32_t sampleRate,
305 audio_format_t format,
306 audio_channel_mask_t channelMask,
307 size_t frameCount,
308 const sp<IMemory>& sharedBuffer,
309 int sessionId,
310 IAudioFlinger::track_flags_t flags)
311 : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer,
Glenn Kastene3aa6592012-12-04 12:22:46 -0800312 sessionId, true /*isOut*/),
Eric Laurent81784c32012-11-19 14:55:58 -0800313 mFillingUpStatus(FS_INVALID),
314 // mRetryCount initialized later when needed
315 mSharedBuffer(sharedBuffer),
316 mStreamType(streamType),
317 mName(-1), // see note below
318 mMainBuffer(thread->mixBuffer()),
319 mAuxBuffer(NULL),
320 mAuxEffectId(0), mHasVolumeController(false),
321 mPresentationCompleteFrames(0),
322 mFlags(flags),
323 mFastIndex(-1),
324 mUnderrunCount(0),
Glenn Kasten5736c352012-12-04 12:12:34 -0800325 mCachedVolume(1.0),
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800326 mIsInvalid(false),
Eric Laurentbfb1b832013-01-07 09:53:42 -0800327 mAudioTrackServerProxy(NULL),
328 mResumeToStopping(false)
Eric Laurent81784c32012-11-19 14:55:58 -0800329{
330 if (mCblk != NULL) {
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800331 if (sharedBuffer == 0) {
332 mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
333 mFrameSize);
334 } else {
335 mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
336 mFrameSize);
337 }
338 mServerProxy = mAudioTrackServerProxy;
Eric Laurent81784c32012-11-19 14:55:58 -0800339 // to avoid leaking a track name, do not allocate one unless there is an mCblk
340 mName = thread->getTrackName_l(channelMask, sessionId);
341 mCblk->mName = mName;
342 if (mName < 0) {
343 ALOGE("no more track names available");
344 return;
345 }
346 // only allocate a fast track index if we were able to allocate a normal track name
347 if (flags & IAudioFlinger::TRACK_FAST) {
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800348 mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
Eric Laurent81784c32012-11-19 14:55:58 -0800349 ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
350 int i = __builtin_ctz(thread->mFastTrackAvailMask);
351 ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks);
352 // FIXME This is too eager. We allocate a fast track index before the
353 // fast track becomes active. Since fast tracks are a scarce resource,
354 // this means we are potentially denying other more important fast tracks from
355 // being created. It would be better to allocate the index dynamically.
356 mFastIndex = i;
357 mCblk->mName = i;
358 // Read the initial underruns because this field is never cleared by the fast mixer
359 mObservedUnderruns = thread->getFastTrackUnderruns(i);
360 thread->mFastTrackAvailMask &= ~(1 << i);
361 }
362 }
363 ALOGV("Track constructor name %d, calling pid %d", mName,
364 IPCThreadState::self()->getCallingPid());
365}
366
367AudioFlinger::PlaybackThread::Track::~Track()
368{
369 ALOGV("PlaybackThread::Track destructor");
370}
371
372void AudioFlinger::PlaybackThread::Track::destroy()
373{
374 // NOTE: destroyTrack_l() can remove a strong reference to this Track
375 // by removing it from mTracks vector, so there is a risk that this Tracks's
376 // destructor is called. As the destructor needs to lock mLock,
377 // we must acquire a strong reference on this Track before locking mLock
378 // here so that the destructor is called only when exiting this function.
379 // On the other hand, as long as Track::destroy() is only called by
380 // TrackHandle destructor, the TrackHandle still holds a strong ref on
381 // this Track with its member mTrack.
382 sp<Track> keep(this);
383 { // scope for mLock
384 sp<ThreadBase> thread = mThread.promote();
385 if (thread != 0) {
Eric Laurent81784c32012-11-19 14:55:58 -0800386 Mutex::Autolock _l(thread->mLock);
387 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Eric Laurentbfb1b832013-01-07 09:53:42 -0800388 bool wasActive = playbackThread->destroyTrack_l(this);
389 if (!isOutputTrack() && !wasActive) {
390 AudioSystem::releaseOutput(thread->id());
391 }
Eric Laurent81784c32012-11-19 14:55:58 -0800392 }
393 }
394}
395
396/*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
397{
Eric Laurentbfb1b832013-01-07 09:53:42 -0800398 result.append(" Name Client Type Fmt Chn mask Session StpCnt fCount S F SRate "
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800399 "L dB R dB Server Main buf Aux Buf Flags Underruns\n");
Eric Laurent81784c32012-11-19 14:55:58 -0800400}
401
402void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
403{
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800404 uint32_t vlr = mAudioTrackServerProxy->getVolumeLR();
Eric Laurent81784c32012-11-19 14:55:58 -0800405 if (isFastTrack()) {
406 sprintf(buffer, " F %2d", mFastIndex);
407 } else {
408 sprintf(buffer, " %4d", mName - AudioMixer::TRACK0);
409 }
410 track_state state = mState;
411 char stateChar;
Eric Laurentbfb1b832013-01-07 09:53:42 -0800412 if (isTerminated()) {
Eric Laurent81784c32012-11-19 14:55:58 -0800413 stateChar = 'T';
Eric Laurentbfb1b832013-01-07 09:53:42 -0800414 } else {
415 switch (state) {
416 case IDLE:
417 stateChar = 'I';
418 break;
419 case STOPPING_1:
420 stateChar = 's';
421 break;
422 case STOPPING_2:
423 stateChar = '5';
424 break;
425 case STOPPED:
426 stateChar = 'S';
427 break;
428 case RESUMING:
429 stateChar = 'R';
430 break;
431 case ACTIVE:
432 stateChar = 'A';
433 break;
434 case PAUSING:
435 stateChar = 'p';
436 break;
437 case PAUSED:
438 stateChar = 'P';
439 break;
440 case FLUSHED:
441 stateChar = 'F';
442 break;
443 default:
444 stateChar = '?';
445 break;
446 }
Eric Laurent81784c32012-11-19 14:55:58 -0800447 }
448 char nowInUnderrun;
449 switch (mObservedUnderruns.mBitFields.mMostRecent) {
450 case UNDERRUN_FULL:
451 nowInUnderrun = ' ';
452 break;
453 case UNDERRUN_PARTIAL:
454 nowInUnderrun = '<';
455 break;
456 case UNDERRUN_EMPTY:
457 nowInUnderrun = '*';
458 break;
459 default:
460 nowInUnderrun = '?';
461 break;
462 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800463 snprintf(&buffer[7], size-7, " %6d %4u 0x%08x 0x%08x %7u %6u %6u %1c %1d %5u %5.2g %5.2g "
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800464 "0x%08x 0x%08x 0x%08x %#5x %9u%c\n",
Eric Laurent81784c32012-11-19 14:55:58 -0800465 (mClient == 0) ? getpid_cached : mClient->pid(),
466 mStreamType,
467 mFormat,
468 mChannelMask,
469 mSessionId,
470 mStepCount,
471 mFrameCount,
472 stateChar,
Eric Laurent81784c32012-11-19 14:55:58 -0800473 mFillingUpStatus,
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800474 mAudioTrackServerProxy->getSampleRate(),
Eric Laurent81784c32012-11-19 14:55:58 -0800475 20.0 * log10((vlr & 0xFFFF) / 4096.0),
476 20.0 * log10((vlr >> 16) / 4096.0),
477 mCblk->server,
Eric Laurent81784c32012-11-19 14:55:58 -0800478 (int)mMainBuffer,
479 (int)mAuxBuffer,
480 mCblk->flags,
481 mUnderrunCount,
482 nowInUnderrun);
483}
484
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800485uint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const {
486 return mAudioTrackServerProxy->getSampleRate();
487}
488
Eric Laurent81784c32012-11-19 14:55:58 -0800489// AudioBufferProvider interface
490status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
491 AudioBufferProvider::Buffer* buffer, int64_t pts)
492{
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800493 ServerProxy::Buffer buf;
494 size_t desiredFrames = buffer->frameCount;
495 buf.mFrameCount = desiredFrames;
496 status_t status = mServerProxy->obtainBuffer(&buf);
497 buffer->frameCount = buf.mFrameCount;
498 buffer->raw = buf.mRaw;
499 if (buf.mFrameCount == 0) {
500 // only implemented so far for normal tracks, not fast tracks
501 mCblk->u.mStreaming.mUnderrunFrames += desiredFrames;
502 // FIXME also wake futex so that underrun is noticed more quickly
503 (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->flags);
Eric Laurent81784c32012-11-19 14:55:58 -0800504 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800505 return status;
Eric Laurent81784c32012-11-19 14:55:58 -0800506}
507
508// Note that framesReady() takes a mutex on the control block using tryLock().
509// This could result in priority inversion if framesReady() is called by the normal mixer,
510// as the normal mixer thread runs at lower
511// priority than the client's callback thread: there is a short window within framesReady()
512// during which the normal mixer could be preempted, and the client callback would block.
513// Another problem can occur if framesReady() is called by the fast mixer:
514// the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer.
515// FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue.
516size_t AudioFlinger::PlaybackThread::Track::framesReady() const {
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800517 return mAudioTrackServerProxy->framesReady();
Eric Laurent81784c32012-11-19 14:55:58 -0800518}
519
520// Don't call for fast tracks; the framesReady() could result in priority inversion
521bool AudioFlinger::PlaybackThread::Track::isReady() const {
522 if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
523 return true;
524 }
525
526 if (framesReady() >= mFrameCount ||
527 (mCblk->flags & CBLK_FORCEREADY)) {
528 mFillingUpStatus = FS_FILLED;
529 android_atomic_and(~CBLK_FORCEREADY, &mCblk->flags);
530 return true;
531 }
532 return false;
533}
534
535status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event,
536 int triggerSession)
537{
538 status_t status = NO_ERROR;
539 ALOGV("start(%d), calling pid %d session %d",
540 mName, IPCThreadState::self()->getCallingPid(), mSessionId);
541
542 sp<ThreadBase> thread = mThread.promote();
543 if (thread != 0) {
544 Mutex::Autolock _l(thread->mLock);
545 track_state state = mState;
546 // here the track could be either new, or restarted
547 // in both cases "unstop" the track
Eric Laurentbfb1b832013-01-07 09:53:42 -0800548
Glenn Kastenc9b2e202013-02-26 11:32:32 -0800549 if (state == PAUSED) {
Eric Laurentbfb1b832013-01-07 09:53:42 -0800550 if (mResumeToStopping) {
551 // happened we need to resume to STOPPING_1
552 mState = TrackBase::STOPPING_1;
553 ALOGV("PAUSED => STOPPING_1 (%d) on thread %p", mName, this);
554 } else {
555 mState = TrackBase::RESUMING;
556 ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
557 }
Eric Laurent81784c32012-11-19 14:55:58 -0800558 } else {
559 mState = TrackBase::ACTIVE;
560 ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
561 }
562
Eric Laurentbfb1b832013-01-07 09:53:42 -0800563 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
564 status = playbackThread->addTrack_l(this);
565 if (status == INVALID_OPERATION || status == PERMISSION_DENIED) {
Eric Laurent81784c32012-11-19 14:55:58 -0800566 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -0800567 // restore previous state if start was rejected by policy manager
568 if (status == PERMISSION_DENIED) {
569 mState = state;
570 }
571 }
572 // track was already in the active list, not a problem
573 if (status == ALREADY_EXISTS) {
574 status = NO_ERROR;
Eric Laurent81784c32012-11-19 14:55:58 -0800575 }
576 } else {
577 status = BAD_VALUE;
578 }
579 return status;
580}
581
582void AudioFlinger::PlaybackThread::Track::stop()
583{
584 ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
585 sp<ThreadBase> thread = mThread.promote();
586 if (thread != 0) {
587 Mutex::Autolock _l(thread->mLock);
588 track_state state = mState;
589 if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
590 // If the track is not active (PAUSED and buffers full), flush buffers
591 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
592 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
593 reset();
594 mState = STOPPED;
Eric Laurentbfb1b832013-01-07 09:53:42 -0800595 } else if (!isFastTrack() && !isOffloaded()) {
Eric Laurent81784c32012-11-19 14:55:58 -0800596 mState = STOPPED;
597 } else {
Eric Laurentbfb1b832013-01-07 09:53:42 -0800598 // For fast tracks prepareTracks_l() will set state to STOPPING_2
599 // presentation is complete
600 // For an offloaded track this starts a drain and state will
601 // move to STOPPING_2 when drain completes and then STOPPED
Eric Laurent81784c32012-11-19 14:55:58 -0800602 mState = STOPPING_1;
603 }
604 ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName,
605 playbackThread);
606 }
Eric Laurent81784c32012-11-19 14:55:58 -0800607 }
608}
609
610void AudioFlinger::PlaybackThread::Track::pause()
611{
612 ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
613 sp<ThreadBase> thread = mThread.promote();
614 if (thread != 0) {
615 Mutex::Autolock _l(thread->mLock);
Eric Laurentbfb1b832013-01-07 09:53:42 -0800616 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
617 switch (mState) {
618 case STOPPING_1:
619 case STOPPING_2:
620 if (!isOffloaded()) {
621 /* nothing to do if track is not offloaded */
622 break;
623 }
624
625 // Offloaded track was draining, we need to carry on draining when resumed
626 mResumeToStopping = true;
627 // fall through...
628 case ACTIVE:
629 case RESUMING:
Eric Laurent81784c32012-11-19 14:55:58 -0800630 mState = PAUSING;
631 ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
Eric Laurentbfb1b832013-01-07 09:53:42 -0800632 playbackThread->signal_l();
633 break;
Eric Laurent81784c32012-11-19 14:55:58 -0800634
Eric Laurentbfb1b832013-01-07 09:53:42 -0800635 default:
636 break;
Eric Laurent81784c32012-11-19 14:55:58 -0800637 }
638 }
639}
640
641void AudioFlinger::PlaybackThread::Track::flush()
642{
643 ALOGV("flush(%d)", mName);
644 sp<ThreadBase> thread = mThread.promote();
645 if (thread != 0) {
646 Mutex::Autolock _l(thread->mLock);
Eric Laurent81784c32012-11-19 14:55:58 -0800647 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
Eric Laurentbfb1b832013-01-07 09:53:42 -0800648
649 if (isOffloaded()) {
650 // If offloaded we allow flush during any state except terminated
651 // and keep the track active to avoid problems if user is seeking
652 // rapidly and underlying hardware has a significant delay handling
653 // a pause
654 if (isTerminated()) {
655 return;
656 }
657
658 ALOGV("flush: offload flush");
Eric Laurent81784c32012-11-19 14:55:58 -0800659 reset();
Eric Laurentbfb1b832013-01-07 09:53:42 -0800660
661 if (mState == STOPPING_1 || mState == STOPPING_2) {
662 ALOGV("flushed in STOPPING_1 or 2 state, change state to ACTIVE");
663 mState = ACTIVE;
664 }
665
666 if (mState == ACTIVE) {
667 ALOGV("flush called in active state, resetting buffer time out retry count");
668 mRetryCount = PlaybackThread::kMaxTrackRetriesOffload;
669 }
670
671 mResumeToStopping = false;
672 } else {
673 if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
674 mState != PAUSED && mState != PAUSING && mState != IDLE && mState != FLUSHED) {
675 return;
676 }
677 // No point remaining in PAUSED state after a flush => go to
678 // FLUSHED state
679 mState = FLUSHED;
680 // do not reset the track if it is still in the process of being stopped or paused.
681 // this will be done by prepareTracks_l() when the track is stopped.
682 // prepareTracks_l() will see mState == FLUSHED, then
683 // remove from active track list, reset(), and trigger presentation complete
684 if (playbackThread->mActiveTracks.indexOf(this) < 0) {
685 reset();
686 }
Eric Laurent81784c32012-11-19 14:55:58 -0800687 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800688 // Prevent flush being lost if the track is flushed and then resumed
689 // before mixer thread can run. This is important when offloading
690 // because the hardware buffer could hold a large amount of audio
691 playbackThread->flushOutput_l();
692 playbackThread->signal_l();
Eric Laurent81784c32012-11-19 14:55:58 -0800693 }
694}
695
696void AudioFlinger::PlaybackThread::Track::reset()
697{
698 // Do not reset twice to avoid discarding data written just after a flush and before
699 // the audioflinger thread detects the track is stopped.
700 if (!mResetDone) {
Eric Laurent81784c32012-11-19 14:55:58 -0800701 // Force underrun condition to avoid false underrun callback until first data is
702 // written to buffer
703 android_atomic_and(~CBLK_FORCEREADY, &mCblk->flags);
Eric Laurent81784c32012-11-19 14:55:58 -0800704 mFillingUpStatus = FS_FILLING;
705 mResetDone = true;
706 if (mState == FLUSHED) {
707 mState = IDLE;
708 }
709 }
710}
711
Eric Laurentbfb1b832013-01-07 09:53:42 -0800712status_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyValuePairs)
713{
714 sp<ThreadBase> thread = mThread.promote();
715 if (thread == 0) {
716 ALOGE("thread is dead");
717 return FAILED_TRANSACTION;
718 } else if ((thread->type() == ThreadBase::DIRECT) ||
719 (thread->type() == ThreadBase::OFFLOAD)) {
720 return thread->setParameters(keyValuePairs);
721 } else {
722 return PERMISSION_DENIED;
723 }
724}
725
Eric Laurent81784c32012-11-19 14:55:58 -0800726status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
727{
728 status_t status = DEAD_OBJECT;
729 sp<ThreadBase> thread = mThread.promote();
730 if (thread != 0) {
731 PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
732 sp<AudioFlinger> af = mClient->audioFlinger();
733
734 Mutex::Autolock _l(af->mLock);
735
736 sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
737
738 if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) {
739 Mutex::Autolock _dl(playbackThread->mLock);
740 Mutex::Autolock _sl(srcThread->mLock);
741 sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
742 if (chain == 0) {
743 return INVALID_OPERATION;
744 }
745
746 sp<EffectModule> effect = chain->getEffectFromId_l(EffectId);
747 if (effect == 0) {
748 return INVALID_OPERATION;
749 }
750 srcThread->removeEffect_l(effect);
751 playbackThread->addEffect_l(effect);
752 // removeEffect_l() has stopped the effect if it was active so it must be restarted
753 if (effect->state() == EffectModule::ACTIVE ||
754 effect->state() == EffectModule::STOPPING) {
755 effect->start();
756 }
757
758 sp<EffectChain> dstChain = effect->chain().promote();
759 if (dstChain == 0) {
760 srcThread->addEffect_l(effect);
761 return INVALID_OPERATION;
762 }
763 AudioSystem::unregisterEffect(effect->id());
764 AudioSystem::registerEffect(&effect->desc(),
765 srcThread->id(),
766 dstChain->strategy(),
767 AUDIO_SESSION_OUTPUT_MIX,
768 effect->id());
769 }
770 status = playbackThread->attachAuxEffect(this, EffectId);
771 }
772 return status;
773}
774
775void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
776{
777 mAuxEffectId = EffectId;
778 mAuxBuffer = buffer;
779}
780
781bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWritten,
782 size_t audioHalFrames)
783{
784 // a track is considered presented when the total number of frames written to audio HAL
785 // corresponds to the number of frames written when presentationComplete() is called for the
786 // first time (mPresentationCompleteFrames == 0) plus the buffer filling status at that time.
Eric Laurentbfb1b832013-01-07 09:53:42 -0800787 // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
788 // to detect when all frames have been played. In this case framesWritten isn't
789 // useful because it doesn't always reflect whether there is data in the h/w
790 // buffers, particularly if a track has been paused and resumed during draining
791 ALOGV("presentationComplete() mPresentationCompleteFrames %d framesWritten %d",
792 mPresentationCompleteFrames, framesWritten);
Eric Laurent81784c32012-11-19 14:55:58 -0800793 if (mPresentationCompleteFrames == 0) {
794 mPresentationCompleteFrames = framesWritten + audioHalFrames;
795 ALOGV("presentationComplete() reset: mPresentationCompleteFrames %d audioHalFrames %d",
796 mPresentationCompleteFrames, audioHalFrames);
797 }
Eric Laurentbfb1b832013-01-07 09:53:42 -0800798
799 if (framesWritten >= mPresentationCompleteFrames || isOffloaded()) {
Eric Laurent81784c32012-11-19 14:55:58 -0800800 ALOGV("presentationComplete() session %d complete: framesWritten %d",
801 mSessionId, framesWritten);
802 triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
Eric Laurentbfb1b832013-01-07 09:53:42 -0800803 mAudioTrackServerProxy->setStreamEndDone();
Eric Laurent81784c32012-11-19 14:55:58 -0800804 return true;
805 }
806 return false;
807}
808
809void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
810{
811 for (int i = 0; i < (int)mSyncEvents.size(); i++) {
812 if (mSyncEvents[i]->type() == type) {
813 mSyncEvents[i]->trigger();
814 mSyncEvents.removeAt(i);
815 i--;
816 }
817 }
818}
819
820// implement VolumeBufferProvider interface
821
822uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR()
823{
824 // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
825 ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800826 uint32_t vlr = mAudioTrackServerProxy->getVolumeLR();
Eric Laurent81784c32012-11-19 14:55:58 -0800827 uint32_t vl = vlr & 0xFFFF;
828 uint32_t vr = vlr >> 16;
829 // track volumes come from shared memory, so can't be trusted and must be clamped
830 if (vl > MAX_GAIN_INT) {
831 vl = MAX_GAIN_INT;
832 }
833 if (vr > MAX_GAIN_INT) {
834 vr = MAX_GAIN_INT;
835 }
836 // now apply the cached master volume and stream type volume;
837 // this is trusted but lacks any synchronization or barrier so may be stale
838 float v = mCachedVolume;
839 vl *= v;
840 vr *= v;
841 // re-combine into U4.16
842 vlr = (vr << 16) | (vl & 0xFFFF);
843 // FIXME look at mute, pause, and stop flags
844 return vlr;
845}
846
847status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event)
848{
Eric Laurentbfb1b832013-01-07 09:53:42 -0800849 if (isTerminated() || mState == PAUSED ||
Eric Laurent81784c32012-11-19 14:55:58 -0800850 ((framesReady() == 0) && ((mSharedBuffer != 0) ||
851 (mState == STOPPED)))) {
852 ALOGW("Track::setSyncEvent() in invalid state %d on session %d %s mode, framesReady %d ",
853 mState, mSessionId, (mSharedBuffer != 0) ? "static" : "stream", framesReady());
854 event->cancel();
855 return INVALID_OPERATION;
856 }
857 (void) TrackBase::setSyncEvent(event);
858 return NO_ERROR;
859}
860
Glenn Kasten5736c352012-12-04 12:12:34 -0800861void AudioFlinger::PlaybackThread::Track::invalidate()
862{
Glenn Kasten9f80dd22012-12-18 15:57:32 -0800863 // FIXME should use proxy, and needs work
864 audio_track_cblk_t* cblk = mCblk;
865 android_atomic_or(CBLK_INVALID, &cblk->flags);
866 android_atomic_release_store(0x40000000, &cblk->mFutex);
867 // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
868 (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX);
Glenn Kasten5736c352012-12-04 12:12:34 -0800869 mIsInvalid = true;
870}
871
Eric Laurent81784c32012-11-19 14:55:58 -0800872// ----------------------------------------------------------------------------
873
874sp<AudioFlinger::PlaybackThread::TimedTrack>
875AudioFlinger::PlaybackThread::TimedTrack::create(
876 PlaybackThread *thread,
877 const sp<Client>& client,
878 audio_stream_type_t streamType,
879 uint32_t sampleRate,
880 audio_format_t format,
881 audio_channel_mask_t channelMask,
882 size_t frameCount,
883 const sp<IMemory>& sharedBuffer,
884 int sessionId) {
885 if (!client->reserveTimedTrack())
886 return 0;
887
888 return new TimedTrack(
889 thread, client, streamType, sampleRate, format, channelMask, frameCount,
890 sharedBuffer, sessionId);
891}
892
893AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
894 PlaybackThread *thread,
895 const sp<Client>& client,
896 audio_stream_type_t streamType,
897 uint32_t sampleRate,
898 audio_format_t format,
899 audio_channel_mask_t channelMask,
900 size_t frameCount,
901 const sp<IMemory>& sharedBuffer,
902 int sessionId)
903 : Track(thread, client, streamType, sampleRate, format, channelMask,
904 frameCount, sharedBuffer, sessionId, IAudioFlinger::TRACK_TIMED),
905 mQueueHeadInFlight(false),
906 mTrimQueueHeadOnRelease(false),
907 mFramesPendingInQueue(0),
908 mTimedSilenceBuffer(NULL),
909 mTimedSilenceBufferSize(0),
910 mTimedAudioOutputOnTime(false),
911 mMediaTimeTransformValid(false)
912{
913 LocalClock lc;
914 mLocalTimeFreq = lc.getLocalFreq();
915
916 mLocalTimeToSampleTransform.a_zero = 0;
917 mLocalTimeToSampleTransform.b_zero = 0;
918 mLocalTimeToSampleTransform.a_to_b_numer = sampleRate;
919 mLocalTimeToSampleTransform.a_to_b_denom = mLocalTimeFreq;
920 LinearTransform::reduce(&mLocalTimeToSampleTransform.a_to_b_numer,
921 &mLocalTimeToSampleTransform.a_to_b_denom);
922
923 mMediaTimeToSampleTransform.a_zero = 0;
924 mMediaTimeToSampleTransform.b_zero = 0;
925 mMediaTimeToSampleTransform.a_to_b_numer = sampleRate;
926 mMediaTimeToSampleTransform.a_to_b_denom = 1000000;
927 LinearTransform::reduce(&mMediaTimeToSampleTransform.a_to_b_numer,
928 &mMediaTimeToSampleTransform.a_to_b_denom);
929}
930
931AudioFlinger::PlaybackThread::TimedTrack::~TimedTrack() {
932 mClient->releaseTimedTrack();
933 delete [] mTimedSilenceBuffer;
934}
935
936status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer(
937 size_t size, sp<IMemory>* buffer) {
938
939 Mutex::Autolock _l(mTimedBufferQueueLock);
940
941 trimTimedBufferQueue_l();
942
943 // lazily initialize the shared memory heap for timed buffers
944 if (mTimedMemoryDealer == NULL) {
945 const int kTimedBufferHeapSize = 512 << 10;
946
947 mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize,
948 "AudioFlingerTimed");
949 if (mTimedMemoryDealer == NULL)
950 return NO_MEMORY;
951 }
952
953 sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size);
954 if (newBuffer == NULL) {
955 newBuffer = mTimedMemoryDealer->allocate(size);
956 if (newBuffer == NULL)
957 return NO_MEMORY;
958 }
959
960 *buffer = newBuffer;
961 return NO_ERROR;
962}
963
964// caller must hold mTimedBufferQueueLock
965void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueue_l() {
966 int64_t mediaTimeNow;
967 {
968 Mutex::Autolock mttLock(mMediaTimeTransformLock);
969 if (!mMediaTimeTransformValid)
970 return;
971
972 int64_t targetTimeNow;
973 status_t res = (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME)
974 ? mCCHelper.getCommonTime(&targetTimeNow)
975 : mCCHelper.getLocalTime(&targetTimeNow);
976
977 if (OK != res)
978 return;
979
980 if (!mMediaTimeTransform.doReverseTransform(targetTimeNow,
981 &mediaTimeNow)) {
982 return;
983 }
984 }
985
986 size_t trimEnd;
987 for (trimEnd = 0; trimEnd < mTimedBufferQueue.size(); trimEnd++) {
988 int64_t bufEnd;
989
990 if ((trimEnd + 1) < mTimedBufferQueue.size()) {
991 // We have a next buffer. Just use its PTS as the PTS of the frame
992 // following the last frame in this buffer. If the stream is sparse
993 // (ie, there are deliberate gaps left in the stream which should be
994 // filled with silence by the TimedAudioTrack), then this can result
995 // in one extra buffer being left un-trimmed when it could have
996 // been. In general, this is not typical, and we would rather
997 // optimized away the TS calculation below for the more common case
998 // where PTSes are contiguous.
999 bufEnd = mTimedBufferQueue[trimEnd + 1].pts();
1000 } else {
1001 // We have no next buffer. Compute the PTS of the frame following
1002 // the last frame in this buffer by computing the duration of of
1003 // this frame in media time units and adding it to the PTS of the
1004 // buffer.
1005 int64_t frameCount = mTimedBufferQueue[trimEnd].buffer()->size()
1006 / mFrameSize;
1007
1008 if (!mMediaTimeToSampleTransform.doReverseTransform(frameCount,
1009 &bufEnd)) {
1010 ALOGE("Failed to convert frame count of %lld to media time"
1011 " duration" " (scale factor %d/%u) in %s",
1012 frameCount,
1013 mMediaTimeToSampleTransform.a_to_b_numer,
1014 mMediaTimeToSampleTransform.a_to_b_denom,
1015 __PRETTY_FUNCTION__);
1016 break;
1017 }
1018 bufEnd += mTimedBufferQueue[trimEnd].pts();
1019 }
1020
1021 if (bufEnd > mediaTimeNow)
1022 break;
1023
1024 // Is the buffer we want to use in the middle of a mix operation right
1025 // now? If so, don't actually trim it. Just wait for the releaseBuffer
1026 // from the mixer which should be coming back shortly.
1027 if (!trimEnd && mQueueHeadInFlight) {
1028 mTrimQueueHeadOnRelease = true;
1029 }
1030 }
1031
1032 size_t trimStart = mTrimQueueHeadOnRelease ? 1 : 0;
1033 if (trimStart < trimEnd) {
1034 // Update the bookkeeping for framesReady()
1035 for (size_t i = trimStart; i < trimEnd; ++i) {
1036 updateFramesPendingAfterTrim_l(mTimedBufferQueue[i], "trim");
1037 }
1038
1039 // Now actually remove the buffers from the queue.
1040 mTimedBufferQueue.removeItemsAt(trimStart, trimEnd);
1041 }
1042}
1043
1044void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueueHead_l(
1045 const char* logTag) {
1046 ALOG_ASSERT(mTimedBufferQueue.size() > 0,
1047 "%s called (reason \"%s\"), but timed buffer queue has no"
1048 " elements to trim.", __FUNCTION__, logTag);
1049
1050 updateFramesPendingAfterTrim_l(mTimedBufferQueue[0], logTag);
1051 mTimedBufferQueue.removeAt(0);
1052}
1053
1054void AudioFlinger::PlaybackThread::TimedTrack::updateFramesPendingAfterTrim_l(
1055 const TimedBuffer& buf,
1056 const char* logTag) {
1057 uint32_t bufBytes = buf.buffer()->size();
1058 uint32_t consumedAlready = buf.position();
1059
1060 ALOG_ASSERT(consumedAlready <= bufBytes,
1061 "Bad bookkeeping while updating frames pending. Timed buffer is"
1062 " only %u bytes long, but claims to have consumed %u"
1063 " bytes. (update reason: \"%s\")",
1064 bufBytes, consumedAlready, logTag);
1065
1066 uint32_t bufFrames = (bufBytes - consumedAlready) / mFrameSize;
1067 ALOG_ASSERT(mFramesPendingInQueue >= bufFrames,
1068 "Bad bookkeeping while updating frames pending. Should have at"
1069 " least %u queued frames, but we think we have only %u. (update"
1070 " reason: \"%s\")",
1071 bufFrames, mFramesPendingInQueue, logTag);
1072
1073 mFramesPendingInQueue -= bufFrames;
1074}
1075
1076status_t AudioFlinger::PlaybackThread::TimedTrack::queueTimedBuffer(
1077 const sp<IMemory>& buffer, int64_t pts) {
1078
1079 {
1080 Mutex::Autolock mttLock(mMediaTimeTransformLock);
1081 if (!mMediaTimeTransformValid)
1082 return INVALID_OPERATION;
1083 }
1084
1085 Mutex::Autolock _l(mTimedBufferQueueLock);
1086
1087 uint32_t bufFrames = buffer->size() / mFrameSize;
1088 mFramesPendingInQueue += bufFrames;
1089 mTimedBufferQueue.add(TimedBuffer(buffer, pts));
1090
1091 return NO_ERROR;
1092}
1093
1094status_t AudioFlinger::PlaybackThread::TimedTrack::setMediaTimeTransform(
1095 const LinearTransform& xform, TimedAudioTrack::TargetTimeline target) {
1096
1097 ALOGVV("setMediaTimeTransform az=%lld bz=%lld n=%d d=%u tgt=%d",
1098 xform.a_zero, xform.b_zero, xform.a_to_b_numer, xform.a_to_b_denom,
1099 target);
1100
1101 if (!(target == TimedAudioTrack::LOCAL_TIME ||
1102 target == TimedAudioTrack::COMMON_TIME)) {
1103 return BAD_VALUE;
1104 }
1105
1106 Mutex::Autolock lock(mMediaTimeTransformLock);
1107 mMediaTimeTransform = xform;
1108 mMediaTimeTransformTarget = target;
1109 mMediaTimeTransformValid = true;
1110
1111 return NO_ERROR;
1112}
1113
1114#define min(a, b) ((a) < (b) ? (a) : (b))
1115
1116// implementation of getNextBuffer for tracks whose buffers have timestamps
1117status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer(
1118 AudioBufferProvider::Buffer* buffer, int64_t pts)
1119{
1120 if (pts == AudioBufferProvider::kInvalidPTS) {
1121 buffer->raw = NULL;
1122 buffer->frameCount = 0;
1123 mTimedAudioOutputOnTime = false;
1124 return INVALID_OPERATION;
1125 }
1126
1127 Mutex::Autolock _l(mTimedBufferQueueLock);
1128
1129 ALOG_ASSERT(!mQueueHeadInFlight,
1130 "getNextBuffer called without releaseBuffer!");
1131
1132 while (true) {
1133
1134 // if we have no timed buffers, then fail
1135 if (mTimedBufferQueue.isEmpty()) {
1136 buffer->raw = NULL;
1137 buffer->frameCount = 0;
1138 return NOT_ENOUGH_DATA;
1139 }
1140
1141 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
1142
1143 // calculate the PTS of the head of the timed buffer queue expressed in
1144 // local time
1145 int64_t headLocalPTS;
1146 {
1147 Mutex::Autolock mttLock(mMediaTimeTransformLock);
1148
1149 ALOG_ASSERT(mMediaTimeTransformValid, "media time transform invalid");
1150
1151 if (mMediaTimeTransform.a_to_b_denom == 0) {
1152 // the transform represents a pause, so yield silence
1153 timedYieldSilence_l(buffer->frameCount, buffer);
1154 return NO_ERROR;
1155 }
1156
1157 int64_t transformedPTS;
1158 if (!mMediaTimeTransform.doForwardTransform(head.pts(),
1159 &transformedPTS)) {
1160 // the transform failed. this shouldn't happen, but if it does
1161 // then just drop this buffer
1162 ALOGW("timedGetNextBuffer transform failed");
1163 buffer->raw = NULL;
1164 buffer->frameCount = 0;
1165 trimTimedBufferQueueHead_l("getNextBuffer; no transform");
1166 return NO_ERROR;
1167 }
1168
1169 if (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) {
1170 if (OK != mCCHelper.commonTimeToLocalTime(transformedPTS,
1171 &headLocalPTS)) {
1172 buffer->raw = NULL;
1173 buffer->frameCount = 0;
1174 return INVALID_OPERATION;
1175 }
1176 } else {
1177 headLocalPTS = transformedPTS;
1178 }
1179 }
1180
1181 // adjust the head buffer's PTS to reflect the portion of the head buffer
1182 // that has already been consumed
1183 int64_t effectivePTS = headLocalPTS +
1184 ((head.position() / mFrameSize) * mLocalTimeFreq / sampleRate());
1185
1186 // Calculate the delta in samples between the head of the input buffer
1187 // queue and the start of the next output buffer that will be written.
1188 // If the transformation fails because of over or underflow, it means
1189 // that the sample's position in the output stream is so far out of
1190 // whack that it should just be dropped.
1191 int64_t sampleDelta;
1192 if (llabs(effectivePTS - pts) >= (static_cast<int64_t>(1) << 31)) {
1193 ALOGV("*** head buffer is too far from PTS: dropped buffer");
1194 trimTimedBufferQueueHead_l("getNextBuffer, buf pts too far from"
1195 " mix");
1196 continue;
1197 }
1198 if (!mLocalTimeToSampleTransform.doForwardTransform(
1199 (effectivePTS - pts) << 32, &sampleDelta)) {
1200 ALOGV("*** too late during sample rate transform: dropped buffer");
1201 trimTimedBufferQueueHead_l("getNextBuffer, bad local to sample");
1202 continue;
1203 }
1204
1205 ALOGVV("*** getNextBuffer head.pts=%lld head.pos=%d pts=%lld"
1206 " sampleDelta=[%d.%08x]",
1207 head.pts(), head.position(), pts,
1208 static_cast<int32_t>((sampleDelta >= 0 ? 0 : 1)
1209 + (sampleDelta >> 32)),
1210 static_cast<uint32_t>(sampleDelta & 0xFFFFFFFF));
1211
1212 // if the delta between the ideal placement for the next input sample and
1213 // the current output position is within this threshold, then we will
1214 // concatenate the next input samples to the previous output
1215 const int64_t kSampleContinuityThreshold =
1216 (static_cast<int64_t>(sampleRate()) << 32) / 250;
1217
1218 // if this is the first buffer of audio that we're emitting from this track
1219 // then it should be almost exactly on time.
1220 const int64_t kSampleStartupThreshold = 1LL << 32;
1221
1222 if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) ||
1223 (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
1224 // the next input is close enough to being on time, so concatenate it
1225 // with the last output
1226 timedYieldSamples_l(buffer);
1227
1228 ALOGVV("*** on time: head.pos=%d frameCount=%u",
1229 head.position(), buffer->frameCount);
1230 return NO_ERROR;
1231 }
1232
1233 // Looks like our output is not on time. Reset our on timed status.
1234 // Next time we mix samples from our input queue, then should be within
1235 // the StartupThreshold.
1236 mTimedAudioOutputOnTime = false;
1237 if (sampleDelta > 0) {
1238 // the gap between the current output position and the proper start of
1239 // the next input sample is too big, so fill it with silence
1240 uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;
1241
1242 timedYieldSilence_l(framesUntilNextInput, buffer);
1243 ALOGV("*** silence: frameCount=%u", buffer->frameCount);
1244 return NO_ERROR;
1245 } else {
1246 // the next input sample is late
1247 uint32_t lateFrames = static_cast<uint32_t>(-((sampleDelta + 0x80000000) >> 32));
1248 size_t onTimeSamplePosition =
1249 head.position() + lateFrames * mFrameSize;
1250
1251 if (onTimeSamplePosition > head.buffer()->size()) {
1252 // all the remaining samples in the head are too late, so
1253 // drop it and move on
1254 ALOGV("*** too late: dropped buffer");
1255 trimTimedBufferQueueHead_l("getNextBuffer, dropped late buffer");
1256 continue;
1257 } else {
1258 // skip over the late samples
1259 head.setPosition(onTimeSamplePosition);
1260
1261 // yield the available samples
1262 timedYieldSamples_l(buffer);
1263
1264 ALOGV("*** late: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
1265 return NO_ERROR;
1266 }
1267 }
1268 }
1269}
1270
1271// Yield samples from the timed buffer queue head up to the given output
1272// buffer's capacity.
1273//
1274// Caller must hold mTimedBufferQueueLock
1275void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSamples_l(
1276 AudioBufferProvider::Buffer* buffer) {
1277
1278 const TimedBuffer& head = mTimedBufferQueue[0];
1279
1280 buffer->raw = (static_cast<uint8_t*>(head.buffer()->pointer()) +
1281 head.position());
1282
1283 uint32_t framesLeftInHead = ((head.buffer()->size() - head.position()) /
1284 mFrameSize);
1285 size_t framesRequested = buffer->frameCount;
1286 buffer->frameCount = min(framesLeftInHead, framesRequested);
1287
1288 mQueueHeadInFlight = true;
1289 mTimedAudioOutputOnTime = true;
1290}
1291
1292// Yield samples of silence up to the given output buffer's capacity
1293//
1294// Caller must hold mTimedBufferQueueLock
1295void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSilence_l(
1296 uint32_t numFrames, AudioBufferProvider::Buffer* buffer) {
1297
1298 // lazily allocate a buffer filled with silence
1299 if (mTimedSilenceBufferSize < numFrames * mFrameSize) {
1300 delete [] mTimedSilenceBuffer;
1301 mTimedSilenceBufferSize = numFrames * mFrameSize;
1302 mTimedSilenceBuffer = new uint8_t[mTimedSilenceBufferSize];
1303 memset(mTimedSilenceBuffer, 0, mTimedSilenceBufferSize);
1304 }
1305
1306 buffer->raw = mTimedSilenceBuffer;
1307 size_t framesRequested = buffer->frameCount;
1308 buffer->frameCount = min(numFrames, framesRequested);
1309
1310 mTimedAudioOutputOnTime = false;
1311}
1312
1313// AudioBufferProvider interface
1314void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer(
1315 AudioBufferProvider::Buffer* buffer) {
1316
1317 Mutex::Autolock _l(mTimedBufferQueueLock);
1318
1319 // If the buffer which was just released is part of the buffer at the head
1320 // of the queue, be sure to update the amt of the buffer which has been
1321 // consumed. If the buffer being returned is not part of the head of the
1322 // queue, its either because the buffer is part of the silence buffer, or
1323 // because the head of the timed queue was trimmed after the mixer called
1324 // getNextBuffer but before the mixer called releaseBuffer.
1325 if (buffer->raw == mTimedSilenceBuffer) {
1326 ALOG_ASSERT(!mQueueHeadInFlight,
1327 "Queue head in flight during release of silence buffer!");
1328 goto done;
1329 }
1330
1331 ALOG_ASSERT(mQueueHeadInFlight,
1332 "TimedTrack::releaseBuffer of non-silence buffer, but no queue"
1333 " head in flight.");
1334
1335 if (mTimedBufferQueue.size()) {
1336 TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
1337
1338 void* start = head.buffer()->pointer();
1339 void* end = reinterpret_cast<void*>(
1340 reinterpret_cast<uint8_t*>(head.buffer()->pointer())
1341 + head.buffer()->size());
1342
1343 ALOG_ASSERT((buffer->raw >= start) && (buffer->raw < end),
1344 "released buffer not within the head of the timed buffer"
1345 " queue; qHead = [%p, %p], released buffer = %p",
1346 start, end, buffer->raw);
1347
1348 head.setPosition(head.position() +
1349 (buffer->frameCount * mFrameSize));
1350 mQueueHeadInFlight = false;
1351
1352 ALOG_ASSERT(mFramesPendingInQueue >= buffer->frameCount,
1353 "Bad bookkeeping during releaseBuffer! Should have at"
1354 " least %u queued frames, but we think we have only %u",
1355 buffer->frameCount, mFramesPendingInQueue);
1356
1357 mFramesPendingInQueue -= buffer->frameCount;
1358
1359 if ((static_cast<size_t>(head.position()) >= head.buffer()->size())
1360 || mTrimQueueHeadOnRelease) {
1361 trimTimedBufferQueueHead_l("releaseBuffer");
1362 mTrimQueueHeadOnRelease = false;
1363 }
1364 } else {
1365 LOG_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no"
1366 " buffers in the timed buffer queue");
1367 }
1368
1369done:
1370 buffer->raw = 0;
1371 buffer->frameCount = 0;
1372}
1373
1374size_t AudioFlinger::PlaybackThread::TimedTrack::framesReady() const {
1375 Mutex::Autolock _l(mTimedBufferQueueLock);
1376 return mFramesPendingInQueue;
1377}
1378
1379AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer()
1380 : mPTS(0), mPosition(0) {}
1381
1382AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer(
1383 const sp<IMemory>& buffer, int64_t pts)
1384 : mBuffer(buffer), mPTS(pts), mPosition(0) {}
1385
1386
1387// ----------------------------------------------------------------------------
1388
1389AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
1390 PlaybackThread *playbackThread,
1391 DuplicatingThread *sourceThread,
1392 uint32_t sampleRate,
1393 audio_format_t format,
1394 audio_channel_mask_t channelMask,
1395 size_t frameCount)
1396 : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
1397 NULL, 0, IAudioFlinger::TRACK_DEFAULT),
Glenn Kastene3aa6592012-12-04 12:22:46 -08001398 mActive(false), mSourceThread(sourceThread), mClientProxy(NULL)
Eric Laurent81784c32012-11-19 14:55:58 -08001399{
1400
1401 if (mCblk != NULL) {
Eric Laurent81784c32012-11-19 14:55:58 -08001402 mOutBuffer.frameCount = 0;
1403 playbackThread->mTracks.add(this);
Glenn Kastene3aa6592012-12-04 12:22:46 -08001404 ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, "
1405 "mCblk->frameCount_ %u, mChannelMask 0x%08x mBufferEnd %p",
1406 mCblk, mBuffer,
1407 mCblk->frameCount_, mChannelMask, mBufferEnd);
1408 // since client and server are in the same process,
1409 // the buffer has the same virtual address on both sides
1410 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize);
Eric Laurent8d2d4932013-04-25 12:56:18 -07001411 mClientProxy->setVolumeLR((uint32_t(uint16_t(0x1000)) << 16) | uint16_t(0x1000));
1412 mClientProxy->setSendLevel(0.0);
1413 mClientProxy->setSampleRate(sampleRate);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001414 mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize,
1415 true /*clientInServer*/);
Eric Laurent81784c32012-11-19 14:55:58 -08001416 } else {
1417 ALOGW("Error creating output track on thread %p", playbackThread);
1418 }
1419}
1420
1421AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
1422{
1423 clearBufferQueue();
Glenn Kastene3aa6592012-12-04 12:22:46 -08001424 delete mClientProxy;
1425 // superclass destructor will now delete the server proxy and shared memory both refer to
Eric Laurent81784c32012-11-19 14:55:58 -08001426}
1427
1428status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
1429 int triggerSession)
1430{
1431 status_t status = Track::start(event, triggerSession);
1432 if (status != NO_ERROR) {
1433 return status;
1434 }
1435
1436 mActive = true;
1437 mRetryCount = 127;
1438 return status;
1439}
1440
1441void AudioFlinger::PlaybackThread::OutputTrack::stop()
1442{
1443 Track::stop();
1444 clearBufferQueue();
1445 mOutBuffer.frameCount = 0;
1446 mActive = false;
1447}
1448
1449bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
1450{
1451 Buffer *pInBuffer;
1452 Buffer inBuffer;
1453 uint32_t channelCount = mChannelCount;
1454 bool outputBufferFull = false;
1455 inBuffer.frameCount = frames;
1456 inBuffer.i16 = data;
1457
1458 uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
1459
1460 if (!mActive && frames != 0) {
1461 start();
1462 sp<ThreadBase> thread = mThread.promote();
1463 if (thread != 0) {
1464 MixerThread *mixerThread = (MixerThread *)thread.get();
1465 if (mFrameCount > frames) {
1466 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
1467 uint32_t startFrames = (mFrameCount - frames);
1468 pInBuffer = new Buffer;
1469 pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
1470 pInBuffer->frameCount = startFrames;
1471 pInBuffer->i16 = pInBuffer->mBuffer;
1472 memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
1473 mBufferQueue.add(pInBuffer);
1474 } else {
Glenn Kasten7c027242012-12-26 14:43:16 -08001475 ALOGW("OutputTrack::write() %p no more buffers in queue", this);
Eric Laurent81784c32012-11-19 14:55:58 -08001476 }
1477 }
1478 }
1479 }
1480
1481 while (waitTimeLeftMs) {
1482 // First write pending buffers, then new data
1483 if (mBufferQueue.size()) {
1484 pInBuffer = mBufferQueue.itemAt(0);
1485 } else {
1486 pInBuffer = &inBuffer;
1487 }
1488
1489 if (pInBuffer->frameCount == 0) {
1490 break;
1491 }
1492
1493 if (mOutBuffer.frameCount == 0) {
1494 mOutBuffer.frameCount = pInBuffer->frameCount;
1495 nsecs_t startTime = systemTime();
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001496 status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
1497 if (status != NO_ERROR) {
1498 ALOGV("OutputTrack::write() %p thread %p no more output buffers; status %d", this,
1499 mThread.unsafe_get(), status);
Eric Laurent81784c32012-11-19 14:55:58 -08001500 outputBufferFull = true;
1501 break;
1502 }
1503 uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
1504 if (waitTimeLeftMs >= waitTimeMs) {
1505 waitTimeLeftMs -= waitTimeMs;
1506 } else {
1507 waitTimeLeftMs = 0;
1508 }
1509 }
1510
1511 uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
1512 pInBuffer->frameCount;
1513 memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001514 Proxy::Buffer buf;
1515 buf.mFrameCount = outFrames;
1516 buf.mRaw = NULL;
1517 mClientProxy->releaseBuffer(&buf);
Eric Laurent81784c32012-11-19 14:55:58 -08001518 pInBuffer->frameCount -= outFrames;
1519 pInBuffer->i16 += outFrames * channelCount;
1520 mOutBuffer.frameCount -= outFrames;
1521 mOutBuffer.i16 += outFrames * channelCount;
1522
1523 if (pInBuffer->frameCount == 0) {
1524 if (mBufferQueue.size()) {
1525 mBufferQueue.removeAt(0);
1526 delete [] pInBuffer->mBuffer;
1527 delete pInBuffer;
1528 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this,
1529 mThread.unsafe_get(), mBufferQueue.size());
1530 } else {
1531 break;
1532 }
1533 }
1534 }
1535
1536 // If we could not write all frames, allocate a buffer and queue it for next time.
1537 if (inBuffer.frameCount) {
1538 sp<ThreadBase> thread = mThread.promote();
1539 if (thread != 0 && !thread->standby()) {
1540 if (mBufferQueue.size() < kMaxOverFlowBuffers) {
1541 pInBuffer = new Buffer;
1542 pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
1543 pInBuffer->frameCount = inBuffer.frameCount;
1544 pInBuffer->i16 = pInBuffer->mBuffer;
1545 memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount *
1546 sizeof(int16_t));
1547 mBufferQueue.add(pInBuffer);
1548 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this,
1549 mThread.unsafe_get(), mBufferQueue.size());
1550 } else {
1551 ALOGW("OutputTrack::write() %p thread %p no more overflow buffers",
1552 mThread.unsafe_get(), this);
1553 }
1554 }
1555 }
1556
1557 // Calling write() with a 0 length buffer, means that no more data will be written:
1558 // If no more buffers are pending, fill output track buffer to make sure it is started
1559 // by output mixer.
1560 if (frames == 0 && mBufferQueue.size() == 0) {
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001561 // FIXME borken, replace by getting framesReady() from proxy
1562 size_t user = 0; // was mCblk->user
1563 if (user < mFrameCount) {
1564 frames = mFrameCount - user;
Eric Laurent81784c32012-11-19 14:55:58 -08001565 pInBuffer = new Buffer;
1566 pInBuffer->mBuffer = new int16_t[frames * channelCount];
1567 pInBuffer->frameCount = frames;
1568 pInBuffer->i16 = pInBuffer->mBuffer;
1569 memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
1570 mBufferQueue.add(pInBuffer);
1571 } else if (mActive) {
1572 stop();
1573 }
1574 }
1575
1576 return outputBufferFull;
1577}
1578
1579status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
1580 AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
1581{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001582 ClientProxy::Buffer buf;
1583 buf.mFrameCount = buffer->frameCount;
1584 struct timespec timeout;
1585 timeout.tv_sec = waitTimeMs / 1000;
1586 timeout.tv_nsec = (int) (waitTimeMs % 1000) * 1000000;
1587 status_t status = mClientProxy->obtainBuffer(&buf, &timeout);
1588 buffer->frameCount = buf.mFrameCount;
1589 buffer->raw = buf.mRaw;
1590 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001591}
1592
Eric Laurent81784c32012-11-19 14:55:58 -08001593void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
1594{
1595 size_t size = mBufferQueue.size();
1596
1597 for (size_t i = 0; i < size; i++) {
1598 Buffer *pBuffer = mBufferQueue.itemAt(i);
1599 delete [] pBuffer->mBuffer;
1600 delete pBuffer;
1601 }
1602 mBufferQueue.clear();
1603}
1604
1605
1606// ----------------------------------------------------------------------------
1607// Record
1608// ----------------------------------------------------------------------------
1609
1610AudioFlinger::RecordHandle::RecordHandle(
1611 const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
1612 : BnAudioRecord(),
1613 mRecordTrack(recordTrack)
1614{
1615}
1616
1617AudioFlinger::RecordHandle::~RecordHandle() {
1618 stop_nonvirtual();
1619 mRecordTrack->destroy();
1620}
1621
1622sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
1623 return mRecordTrack->getCblk();
1624}
1625
1626status_t AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
1627 int triggerSession) {
1628 ALOGV("RecordHandle::start()");
1629 return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession);
1630}
1631
1632void AudioFlinger::RecordHandle::stop() {
1633 stop_nonvirtual();
1634}
1635
1636void AudioFlinger::RecordHandle::stop_nonvirtual() {
1637 ALOGV("RecordHandle::stop()");
1638 mRecordTrack->stop();
1639}
1640
1641status_t AudioFlinger::RecordHandle::onTransact(
1642 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1643{
1644 return BnAudioRecord::onTransact(code, data, reply, flags);
1645}
1646
1647// ----------------------------------------------------------------------------
1648
1649// RecordTrack constructor must be called with AudioFlinger::mLock held
1650AudioFlinger::RecordThread::RecordTrack::RecordTrack(
1651 RecordThread *thread,
1652 const sp<Client>& client,
1653 uint32_t sampleRate,
1654 audio_format_t format,
1655 audio_channel_mask_t channelMask,
1656 size_t frameCount,
1657 int sessionId)
1658 : TrackBase(thread, client, sampleRate, format,
Glenn Kastene3aa6592012-12-04 12:22:46 -08001659 channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, false /*isOut*/),
Eric Laurent81784c32012-11-19 14:55:58 -08001660 mOverflow(false)
1661{
1662 ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001663 if (mCblk != NULL) {
1664 mAudioRecordServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
1665 mFrameSize);
1666 mServerProxy = mAudioRecordServerProxy;
1667 }
Eric Laurent81784c32012-11-19 14:55:58 -08001668}
1669
1670AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
1671{
1672 ALOGV("%s", __func__);
1673}
1674
1675// AudioBufferProvider interface
1676status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer,
1677 int64_t pts)
1678{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001679 ServerProxy::Buffer buf;
1680 buf.mFrameCount = buffer->frameCount;
1681 status_t status = mServerProxy->obtainBuffer(&buf);
1682 buffer->frameCount = buf.mFrameCount;
1683 buffer->raw = buf.mRaw;
1684 if (buf.mFrameCount == 0) {
1685 // FIXME also wake futex so that overrun is noticed more quickly
1686 (void) android_atomic_or(CBLK_OVERRUN, &mCblk->flags);
Eric Laurent81784c32012-11-19 14:55:58 -08001687 }
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001688 return status;
Eric Laurent81784c32012-11-19 14:55:58 -08001689}
1690
1691status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
1692 int triggerSession)
1693{
1694 sp<ThreadBase> thread = mThread.promote();
1695 if (thread != 0) {
1696 RecordThread *recordThread = (RecordThread *)thread.get();
1697 return recordThread->start(this, event, triggerSession);
1698 } else {
1699 return BAD_VALUE;
1700 }
1701}
1702
1703void AudioFlinger::RecordThread::RecordTrack::stop()
1704{
1705 sp<ThreadBase> thread = mThread.promote();
1706 if (thread != 0) {
1707 RecordThread *recordThread = (RecordThread *)thread.get();
Glenn Kastena8356f62013-07-25 14:37:52 -07001708 if (recordThread->stop(this)) {
Eric Laurent81784c32012-11-19 14:55:58 -08001709 AudioSystem::stopInput(recordThread->id());
1710 }
1711 }
1712}
1713
1714void AudioFlinger::RecordThread::RecordTrack::destroy()
1715{
1716 // see comments at AudioFlinger::PlaybackThread::Track::destroy()
1717 sp<RecordTrack> keep(this);
1718 {
1719 sp<ThreadBase> thread = mThread.promote();
1720 if (thread != 0) {
1721 if (mState == ACTIVE || mState == RESUMING) {
1722 AudioSystem::stopInput(thread->id());
1723 }
1724 AudioSystem::releaseInput(thread->id());
1725 Mutex::Autolock _l(thread->mLock);
1726 RecordThread *recordThread = (RecordThread *) thread.get();
1727 recordThread->destroyTrack_l(this);
1728 }
1729 }
1730}
1731
1732
1733/*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
1734{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001735 result.append(" Clien Fmt Chn mask Session Step S Serv FrameCount\n");
Eric Laurent81784c32012-11-19 14:55:58 -08001736}
1737
1738void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
1739{
Glenn Kasten9f80dd22012-12-18 15:57:32 -08001740 snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %08x %05d\n",
Eric Laurent81784c32012-11-19 14:55:58 -08001741 (mClient == 0) ? getpid_cached : mClient->pid(),
1742 mFormat,
1743 mChannelMask,
1744 mSessionId,
1745 mStepCount,
1746 mState,
Eric Laurent81784c32012-11-19 14:55:58 -08001747 mCblk->server,
Eric Laurent81784c32012-11-19 14:55:58 -08001748 mFrameCount);
1749}
1750
Eric Laurent81784c32012-11-19 14:55:58 -08001751}; // namespace android