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