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