Home | History | Annotate | Download | only in libopensles
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define USE_LOG SLAndroidLogLevel_Verbose
     18 
     19 #include "android_SfPlayer.h"
     20 
     21 #include <stdio.h>
     22 #include "SLES/OpenSLES.h"
     23 #include "SLES/OpenSLES_Android.h"
     24 #include "sllog.h"
     25 #include <stdlib.h>
     26 
     27 #ifdef _DEBUG_AUDIO_TESTS
     28 // defines used for automated audio quality tests
     29 #define MONITOR_AUDIO_TARGET "/sdcard/playbackqual.raw"
     30 #define MONITOR_AUDIO_PLAY_PROP "system.media.sles-decode-dump"
     31 #include <cutils/properties.h> // for property_get
     32 #endif
     33 namespace android {
     34 
     35 SfPlayer::SfPlayer(AudioPlayback_Parameters *app)
     36     : mAudioTrack(NULL),
     37       mFlags(0),
     38       mBitrate(-1),
     39       mNumChannels(1),
     40       mSampleRateHz(0),
     41       mTimeDelta(-1),
     42       mDurationUsec(-1),
     43       mCacheStatus(kStatusEmpty),
     44       mSeekTimeMsec(0),
     45       mLastDecodedPositionUs(-1),
     46       mCacheFill(0),
     47       mLastNotifiedCacheFill(0),
     48       mCacheFillNotifThreshold(100),
     49       mDataLocatorType(kDataLocatorNone),
     50       mNotifyClient(NULL),
     51       mNotifyUser(NULL),
     52       mDecodeBuffer(NULL) {
     53 
     54       mRenderLooper = new android::ALooper();
     55 
     56       mPlaybackParams.sessionId = app->sessionId;
     57       mPlaybackParams.streamType = app->streamType;
     58       mPlaybackParams.trackcb = app->trackcb;
     59       mPlaybackParams.trackcbUser = app->trackcbUser;
     60 #ifdef _DEBUG_AUDIO_TESTS
     61       mMonitorAudioFp = NULL; // automated tests
     62 #endif
     63 }
     64 
     65 
     66 SfPlayer::~SfPlayer() {
     67     SL_LOGV("SfPlayer::~SfPlayer()");
     68 
     69     mRenderLooper->stop();
     70     mRenderLooper->unregisterHandler(this->id());
     71     mRenderLooper.clear();
     72 
     73     if (mAudioTrack != NULL) {
     74         mAudioTrack->stop();
     75         delete mAudioTrack;
     76         mAudioTrack = NULL;
     77     }
     78 
     79     if (mAudioSource != NULL) {
     80         {
     81             // don't even think about stopping the media source without releasing the decode buffer
     82             Mutex::Autolock _l(mDecodeBufferLock);
     83             if (NULL != mDecodeBuffer) {
     84                 mDecodeBuffer->release();
     85                 mDecodeBuffer = NULL;
     86             }
     87         }
     88         mAudioSource->stop();
     89     }
     90 
     91     resetDataLocator();
     92 }
     93 
     94 void SfPlayer::armLooper() {
     95     mRenderLooper->registerHandler(this);
     96     mRenderLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/,
     97             ANDROID_PRIORITY_AUDIO);
     98 }
     99 
    100 
    101 void SfPlayer::setNotifListener(const notif_client_t cbf, void* notifUser) {
    102     mNotifyClient = cbf;
    103     mNotifyUser = notifUser;
    104 }
    105 
    106 
    107 void SfPlayer::notifyPrepared(status_t prepareRes) {
    108     sp<AMessage> msg = new AMessage(kWhatNotif, id());
    109     msg->setInt32(EVENT_PREPARED, (int32_t)prepareRes);
    110     notify(msg, true /*async*/);
    111 }
    112 
    113 
    114 void SfPlayer::notifyStatus() {
    115     sp<AMessage> msg = new AMessage(kWhatNotif, id());
    116     msg->setInt32(EVENT_PREFETCHSTATUSCHANGE, (int32_t)mCacheStatus);
    117     notify(msg, true /*async*/);
    118 }
    119 
    120 
    121 void SfPlayer::notifyCacheFill() {
    122     sp<AMessage> msg = new AMessage(kWhatNotif, id());
    123     mLastNotifiedCacheFill = mCacheFill;
    124     msg->setInt32(EVENT_PREFETCHFILLLEVELUPDATE, (int32_t)mLastNotifiedCacheFill);
    125     notify(msg, true /*async*/);
    126 }
    127 
    128 
    129 void SfPlayer::notify(const sp<AMessage> &msg, bool async) {
    130     if (async) {
    131         msg->post();
    132     } else {
    133         onNotify(msg);
    134     }
    135 }
    136 
    137 
    138 void SfPlayer::setDataSource(const char *uri) {
    139     resetDataLocator();
    140 
    141     size_t len = strlen((const char *) uri);
    142     char* newUri = (char*) malloc(len + 1);
    143     if (NULL == newUri) {
    144         // mem issue
    145         SL_LOGE("SfPlayer::setDataSource: not enough memory to allocator URI string");
    146         return;
    147     }
    148     memcpy(newUri, uri, len + 1);
    149     mDataLocator.uri = newUri;
    150 
    151     mDataLocatorType = kDataLocatorUri;
    152 }
    153 
    154 void SfPlayer::setDataSource(const int fd, const int64_t offset, const int64_t length) {
    155     resetDataLocator();
    156 
    157     mDataLocator.fdi.fd = fd;
    158 
    159     struct stat sb;
    160     int ret = fstat(fd, &sb);
    161     if (ret != 0) {
    162         // sockets are not supported
    163         SL_LOGE("SfPlayer::setDataSource: fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
    164         return;
    165     }
    166 
    167     if (offset >= sb.st_size) {
    168         SL_LOGE("SfPlayer::setDataSource: invalid offset");
    169         return;
    170     }
    171     mDataLocator.fdi.offset = offset;
    172 
    173     if (SFPLAYER_FD_FIND_FILE_SIZE == length) {
    174         mDataLocator.fdi.length = sb.st_size;
    175     } else if (offset + length > sb.st_size) {
    176         mDataLocator.fdi.length = sb.st_size - offset;
    177     } else {
    178         mDataLocator.fdi.length = length;
    179     }
    180 
    181     mDataLocatorType = kDataLocatorFd;
    182 }
    183 
    184 void SfPlayer::prepare() {
    185     //SL_LOGV("SfPlayer::prepare()");
    186     sp<AMessage> msg = new AMessage(kWhatPrepare, id());
    187     msg->post();
    188 }
    189 
    190 
    191 void SfPlayer::onPrepare(const sp<AMessage> &msg) {
    192     SL_LOGV("SfPlayer::onPrepare");
    193     sp<DataSource> dataSource;
    194 
    195     switch (mDataLocatorType) {
    196 
    197         case kDataLocatorNone:
    198             SL_LOGE("SfPlayer::onPrepare: no data locator set");
    199             notifyPrepared(MEDIA_ERROR_BASE);
    200             break;
    201 
    202         case kDataLocatorUri:
    203             if (!strncasecmp(mDataLocator.uri, "http://", 7)) {
    204                 sp<NuHTTPDataSource> http = new NuHTTPDataSource;
    205                 if (http->connect(mDataLocator.uri) == OK) {
    206                     dataSource =
    207                         new NuCachedSource2(
    208                                 new ThrottledSource(
    209                                         http, 50 * 1024 /* bytes/sec */));
    210                 }
    211             } else {
    212                 dataSource = DataSource::CreateFromURI(mDataLocator.uri);
    213             }
    214             break;
    215 
    216         case kDataLocatorFd: {
    217             dataSource = new FileSource(
    218                     mDataLocator.fdi.fd, mDataLocator.fdi.offset, mDataLocator.fdi.length);
    219             status_t err = dataSource->initCheck();
    220             if (err != OK) {
    221                 notifyPrepared(err);
    222                 return;
    223             }
    224             }
    225             break;
    226 
    227         default:
    228             TRESPASS();
    229     }
    230 
    231     if (dataSource == NULL) {
    232         SL_LOGE("SfPlayer::onPrepare: Could not create data source.");
    233         notifyPrepared(ERROR_UNSUPPORTED);
    234         return;
    235     }
    236 
    237     sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
    238     if (extractor == NULL) {
    239         SL_LOGE("SfPlayer::onPrepare: Could not instantiate extractor.");
    240         notifyPrepared(ERROR_UNSUPPORTED);
    241         return;
    242     }
    243 
    244     ssize_t audioTrackIndex = -1;
    245     bool isRawAudio = false;
    246     for (size_t i = 0; i < extractor->countTracks(); ++i) {
    247         sp<MetaData> meta = extractor->getTrackMetaData(i);
    248 
    249         const char *mime;
    250         CHECK(meta->findCString(kKeyMIMEType, &mime));
    251 
    252         if (!strncasecmp("audio/", mime, 6)) {
    253             audioTrackIndex = i;
    254 
    255             if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
    256                 isRawAudio = true;
    257             }
    258             break;
    259         }
    260     }
    261 
    262     if (audioTrackIndex < 0) {
    263         SL_LOGE("SfPlayer::onPrepare: Could not find a supported audio track.");
    264         notifyPrepared(ERROR_UNSUPPORTED);
    265         return;
    266     }
    267 
    268     sp<MediaSource> source = extractor->getTrack(audioTrackIndex);
    269     sp<MetaData> meta = source->getFormat();
    270 
    271     off_t size;
    272     int64_t durationUs;
    273     if (dataSource->getSize(&size) == OK
    274             && meta->findInt64(kKeyDuration, &durationUs)) {
    275         mBitrate = size * 8000000ll / durationUs;  // in bits/sec
    276         mDurationUsec = durationUs;
    277     } else {
    278         mBitrate = -1;
    279         mDurationUsec = -1;
    280     }
    281 
    282     if (!isRawAudio) {
    283         OMXClient client;
    284         CHECK_EQ(client.connect(), (status_t)OK);
    285 
    286         source = OMXCodec::Create(
    287                 client.interface(), meta, false /* createEncoder */,
    288                 source);
    289 
    290         if (source == NULL) {
    291             SL_LOGE("SfPlayer::onPrepare: Could not instantiate decoder.");
    292             notifyPrepared(ERROR_UNSUPPORTED);
    293             return;
    294         }
    295 
    296         meta = source->getFormat();
    297     }
    298 
    299     if (source->start() != OK) {
    300         SL_LOGE("SfPlayer::onPrepare: Failed to start source/decoder.");
    301         notifyPrepared(MEDIA_ERROR_BASE);
    302         return;
    303     }
    304 
    305     mDataSource = dataSource;
    306     mAudioSource = source;
    307 
    308     CHECK(meta->findInt32(kKeyChannelCount, &mNumChannels));
    309     CHECK(meta->findInt32(kKeySampleRate, &mSampleRateHz));
    310 
    311     if (!wantPrefetch()) {
    312         SL_LOGV("SfPlayer::onPrepare: no need to prefetch");
    313         // doesn't need prefetching, notify good to go
    314         mCacheStatus = kStatusHigh;
    315         mCacheFill = 1000;
    316         notifyStatus();
    317         notifyCacheFill();
    318     }
    319 
    320     // at this point we have enough information about the source to create its associated AudioTrack
    321     assert(NULL == mAudioTrack);
    322     mAudioTrack = new android::AudioTrack(
    323             mPlaybackParams.streamType,                          // streamType
    324             mSampleRateHz,                                       // sampleRate
    325             android::AudioSystem::PCM_16_BIT,                    // format
    326             mNumChannels == 1 ?     //channel mask
    327                     android::AudioSystem::CHANNEL_OUT_MONO :
    328                     android::AudioSystem::CHANNEL_OUT_STEREO,
    329             0,                                                   // frameCount (here min)
    330             0,                                                   // flags
    331             mPlaybackParams.trackcb,                             // callback
    332             mPlaybackParams.trackcbUser,                         // user
    333             0,                                                   // notificationFrame
    334             mPlaybackParams.sessionId
    335         );
    336 
    337     //SL_LOGV("SfPlayer::onPrepare: end");
    338     notifyPrepared(SFPLAYER_SUCCESS);
    339 
    340 }
    341 
    342 
    343 bool SfPlayer::wantPrefetch() {
    344     return (mDataSource->flags() & DataSource::kWantsPrefetching);
    345 }
    346 
    347 
    348 void SfPlayer::startPrefetch_async() {
    349     SL_LOGV("SfPlayer::startPrefetch_async()");
    350     if (wantPrefetch()) {
    351         //SL_LOGV("SfPlayer::startPrefetch_async(): sending check cache msg");
    352 
    353         mFlags |= kFlagPreparing;
    354         mFlags |= kFlagBuffering;
    355 
    356         (new AMessage(kWhatCheckCache, id()))->post();
    357     }
    358 }
    359 
    360 
    361 void SfPlayer::play() {
    362     SL_LOGV("SfPlayer::play");
    363 
    364     (new AMessage(kWhatPlay, id()))->post();
    365     (new AMessage(kWhatDecode, id()))->post();
    366 }
    367 
    368 
    369 void SfPlayer::stop() {
    370     SL_LOGV("SfPlayer::stop");
    371 
    372     if (NULL != mAudioTrack) {
    373         mAudioTrack->stop();
    374     }
    375 
    376     (new AMessage(kWhatPause, id()))->post();
    377 
    378     // after a stop, playback should resume from the start.
    379     seek(0);
    380 }
    381 
    382 void SfPlayer::pause() {
    383     SL_LOGV("SfPlayer::pause");
    384     if (NULL == mAudioTrack) {
    385         return;
    386     }
    387     (new AMessage(kWhatPause, id()))->post();
    388     mAudioTrack->pause();
    389 }
    390 
    391 void SfPlayer::seek(int64_t timeMsec) {
    392     SL_LOGV("SfPlayer::seek %lld", timeMsec);
    393     sp<AMessage> msg = new AMessage(kWhatSeek, id());
    394     msg->setInt64("seek", timeMsec);
    395     msg->post();
    396 }
    397 
    398 
    399 void SfPlayer::loop(bool loop) {
    400     sp<AMessage> msg = new AMessage(kWhatLoop, id());
    401     msg->setInt32("loop", (int32_t)loop);
    402     msg->post();
    403 }
    404 
    405 
    406 uint32_t SfPlayer::getPositionMsec() {
    407     Mutex::Autolock _l(mSeekLock);
    408     if (mFlags & kFlagSeeking) {
    409         return (uint32_t) mSeekTimeMsec;
    410     } else {
    411         if (mLastDecodedPositionUs < 0) {
    412             return 0;
    413         } else {
    414             return (uint32_t) (mLastDecodedPositionUs / 1000);
    415         }
    416     }
    417 }
    418 
    419 
    420 int64_t SfPlayer::getPositionUsec() {
    421     Mutex::Autolock _l(mSeekLock);
    422     if (mFlags & kFlagSeeking) {
    423         return mSeekTimeMsec * 1000;
    424     } else {
    425         if (mLastDecodedPositionUs < 0) {
    426             return 0;
    427         } else {
    428             return mLastDecodedPositionUs;
    429         }
    430     }
    431 }
    432 
    433 /**
    434  * called from message loop
    435  */
    436 void SfPlayer::reachedEndOfStream() {
    437     SL_LOGV("SfPlayer::reachedEndOfStream");
    438     if (mFlags & kFlagPlaying) {
    439         // async notification of end of stream reached during playback
    440         sp<AMessage> msg = new AMessage(kWhatNotif, id());
    441         msg->setInt32(EVENT_ENDOFSTREAM, 1);
    442         notify(msg, true /*async*/);
    443     }
    444     if (mFlags & kFlagLooping) {
    445         seek(0);
    446         // kick-off decoding again
    447         (new AMessage(kWhatDecode, id()))->post();
    448     }
    449 }
    450 
    451 /**
    452  * called from message loop
    453  */
    454 void SfPlayer::updatePlaybackParamsFromSource() {
    455     if (mAudioSource != 0) {
    456         sp<MetaData> meta = mAudioSource->getFormat();
    457 
    458         SL_LOGV("old sample rate = %d", mSampleRateHz);
    459         CHECK(meta->findInt32(kKeyChannelCount, &mNumChannels));
    460         CHECK(meta->findInt32(kKeySampleRate, &mSampleRateHz));
    461         SL_LOGV("new sample rate = %d", mSampleRateHz);
    462 
    463         // the AudioTrack currently used by the AudioPlayer will be deleted by AudioPlayer itself
    464         // SfPlayer never deletes the AudioTrack it creates and uses.
    465         if (NULL != mAudioTrack) {
    466             mAudioTrack->stop();
    467             delete mAudioTrack;
    468             mAudioTrack = NULL;
    469         }
    470         mAudioTrack = new android::AudioTrack(
    471                 mPlaybackParams.streamType,                          // streamType
    472                 mSampleRateHz,                                       // sampleRate
    473                 android::AudioSystem::PCM_16_BIT,                    // format
    474                 mNumChannels == 1 ?     //channel mask
    475                         android::AudioSystem::CHANNEL_OUT_MONO :
    476                         android::AudioSystem::CHANNEL_OUT_STEREO,
    477                 0,                                                   // frameCount (here min)
    478                 0,                                                   // flags
    479                 mPlaybackParams.trackcb,                             // callback
    480                 mPlaybackParams.trackcbUser,                         // user
    481                 0,                                                   // notificationFrame
    482                 mPlaybackParams.sessionId
    483         );
    484         if (mFlags & kFlagPlaying) {
    485             mAudioTrack->start();
    486         }
    487 
    488         // notify the AudioPlayer synchronously there's a new AudioTrack to use and configure
    489         sp<AMessage> msg = new AMessage(kWhatNotif, id());
    490         msg->setInt32(EVENT_NEW_AUDIOTRACK, 0/*data field unused*/);
    491         notify(msg, false /*async*/);
    492     }
    493 }
    494 
    495 
    496 /**
    497  * Message handlers
    498  */
    499 
    500 void SfPlayer::onPlay() {
    501     SL_LOGV("SfPlayer::onPlay");
    502 #ifdef _DEBUG_AUDIO_TESTS
    503     // Automated tests: Open file for Intercepting pcm audio for quality validation
    504     char value[PROPERTY_VALUE_MAX];
    505     if (property_get(MONITOR_AUDIO_PLAY_PROP, value, NULL) &&
    506            (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
    507         mMonitorAudioFp = fopen(MONITOR_AUDIO_TARGET, "w");
    508         if (mMonitorAudioFp == NULL) { LOGE("error opening %s", MONITOR_AUDIO_TARGET); }
    509         else { LOGE("recording to %s", MONITOR_AUDIO_TARGET); }
    510     }
    511 #endif
    512     mFlags |= kFlagPlaying;
    513 
    514     if (NULL != mAudioTrack) {
    515         mAudioTrack->start();
    516     }
    517 }
    518 
    519 
    520 void SfPlayer::onPause() {
    521     SL_LOGV("SfPlayer::onPause");
    522     mFlags &= ~kFlagPlaying;
    523 #ifdef _DEBUG_AUDIO_TESTS
    524     // Automated tests: close intercept file
    525     if (mMonitorAudioFp != NULL) {
    526         fclose(mMonitorAudioFp);
    527     }
    528     mMonitorAudioFp = NULL;
    529 #endif
    530 }
    531 
    532 
    533 void SfPlayer::onSeek(const sp<AMessage> &msg) {
    534     SL_LOGV("SfPlayer::onSeek");
    535     int64_t timeMsec;
    536     CHECK(msg->findInt64("seek", &timeMsec));
    537 
    538     Mutex::Autolock _l(mSeekLock);
    539     mFlags |= kFlagSeeking;
    540     mSeekTimeMsec = timeMsec;
    541     mTimeDelta = -1;
    542     mLastDecodedPositionUs = -1;
    543 }
    544 
    545 
    546 void SfPlayer::onLoop(const sp<AMessage> &msg) {
    547     //SL_LOGV("SfPlayer::onLoop");
    548     int32_t loop;
    549     CHECK(msg->findInt32("loop", &loop));
    550 
    551     if (loop) {
    552         //SL_LOGV("SfPlayer::onLoop start looping");
    553         mFlags |= kFlagLooping;
    554     } else {
    555         //SL_LOGV("SfPlayer::onLoop stop looping");
    556         mFlags &= ~kFlagLooping;
    557     }
    558 }
    559 
    560 
    561 void SfPlayer::onDecode() {
    562     //SL_LOGV("SfPlayer::onDecode");
    563     bool eos;
    564     if (mDataSource == 0) {
    565         // application set play state to paused which failed, then set play state to playing
    566         return;
    567     }
    568     if ((mDataSource->flags() & DataSource::kWantsPrefetching)
    569             && (getCacheRemaining(&eos) == kStatusLow)
    570             && !eos) {
    571         SL_LOGV("buffering more.");
    572 
    573         if (mFlags & kFlagPlaying) {
    574             mAudioTrack->pause();
    575         }
    576         mFlags |= kFlagBuffering;
    577         (new AMessage(kWhatCheckCache, id()))->post(100000);
    578         return;
    579     }
    580 
    581     if (!(mFlags & (kFlagPlaying | kFlagBuffering | kFlagPreparing))) {
    582         // don't decode if we're not buffering, prefetching or playing
    583         //SL_LOGV("don't decode: not buffering, prefetching or playing");
    584         return;
    585     }
    586 
    587     status_t err;
    588     MediaSource::ReadOptions readOptions;
    589     if (mFlags & kFlagSeeking) {
    590         readOptions.setSeekTo(mSeekTimeMsec * 1000);
    591     }
    592 
    593     {
    594         Mutex::Autolock _l(mDecodeBufferLock);
    595         if (NULL != mDecodeBuffer) {
    596             // the current decoded buffer hasn't been rendered, drop it
    597             mDecodeBuffer->release();
    598             mDecodeBuffer = NULL;
    599         }
    600         err = mAudioSource->read(&mDecodeBuffer, &readOptions);
    601         if (err == OK) {
    602             CHECK(mDecodeBuffer->meta_data()->findInt64(kKeyTime, &mLastDecodedPositionUs));
    603         }
    604     }
    605 
    606     {
    607         Mutex::Autolock _l(mSeekLock);
    608         if (mFlags & kFlagSeeking) {
    609             mFlags &= ~kFlagSeeking;
    610         }
    611     }
    612 
    613     if (err != OK) {
    614         bool continueDecoding = false;
    615         switch(err) {
    616             case ERROR_END_OF_STREAM:
    617                 // handle notification and looping at end of stream
    618                 if (0 < mDurationUsec) {
    619                     mLastDecodedPositionUs = mDurationUsec;
    620                 }
    621                 reachedEndOfStream();
    622                 break;
    623             case INFO_FORMAT_CHANGED:
    624                 SL_LOGI("MediaSource::read encountered INFO_FORMAT_CHANGED");
    625                 // reconfigure output
    626                 updatePlaybackParamsFromSource();
    627                 continueDecoding = true;
    628                 break;
    629             case INFO_DISCONTINUITY:
    630                 SL_LOGI("MediaSource::read encountered INFO_DISCONTINUITY");
    631                 continueDecoding = true;
    632                 break;
    633             default:
    634                 SL_LOGE("MediaSource::read returned error %d", err);
    635                 break;
    636         }
    637         if (continueDecoding) {
    638             if (NULL == mDecodeBuffer) {
    639                 (new AMessage(kWhatDecode, id()))->post();
    640                 return;
    641             }
    642         } else {
    643             return;
    644         }
    645     }
    646 
    647     // render
    648 
    649     sp<AMessage> msg = new AMessage(kWhatRender, id());
    650 
    651     if (mTimeDelta < 0) {
    652         mTimeDelta = ALooper::GetNowUs() - mLastDecodedPositionUs;
    653     }
    654 
    655     int64_t delayUs = mLastDecodedPositionUs + mTimeDelta - ALooper::GetNowUs()
    656             - RENDER_SAFETY_DELAY_US; // negative delays are ignored
    657 
    658 
    659     if ((NULL != mAudioTrack) && (mAudioTrack->getSampleRate() > mSampleRateHz)) {
    660         // we're speeding up playback, feed data faster
    661         // FIXME not the right formula, delays need to be evaluated differently
    662         delayUs = RENDER_SAFETY_DELAY_US;
    663         //SL_LOGV("delayUs=%lld new", delayUs);
    664     }
    665 
    666     // FIXME clicks can be observed if solely relying on delayUs, this is a safe compromise
    667     msg->post(delayUs > RENDER_SAFETY_DELAY_US ? RENDER_SAFETY_DELAY_US : delayUs);
    668     //msg->post(delayUs); // negative delays are ignored
    669     //SL_LOGV("timeUs=%lld, mTimeDelta=%lld, delayUs=%lld",
    670     //        mLastDecodedPositionUs, mTimeDelta, delayUs);
    671 }
    672 
    673 
    674 void SfPlayer::onRender(const sp<AMessage> &msg) {
    675     //SL_LOGV("SfPlayer::onRender");
    676 
    677     Mutex::Autolock _l(mDecodeBufferLock);
    678 
    679     if (NULL == mDecodeBuffer) {
    680         // nothing to render, move along
    681         //SL_LOGV("SfPlayer::onRender NULL buffer, exiting");
    682         return;
    683     }
    684 
    685     if (mFlags & kFlagPlaying) {
    686         assert(NULL != mAudioTrack);
    687         mAudioTrack->write( (const uint8_t *)mDecodeBuffer->data() + mDecodeBuffer->range_offset(),
    688                 mDecodeBuffer->range_length());
    689         (new AMessage(kWhatDecode, id()))->post();
    690 #ifdef _DEBUG_AUDIO_TESTS
    691         // Automated tests: Intercept PCM data and write to file for later validations
    692         if (mMonitorAudioFp != NULL) {
    693             fwrite((const uint8_t *)mDecodeBuffer->data() + mDecodeBuffer->range_offset(),
    694                     mDecodeBuffer->range_length(), 1, mMonitorAudioFp);
    695         }
    696 #endif
    697     }
    698     mDecodeBuffer->release();
    699     mDecodeBuffer = NULL;
    700 
    701 }
    702 
    703 
    704 void SfPlayer::onCheckCache(const sp<AMessage> &msg) {
    705     //SL_LOGV("SfPlayer::onCheckCache");
    706     bool eos;
    707     CacheStatus status = getCacheRemaining(&eos);
    708 
    709     if (eos || status == kStatusHigh
    710             || ((mFlags & kFlagPreparing) && (status >= kStatusEnough))) {
    711         if (mFlags & kFlagPlaying) {
    712             assert(NULL != mAudioTrack);
    713             mAudioTrack->start();
    714         }
    715         mFlags &= ~kFlagBuffering;
    716 
    717         SL_LOGV("SfPlayer::onCheckCache: buffering done.");
    718 
    719         if (mFlags & kFlagPreparing) {
    720             //SL_LOGV("SfPlayer::onCheckCache: preparation done.");
    721             mFlags &= ~kFlagPreparing;
    722         }
    723 
    724         mTimeDelta = -1;
    725         if (mFlags & kFlagPlaying) {
    726             (new AMessage(kWhatDecode, id()))->post();
    727         }
    728         return;
    729     }
    730 
    731     msg->post(100000);
    732 }
    733 
    734 void SfPlayer::onNotify(const sp<AMessage> &msg) {
    735     if (NULL == mNotifyClient) {
    736         return;
    737     }
    738     int32_t val;
    739     if (msg->findInt32(EVENT_PREFETCHSTATUSCHANGE, &val)) {
    740         SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_PREFETCHSTATUSCHANGE, val);
    741         mNotifyClient(kEventPrefetchStatusChange, val, mNotifyUser);
    742     }
    743     if (msg->findInt32(EVENT_PREFETCHFILLLEVELUPDATE, &val)) {
    744         SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_PREFETCHFILLLEVELUPDATE, val);
    745         mNotifyClient(kEventPrefetchFillLevelUpdate, val, mNotifyUser);
    746     }
    747     if (msg->findInt32(EVENT_ENDOFSTREAM, &val)) {
    748         SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_ENDOFSTREAM, val);
    749         mNotifyClient(kEventEndOfStream, val, mNotifyUser);
    750     }
    751 
    752     if (msg->findInt32(EVENT_PREPARED, &val)) {
    753         SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_PREPARED, val);
    754         mNotifyClient(kEventPrepared, val, mNotifyUser);
    755     }
    756 
    757     if (msg->findInt32(EVENT_NEW_AUDIOTRACK, &val)) {
    758         SL_LOGV("\tSfPlayer notifying %s", EVENT_NEW_AUDIOTRACK);
    759         mNotifyClient(kEventNewAudioTrack, val, mNotifyUser);
    760     }
    761 }
    762 
    763 SfPlayer::CacheStatus SfPlayer::getCacheRemaining(bool *eos) {
    764     sp<NuCachedSource2> cachedSource =
    765         static_cast<NuCachedSource2 *>(mDataSource.get());
    766 
    767     CacheStatus oldStatus = mCacheStatus;
    768 
    769     size_t dataRemaining = cachedSource->approxDataRemaining(eos);
    770 
    771     CHECK_GE(mBitrate, 0);
    772 
    773     int64_t dataRemainingUs = dataRemaining * 8000000ll / mBitrate;
    774 
    775     //SL_LOGV("SfPlayer::getCacheRemaining: approx %.2f secs remaining (eos=%d)",
    776     //       dataRemainingUs / 1E6, *eos);
    777 
    778     if (*eos) {
    779         // data is buffered up to the end of the stream, it can't get any better than this
    780         mCacheStatus = kStatusHigh;
    781         mCacheFill = 1000;
    782 
    783     } else {
    784         if (mDurationUsec > 0) {
    785             // known duration:
    786 
    787             //   fill level is ratio of how much has been played + how much is
    788             //   cached, divided by total duration
    789             uint32_t currentPositionUsec = getPositionUsec();
    790             mCacheFill = (int16_t) ((1000.0
    791                     * (double)(currentPositionUsec + dataRemainingUs) / mDurationUsec));
    792             //SL_LOGV("cacheFill = %d", mCacheFill);
    793 
    794             //   cache status is evaluated against duration thresholds
    795             if (dataRemainingUs > DURATION_CACHED_HIGH_US) {
    796                 mCacheStatus = kStatusHigh;
    797                 //LOGV("high");
    798             } else if (dataRemainingUs > DURATION_CACHED_MED_US) {
    799                 //LOGV("enough");
    800                 mCacheStatus = kStatusEnough;
    801             } else if (dataRemainingUs < DURATION_CACHED_LOW_US) {
    802                 //LOGV("low");
    803                 mCacheStatus = kStatusLow;
    804             } else {
    805                 mCacheStatus = kStatusIntermediate;
    806             }
    807 
    808         } else {
    809             // unknown duration:
    810 
    811             //   cache status is evaluated against cache amount thresholds
    812             //   (no duration so we don't have the bitrate either, could be derived from format?)
    813             if (dataRemaining > SIZE_CACHED_HIGH_BYTES) {
    814                 mCacheStatus = kStatusHigh;
    815             } else if (dataRemaining > SIZE_CACHED_MED_BYTES) {
    816                 mCacheStatus = kStatusEnough;
    817             } else if (dataRemaining < SIZE_CACHED_LOW_BYTES) {
    818                 mCacheStatus = kStatusLow;
    819             } else {
    820                 mCacheStatus = kStatusIntermediate;
    821             }
    822         }
    823 
    824     }
    825 
    826     if (oldStatus != mCacheStatus) {
    827         notifyStatus();
    828     }
    829 
    830     if (abs(mCacheFill - mLastNotifiedCacheFill) > mCacheFillNotifThreshold) {
    831         notifyCacheFill();
    832     }
    833 
    834     return mCacheStatus;
    835 }
    836 
    837 
    838 /*
    839  * post-condition: mDataLocatorType == kDataLocatorNone
    840  *
    841  */
    842 void SfPlayer::resetDataLocator() {
    843     if (kDataLocatorUri == mDataLocatorType) {
    844         if (NULL != mDataLocator.uri) {
    845             free(mDataLocator.uri);
    846             mDataLocator.uri = NULL;
    847         }
    848     }
    849     mDataLocatorType = kDataLocatorNone;
    850 }
    851 
    852 
    853 void SfPlayer::onMessageReceived(const sp<AMessage> &msg) {
    854     switch (msg->what()) {
    855         case kWhatPrepare:
    856             onPrepare(msg);
    857             break;
    858 
    859         case kWhatDecode:
    860             onDecode();
    861             break;
    862 
    863         case kWhatRender:
    864             onRender(msg);
    865             break;
    866 
    867         case kWhatCheckCache:
    868             onCheckCache(msg);
    869             break;
    870 
    871         case kWhatNotif:
    872             onNotify(msg);
    873             break;
    874 
    875         case kWhatPlay:
    876             onPlay();
    877             break;
    878 
    879         case kWhatPause:
    880             onPause();
    881             break;
    882 
    883         case kWhatSeek:
    884             onSeek(msg);
    885             break;
    886 
    887         case kWhatLoop:
    888             onLoop(msg);
    889             break;
    890 
    891         default:
    892             TRESPASS();
    893     }
    894 }
    895 
    896 }  // namespace android
    897