• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright 2018, 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 //#define LOG_NDEBUG 0
19 #define LOG_TAG "MediaPlayer2AudioOutput"
20 #include <mediaplayer2/MediaPlayer2AudioOutput.h>
21 
22 #include <cutils/properties.h> // for property_get
23 #include <utils/Log.h>
24 
25 #include <media/AudioPolicyHelper.h>
26 #include <media/AudioTrack.h>
27 #include <media/stagefright/foundation/ADebug.h>
28 
29 namespace {
30 
31 const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
32 
33 } // anonymous namespace
34 
35 namespace android {
36 
37 // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
38 /* static */ int MediaPlayer2AudioOutput::mMinBufferCount = 4;
39 /* static */ bool MediaPlayer2AudioOutput::mIsOnEmulator = false;
40 
dump(int fd,const Vector<String16> & args) const41 status_t MediaPlayer2AudioOutput::dump(int fd, const Vector<String16>& args) const {
42     const size_t SIZE = 256;
43     char buffer[SIZE];
44     String8 result;
45 
46     result.append(" MediaPlayer2AudioOutput\n");
47     snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n",
48             mStreamType, mLeftVolume, mRightVolume);
49     result.append(buffer);
50     snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
51             mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
52     result.append(buffer);
53     snprintf(buffer, 255, "  aux effect id(%d), send level (%f)\n",
54             mAuxEffectId, mSendLevel);
55     result.append(buffer);
56 
57     ::write(fd, result.string(), result.size());
58     if (mTrack != 0) {
59         mTrack->dump(fd, args);
60     }
61     return NO_ERROR;
62 }
63 
MediaPlayer2AudioOutput(audio_session_t sessionId,uid_t uid,int pid,const audio_attributes_t * attr,const sp<AudioSystem::AudioDeviceCallback> & deviceCallback)64 MediaPlayer2AudioOutput::MediaPlayer2AudioOutput(audio_session_t sessionId, uid_t uid, int pid,
65         const audio_attributes_t* attr, const sp<AudioSystem::AudioDeviceCallback>& deviceCallback)
66     : mCallback(NULL),
67       mCallbackCookie(NULL),
68       mCallbackData(NULL),
69       mStreamType(AUDIO_STREAM_MUSIC),
70       mLeftVolume(1.0),
71       mRightVolume(1.0),
72       mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
73       mSampleRateHz(0),
74       mMsecsPerFrame(0),
75       mFrameSize(0),
76       mSessionId(sessionId),
77       mUid(uid),
78       mPid(pid),
79       mSendLevel(0.0),
80       mAuxEffectId(0),
81       mFlags(AUDIO_OUTPUT_FLAG_NONE),
82       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
83       mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
84       mDeviceCallbackEnabled(false),
85       mDeviceCallback(deviceCallback) {
86     ALOGV("MediaPlayer2AudioOutput(%d)", sessionId);
87     if (attr != NULL) {
88         mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
89         if (mAttributes != NULL) {
90             memcpy(mAttributes, attr, sizeof(audio_attributes_t));
91             mStreamType = audio_attributes_to_stream_type(attr);
92         }
93     } else {
94         mAttributes = NULL;
95     }
96 
97     setMinBufferCount();
98 }
99 
~MediaPlayer2AudioOutput()100 MediaPlayer2AudioOutput::~MediaPlayer2AudioOutput() {
101     close();
102     free(mAttributes);
103     delete mCallbackData;
104 }
105 
106 //static
setMinBufferCount()107 void MediaPlayer2AudioOutput::setMinBufferCount() {
108     char value[PROPERTY_VALUE_MAX];
109     if (property_get("ro.kernel.qemu", value, 0)) {
110         mIsOnEmulator = true;
111         mMinBufferCount = 12;  // to prevent systematic buffer underrun for emulator
112     }
113 }
114 
115 // static
isOnEmulator()116 bool MediaPlayer2AudioOutput::isOnEmulator() {
117     setMinBufferCount();  // benign race wrt other threads
118     return mIsOnEmulator;
119 }
120 
121 // static
getMinBufferCount()122 int MediaPlayer2AudioOutput::getMinBufferCount() {
123     setMinBufferCount();  // benign race wrt other threads
124     return mMinBufferCount;
125 }
126 
bufferSize() const127 ssize_t MediaPlayer2AudioOutput::bufferSize() const {
128     Mutex::Autolock lock(mLock);
129     if (mTrack == 0) {
130         return NO_INIT;
131     }
132     return mTrack->frameCount() * mFrameSize;
133 }
134 
frameCount() const135 ssize_t MediaPlayer2AudioOutput::frameCount() const {
136     Mutex::Autolock lock(mLock);
137     if (mTrack == 0) {
138         return NO_INIT;
139     }
140     return mTrack->frameCount();
141 }
142 
channelCount() const143 ssize_t MediaPlayer2AudioOutput::channelCount() const {
144     Mutex::Autolock lock(mLock);
145     if (mTrack == 0) {
146         return NO_INIT;
147     }
148     return mTrack->channelCount();
149 }
150 
frameSize() const151 ssize_t MediaPlayer2AudioOutput::frameSize() const {
152     Mutex::Autolock lock(mLock);
153     if (mTrack == 0) {
154         return NO_INIT;
155     }
156     return mFrameSize;
157 }
158 
latency() const159 uint32_t MediaPlayer2AudioOutput::latency () const {
160     Mutex::Autolock lock(mLock);
161     if (mTrack == 0) {
162         return 0;
163     }
164     return mTrack->latency();
165 }
166 
msecsPerFrame() const167 float MediaPlayer2AudioOutput::msecsPerFrame() const {
168     Mutex::Autolock lock(mLock);
169     return mMsecsPerFrame;
170 }
171 
getPosition(uint32_t * position) const172 status_t MediaPlayer2AudioOutput::getPosition(uint32_t *position) const {
173     Mutex::Autolock lock(mLock);
174     if (mTrack == 0) {
175         return NO_INIT;
176     }
177     return mTrack->getPosition(position);
178 }
179 
getTimestamp(AudioTimestamp & ts) const180 status_t MediaPlayer2AudioOutput::getTimestamp(AudioTimestamp &ts) const {
181     Mutex::Autolock lock(mLock);
182     if (mTrack == 0) {
183         return NO_INIT;
184     }
185     return mTrack->getTimestamp(ts);
186 }
187 
188 // TODO: Remove unnecessary calls to getPlayedOutDurationUs()
189 // as it acquires locks and may query the audio driver.
190 //
191 // Some calls could conceivably retrieve extrapolated data instead of
192 // accessing getTimestamp() or getPosition() every time a data buffer with
193 // a media time is received.
194 //
195 // Calculate duration of played samples if played at normal rate (i.e., 1.0).
getPlayedOutDurationUs(int64_t nowUs) const196 int64_t MediaPlayer2AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const {
197     Mutex::Autolock lock(mLock);
198     if (mTrack == 0 || mSampleRateHz == 0) {
199         return 0;
200     }
201 
202     uint32_t numFramesPlayed;
203     int64_t numFramesPlayedAtUs;
204     AudioTimestamp ts;
205 
206     status_t res = mTrack->getTimestamp(ts);
207     if (res == OK) {                 // case 1: mixing audio tracks and offloaded tracks.
208         numFramesPlayed = ts.mPosition;
209         numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
210         //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
211     } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
212         numFramesPlayed = 0;
213         numFramesPlayedAtUs = nowUs;
214         //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
215         //        numFramesPlayed, (long long)numFramesPlayedAtUs);
216     } else {                         // case 3: transitory at new track or audio fast tracks.
217         res = mTrack->getPosition(&numFramesPlayed);
218         CHECK_EQ(res, (status_t)OK);
219         numFramesPlayedAtUs = nowUs;
220         numFramesPlayedAtUs += 1000LL * mTrack->latency() / 2; /* XXX */
221         //ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
222     }
223 
224     // CHECK_EQ(numFramesPlayed & (1 << 31), 0);  // can't be negative until 12.4 hrs, test
225     // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
226     int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
227             + nowUs - numFramesPlayedAtUs;
228     if (durationUs < 0) {
229         // Occurs when numFramesPlayed position is very small and the following:
230         // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
231         //     numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
232         // (2) In case 3, using getPosition and adding mAudioSink->latency() to
233         //     numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
234         //
235         // Both of these are transitory conditions.
236         ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
237         durationUs = 0;
238     }
239     ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
240             (long long)durationUs, (long long)nowUs,
241             numFramesPlayed, (long long)numFramesPlayedAtUs);
242     return durationUs;
243 }
244 
getFramesWritten(uint32_t * frameswritten) const245 status_t MediaPlayer2AudioOutput::getFramesWritten(uint32_t *frameswritten) const {
246     Mutex::Autolock lock(mLock);
247     if (mTrack == 0) {
248         return NO_INIT;
249     }
250     ExtendedTimestamp ets;
251     status_t status = mTrack->getTimestamp(&ets);
252     if (status == OK || status == WOULD_BLOCK) {
253         *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
254     }
255     return status;
256 }
257 
setParameters(const String8 & keyValuePairs)258 status_t MediaPlayer2AudioOutput::setParameters(const String8& keyValuePairs) {
259     Mutex::Autolock lock(mLock);
260     if (mTrack == 0) {
261         return NO_INIT;
262     }
263     return mTrack->setParameters(keyValuePairs);
264 }
265 
getParameters(const String8 & keys)266 String8  MediaPlayer2AudioOutput::getParameters(const String8& keys) {
267     Mutex::Autolock lock(mLock);
268     if (mTrack == 0) {
269         return String8::empty();
270     }
271     return mTrack->getParameters(keys);
272 }
273 
setAudioAttributes(const audio_attributes_t * attributes)274 void MediaPlayer2AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
275     Mutex::Autolock lock(mLock);
276     if (attributes == NULL) {
277         free(mAttributes);
278         mAttributes = NULL;
279     } else {
280         if (mAttributes == NULL) {
281             mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
282         }
283         memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
284         mStreamType = audio_attributes_to_stream_type(attributes);
285     }
286 }
287 
setAudioStreamType(audio_stream_type_t streamType)288 void MediaPlayer2AudioOutput::setAudioStreamType(audio_stream_type_t streamType) {
289     Mutex::Autolock lock(mLock);
290     // do not allow direct stream type modification if attributes have been set
291     if (mAttributes == NULL) {
292         mStreamType = streamType;
293     }
294 }
295 
close_l()296 void MediaPlayer2AudioOutput::close_l() {
297     mTrack.clear();
298 }
299 
open(uint32_t sampleRate,int channelCount,audio_channel_mask_t channelMask,audio_format_t format,int bufferCount,AudioCallback cb,void * cookie,audio_output_flags_t flags,const audio_offload_info_t * offloadInfo,bool doNotReconnect,uint32_t suggestedFrameCount)300 status_t MediaPlayer2AudioOutput::open(
301         uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
302         audio_format_t format, int bufferCount,
303         AudioCallback cb, void *cookie,
304         audio_output_flags_t flags,
305         const audio_offload_info_t *offloadInfo,
306         bool doNotReconnect,
307         uint32_t suggestedFrameCount) {
308     ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
309                 format, bufferCount, mSessionId, flags);
310 
311     // offloading is only supported in callback mode for now.
312     // offloadInfo must be present if offload flag is set
313     if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
314             ((cb == NULL) || (offloadInfo == NULL))) {
315         return BAD_VALUE;
316     }
317 
318     // compute frame count for the AudioTrack internal buffer
319     size_t frameCount;
320     if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
321         frameCount = 0; // AudioTrack will get frame count from AudioFlinger
322     } else {
323         // try to estimate the buffer processing fetch size from AudioFlinger.
324         // framesPerBuffer is approximate and generally correct, except when it's not :-).
325         uint32_t afSampleRate;
326         size_t afFrameCount;
327         if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
328             return NO_INIT;
329         }
330         if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
331             return NO_INIT;
332         }
333         const size_t framesPerBuffer =
334                 (unsigned long long)sampleRate * afFrameCount / afSampleRate;
335 
336         if (bufferCount == 0) {
337             // use suggestedFrameCount
338             bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
339         }
340         // Check argument bufferCount against the mininum buffer count
341         if (bufferCount != 0 && bufferCount < mMinBufferCount) {
342             ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
343             bufferCount = mMinBufferCount;
344         }
345         // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
346         // which will be the minimum size permitted.
347         frameCount = bufferCount * framesPerBuffer;
348     }
349 
350     if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
351         channelMask = audio_channel_out_mask_from_count(channelCount);
352         if (0 == channelMask) {
353             ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
354             return NO_INIT;
355         }
356     }
357 
358     Mutex::Autolock lock(mLock);
359     mCallback = cb;
360     mCallbackCookie = cookie;
361 
362     sp<AudioTrack> t;
363     CallbackData *newcbd = NULL;
364 
365     ALOGV("creating new AudioTrack");
366 
367     if (mCallback != NULL) {
368         newcbd = new CallbackData(this);
369         t = new AudioTrack(
370                 mStreamType,
371                 sampleRate,
372                 format,
373                 channelMask,
374                 frameCount,
375                 flags,
376                 CallbackWrapper,
377                 newcbd,
378                 0,  // notification frames
379                 mSessionId,
380                 AudioTrack::TRANSFER_CALLBACK,
381                 offloadInfo,
382                 mUid,
383                 mPid,
384                 mAttributes,
385                 doNotReconnect,
386                 1.0f,  // default value for maxRequiredSpeed
387                 mSelectedDeviceId);
388     } else {
389         // TODO: Due to buffer memory concerns, we use a max target playback speed
390         // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
391         // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
392         const float targetSpeed =
393                 std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
394         ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
395                 "track target speed:%f clamped from playback speed:%f",
396                 targetSpeed, mPlaybackRate.mSpeed);
397         t = new AudioTrack(
398                 mStreamType,
399                 sampleRate,
400                 format,
401                 channelMask,
402                 frameCount,
403                 flags,
404                 NULL, // callback
405                 NULL, // user data
406                 0, // notification frames
407                 mSessionId,
408                 AudioTrack::TRANSFER_DEFAULT,
409                 NULL, // offload info
410                 mUid,
411                 mPid,
412                 mAttributes,
413                 doNotReconnect,
414                 targetSpeed,
415                 mSelectedDeviceId);
416     }
417 
418     if ((t == 0) || (t->initCheck() != NO_ERROR)) {
419         ALOGE("Unable to create audio track");
420         delete newcbd;
421         // t goes out of scope, so reference count drops to zero
422         return NO_INIT;
423     } else {
424         // successful AudioTrack initialization implies a legacy stream type was generated
425         // from the audio attributes
426         mStreamType = t->streamType();
427     }
428 
429     CHECK((t != NULL) && ((mCallback == NULL) || (newcbd != NULL)));
430 
431     mCallbackData = newcbd;
432     ALOGV("setVolume");
433     t->setVolume(mLeftVolume, mRightVolume);
434 
435     mSampleRateHz = sampleRate;
436     mFlags = flags;
437     mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
438     mFrameSize = t->frameSize();
439     mTrack = t;
440 
441     return updateTrack_l();
442 }
443 
updateTrack_l()444 status_t MediaPlayer2AudioOutput::updateTrack_l() {
445     if (mTrack == NULL) {
446         return NO_ERROR;
447     }
448 
449     status_t res = NO_ERROR;
450     // Note some output devices may give us a direct track even though we don't specify it.
451     // Example: Line application b/17459982.
452     if ((mTrack->getFlags()
453             & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
454         res = mTrack->setPlaybackRate(mPlaybackRate);
455         if (res == NO_ERROR) {
456             mTrack->setAuxEffectSendLevel(mSendLevel);
457             res = mTrack->attachAuxEffect(mAuxEffectId);
458         }
459     }
460     mTrack->setOutputDevice(mSelectedDeviceId);
461     if (mDeviceCallbackEnabled) {
462         mTrack->addAudioDeviceCallback(mDeviceCallback.promote());
463     }
464     ALOGV("updateTrack_l() DONE status %d", res);
465     return res;
466 }
467 
start()468 status_t MediaPlayer2AudioOutput::start() {
469     ALOGV("start");
470     Mutex::Autolock lock(mLock);
471     if (mCallbackData != NULL) {
472         mCallbackData->endTrackSwitch();
473     }
474     if (mTrack != 0) {
475         mTrack->setVolume(mLeftVolume, mRightVolume);
476         mTrack->setAuxEffectSendLevel(mSendLevel);
477         status_t status = mTrack->start();
478         return status;
479     }
480     return NO_INIT;
481 }
482 
write(const void * buffer,size_t size,bool blocking)483 ssize_t MediaPlayer2AudioOutput::write(const void* buffer, size_t size, bool blocking) {
484     Mutex::Autolock lock(mLock);
485     LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
486 
487     //ALOGV("write(%p, %u)", buffer, size);
488     if (mTrack != 0) {
489         return mTrack->write(buffer, size, blocking);
490     }
491     return NO_INIT;
492 }
493 
stop()494 void MediaPlayer2AudioOutput::stop() {
495     ALOGV("stop");
496     Mutex::Autolock lock(mLock);
497     if (mTrack != 0) {
498         mTrack->stop();
499     }
500 }
501 
flush()502 void MediaPlayer2AudioOutput::flush() {
503     ALOGV("flush");
504     Mutex::Autolock lock(mLock);
505     if (mTrack != 0) {
506         mTrack->flush();
507     }
508 }
509 
pause()510 void MediaPlayer2AudioOutput::pause() {
511     ALOGV("pause");
512     Mutex::Autolock lock(mLock);
513     if (mTrack != 0) {
514         mTrack->pause();
515     }
516 }
517 
close()518 void MediaPlayer2AudioOutput::close() {
519     ALOGV("close");
520     sp<AudioTrack> track;
521     {
522         Mutex::Autolock lock(mLock);
523         track = mTrack;
524         close_l(); // clears mTrack
525     }
526     // destruction of the track occurs outside of mutex.
527 }
528 
setVolume(float left,float right)529 void MediaPlayer2AudioOutput::setVolume(float left, float right) {
530     ALOGV("setVolume(%f, %f)", left, right);
531     Mutex::Autolock lock(mLock);
532     mLeftVolume = left;
533     mRightVolume = right;
534     if (mTrack != 0) {
535         mTrack->setVolume(left, right);
536     }
537 }
538 
setPlaybackRate(const AudioPlaybackRate & rate)539 status_t MediaPlayer2AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate) {
540     ALOGV("setPlaybackRate(%f %f %d %d)",
541                 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
542     Mutex::Autolock lock(mLock);
543     if (mTrack == 0) {
544         // remember rate so that we can set it when the track is opened
545         mPlaybackRate = rate;
546         return OK;
547     }
548     status_t res = mTrack->setPlaybackRate(rate);
549     if (res != NO_ERROR) {
550         return res;
551     }
552     // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
553     CHECK_GT(rate.mSpeed, 0.f);
554     mPlaybackRate = rate;
555     if (mSampleRateHz != 0) {
556         mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
557     }
558     return res;
559 }
560 
getPlaybackRate(AudioPlaybackRate * rate)561 status_t MediaPlayer2AudioOutput::getPlaybackRate(AudioPlaybackRate *rate) {
562     ALOGV("setPlaybackRate");
563     Mutex::Autolock lock(mLock);
564     if (mTrack == 0) {
565         return NO_INIT;
566     }
567     *rate = mTrack->getPlaybackRate();
568     return NO_ERROR;
569 }
570 
setAuxEffectSendLevel(float level)571 status_t MediaPlayer2AudioOutput::setAuxEffectSendLevel(float level) {
572     ALOGV("setAuxEffectSendLevel(%f)", level);
573     Mutex::Autolock lock(mLock);
574     mSendLevel = level;
575     if (mTrack != 0) {
576         return mTrack->setAuxEffectSendLevel(level);
577     }
578     return NO_ERROR;
579 }
580 
attachAuxEffect(int effectId)581 status_t MediaPlayer2AudioOutput::attachAuxEffect(int effectId) {
582     ALOGV("attachAuxEffect(%d)", effectId);
583     Mutex::Autolock lock(mLock);
584     mAuxEffectId = effectId;
585     if (mTrack != 0) {
586         return mTrack->attachAuxEffect(effectId);
587     }
588     return NO_ERROR;
589 }
590 
setOutputDevice(audio_port_handle_t deviceId)591 status_t MediaPlayer2AudioOutput::setOutputDevice(audio_port_handle_t deviceId) {
592     ALOGV("setOutputDevice(%d)", deviceId);
593     Mutex::Autolock lock(mLock);
594     mSelectedDeviceId = deviceId;
595     if (mTrack != 0) {
596         return mTrack->setOutputDevice(deviceId);
597     }
598     return NO_ERROR;
599 }
600 
getRoutedDeviceId(audio_port_handle_t * deviceId)601 status_t MediaPlayer2AudioOutput::getRoutedDeviceId(audio_port_handle_t* deviceId) {
602     ALOGV("getRoutedDeviceId");
603     Mutex::Autolock lock(mLock);
604     if (mTrack != 0) {
605         mRoutedDeviceId = mTrack->getRoutedDeviceId();
606     }
607     *deviceId = mRoutedDeviceId;
608     return NO_ERROR;
609 }
610 
enableAudioDeviceCallback(bool enabled)611 status_t MediaPlayer2AudioOutput::enableAudioDeviceCallback(bool enabled) {
612     ALOGV("enableAudioDeviceCallback, %d", enabled);
613     Mutex::Autolock lock(mLock);
614     mDeviceCallbackEnabled = enabled;
615     if (mTrack != 0) {
616         status_t status;
617         if (enabled) {
618             status = mTrack->addAudioDeviceCallback(mDeviceCallback.promote());
619         } else {
620             status = mTrack->removeAudioDeviceCallback(mDeviceCallback.promote());
621         }
622         return status;
623     }
624     return NO_ERROR;
625 }
626 
627 // static
CallbackWrapper(int event,void * cookie,void * info)628 void MediaPlayer2AudioOutput::CallbackWrapper(
629         int event, void *cookie, void *info) {
630     //ALOGV("callbackwrapper");
631     CallbackData *data = (CallbackData*)cookie;
632     // lock to ensure we aren't caught in the middle of a track switch.
633     data->lock();
634     MediaPlayer2AudioOutput *me = data->getOutput();
635     AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
636     if (me == NULL) {
637         // no output set, likely because the track was scheduled to be reused
638         // by another player, but the format turned out to be incompatible.
639         data->unlock();
640         if (buffer != NULL) {
641             buffer->size = 0;
642         }
643         return;
644     }
645 
646     switch(event) {
647     case AudioTrack::EVENT_MORE_DATA: {
648         size_t actualSize = (*me->mCallback)(
649                 me, buffer->raw, buffer->size, me->mCallbackCookie,
650                 CB_EVENT_FILL_BUFFER);
651 
652         // Log when no data is returned from the callback.
653         // (1) We may have no data (especially with network streaming sources).
654         // (2) We may have reached the EOS and the audio track is not stopped yet.
655         // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
656         // NuPlayer2Renderer will return zero when it doesn't have data (it doesn't block to fill).
657         //
658         // This is a benign busy-wait, with the next data request generated 10 ms or more later;
659         // nevertheless for power reasons, we don't want to see too many of these.
660 
661         ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
662 
663         buffer->size = actualSize;
664         } break;
665 
666     case AudioTrack::EVENT_STREAM_END:
667         // currently only occurs for offloaded callbacks
668         ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
669         (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
670                 me->mCallbackCookie, CB_EVENT_STREAM_END);
671         break;
672 
673     case AudioTrack::EVENT_NEW_IAUDIOTRACK :
674         ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
675         (*me->mCallback)(me,  NULL /* buffer */, 0 /* size */,
676                 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
677         break;
678 
679     case AudioTrack::EVENT_UNDERRUN:
680         // This occurs when there is no data available, typically
681         // when there is a failure to supply data to the AudioTrack.  It can also
682         // occur in non-offloaded mode when the audio device comes out of standby.
683         //
684         // If an AudioTrack underruns it outputs silence. Since this happens suddenly
685         // it may sound like an audible pop or glitch.
686         //
687         // The underrun event is sent once per track underrun; the condition is reset
688         // when more data is sent to the AudioTrack.
689         ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
690         break;
691 
692     default:
693         ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
694     }
695 
696     data->unlock();
697 }
698 
getSessionId() const699 audio_session_t MediaPlayer2AudioOutput::getSessionId() const
700 {
701     Mutex::Autolock lock(mLock);
702     return mSessionId;
703 }
704 
getSampleRate() const705 uint32_t MediaPlayer2AudioOutput::getSampleRate() const
706 {
707     Mutex::Autolock lock(mLock);
708     if (mTrack == 0) {
709         return 0;
710     }
711     return mTrack->getSampleRate();
712 }
713 
getBufferDurationInUs() const714 int64_t MediaPlayer2AudioOutput::getBufferDurationInUs() const
715 {
716     Mutex::Autolock lock(mLock);
717     if (mTrack == 0) {
718         return 0;
719     }
720     int64_t duration;
721     if (mTrack->getBufferDurationInUs(&duration) != OK) {
722         return 0;
723     }
724     return duration;
725 }
726 
727 } // namespace android
728