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
33namespace android {
34
35SfPlayer::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
66SfPlayer::~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
94void SfPlayer::armLooper() {
95    mRenderLooper->registerHandler(this);
96    mRenderLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/,
97            ANDROID_PRIORITY_AUDIO);
98}
99
100
101void SfPlayer::setNotifListener(const notif_client_t cbf, void* notifUser) {
102    mNotifyClient = cbf;
103    mNotifyUser = notifUser;
104}
105
106
107void 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
114void 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
121void 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
129void SfPlayer::notify(const sp<AMessage> &msg, bool async) {
130    if (async) {
131        msg->post();
132    } else {
133        onNotify(msg);
134    }
135}
136
137
138void 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
154void 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
184void SfPlayer::prepare() {
185    //SL_LOGV("SfPlayer::prepare()");
186    sp<AMessage> msg = new AMessage(kWhatPrepare, id());
187    msg->post();
188}
189
190
191void 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
343bool SfPlayer::wantPrefetch() {
344    return (mDataSource->flags() & DataSource::kWantsPrefetching);
345}
346
347
348void 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
361void SfPlayer::play() {
362    SL_LOGV("SfPlayer::play");
363
364    (new AMessage(kWhatPlay, id()))->post();
365    (new AMessage(kWhatDecode, id()))->post();
366}
367
368
369void 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
382void 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
391void 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
399void 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
406uint32_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
420int64_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 */
436void 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 */
454void 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
500void 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
520void 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
533void 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
546void 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
561void 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
674void 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
704void 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
734void 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
763SfPlayer::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 */
842void 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
853void 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