blob: a8e1d1f51c9a32543413ffbe421b34292acf6167 [file] [log] [blame]
Wei Jiaec044b02018-02-19 12:41:23 -08001/*
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
29namespace {
30
31const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
32
33} // anonymous namespace
34
35namespace 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
41status_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
64MediaPlayer2AudioOutput::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
100MediaPlayer2AudioOutput::~MediaPlayer2AudioOutput() {
101 close();
102 free(mAttributes);
103 delete mCallbackData;
104}
105
106//static
107void 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
116bool MediaPlayer2AudioOutput::isOnEmulator() {
117 setMinBufferCount(); // benign race wrt other threads
118 return mIsOnEmulator;
119}
120
121// static
122int MediaPlayer2AudioOutput::getMinBufferCount() {
123 setMinBufferCount(); // benign race wrt other threads
124 return mMinBufferCount;
125}
126
127ssize_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
135ssize_t MediaPlayer2AudioOutput::frameCount() const {
136 Mutex::Autolock lock(mLock);
137 if (mTrack == 0) {
138 return NO_INIT;
139 }
140 return mTrack->frameCount();
141}
142
143ssize_t MediaPlayer2AudioOutput::channelCount() const {
144 Mutex::Autolock lock(mLock);
145 if (mTrack == 0) {
146 return NO_INIT;
147 }
148 return mTrack->channelCount();
149}
150
151ssize_t MediaPlayer2AudioOutput::frameSize() const {
152 Mutex::Autolock lock(mLock);
153 if (mTrack == 0) {
154 return NO_INIT;
155 }
156 return mFrameSize;
157}
158
159uint32_t MediaPlayer2AudioOutput::latency () const {
160 Mutex::Autolock lock(mLock);
161 if (mTrack == 0) {
162 return 0;
163 }
164 return mTrack->latency();
165}
166
167float MediaPlayer2AudioOutput::msecsPerFrame() const {
168 Mutex::Autolock lock(mLock);
169 return mMsecsPerFrame;
170}
171
172status_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
180status_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).
196int64_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
245status_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
258status_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
266String8 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
274void 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
288void 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
296void MediaPlayer2AudioOutput::close_l() {
297 mTrack.clear();
298}
299
300status_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
444status_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
468status_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
483ssize_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
494void MediaPlayer2AudioOutput::stop() {
495 ALOGV("stop");
496 Mutex::Autolock lock(mLock);
497 if (mTrack != 0) {
498 mTrack->stop();
499 }
500}
501
502void MediaPlayer2AudioOutput::flush() {
503 ALOGV("flush");
504 Mutex::Autolock lock(mLock);
505 if (mTrack != 0) {
506 mTrack->flush();
507 }
508}
509
510void MediaPlayer2AudioOutput::pause() {
511 ALOGV("pause");
512 Mutex::Autolock lock(mLock);
513 if (mTrack != 0) {
514 mTrack->pause();
515 }
516}
517
518void 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
529void 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
539status_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
561status_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
571status_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
581status_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
591status_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
601status_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
611status_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
628void 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
699audio_session_t MediaPlayer2AudioOutput::getSessionId() const
700{
701 Mutex::Autolock lock(mLock);
702 return mSessionId;
703}
704
705uint32_t MediaPlayer2AudioOutput::getSampleRate() const
706{
707 Mutex::Autolock lock(mLock);
708 if (mTrack == 0) {
709 return 0;
710 }
711 return mTrack->getSampleRate();
712}
713
714int64_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