AwesomePlayer.cpp revision 7cf180c9bff69e5cc4a2f4e53b432db45ebbebab
1/*
2 * Copyright (C) 2009 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 LOG_NDEBUG 0
18#define LOG_TAG "AwesomePlayer"
19#include <utils/Log.h>
20
21#include <dlfcn.h>
22
23#include "include/ARTSPController.h"
24#include "include/AwesomePlayer.h"
25#include "include/SoftwareRenderer.h"
26#include "include/NuCachedSource2.h"
27#include "include/ThrottledSource.h"
28#include "include/MPEG2TSExtractor.h"
29
30#include <binder/IPCThreadState.h>
31#include <binder/IServiceManager.h>
32#include <media/IMediaPlayerService.h>
33#include <media/stagefright/foundation/hexdump.h>
34#include <media/stagefright/foundation/ADebug.h>
35#include <media/stagefright/AudioPlayer.h>
36#include <media/stagefright/DataSource.h>
37#include <media/stagefright/FileSource.h>
38#include <media/stagefright/MediaBuffer.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/MediaExtractor.h>
41#include <media/stagefright/MediaSource.h>
42#include <media/stagefright/MetaData.h>
43#include <media/stagefright/OMXCodec.h>
44
45#include <surfaceflinger/Surface.h>
46
47#include <media/stagefright/foundation/ALooper.h>
48#include <media/stagefright/foundation/AMessage.h>
49
50#define USE_SURFACE_ALLOC 1
51#define FRAME_DROP_FREQ 7
52
53namespace android {
54
55static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
56static int64_t kHighWaterMarkUs = 10000000ll;  // 10secs
57static int64_t kHighWaterMarkRTSPUs = 4000000ll;  // 4secs
58static const size_t kLowWaterMarkBytes = 40000;
59static const size_t kHighWaterMarkBytes = 200000;
60
61struct AwesomeEvent : public TimedEventQueue::Event {
62    AwesomeEvent(
63            AwesomePlayer *player,
64            void (AwesomePlayer::*method)())
65        : mPlayer(player),
66          mMethod(method) {
67    }
68
69protected:
70    virtual ~AwesomeEvent() {}
71
72    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
73        (mPlayer->*mMethod)();
74    }
75
76private:
77    AwesomePlayer *mPlayer;
78    void (AwesomePlayer::*mMethod)();
79
80    AwesomeEvent(const AwesomeEvent &);
81    AwesomeEvent &operator=(const AwesomeEvent &);
82};
83
84struct AwesomeLocalRenderer : public AwesomeRenderer {
85    AwesomeLocalRenderer(
86            const sp<Surface> &surface, const sp<MetaData> &meta)
87        : mTarget(new SoftwareRenderer(surface, meta)) {
88    }
89
90    virtual void render(MediaBuffer *buffer) {
91        render((const uint8_t *)buffer->data() + buffer->range_offset(),
92               buffer->range_length());
93    }
94
95    void render(const void *data, size_t size) {
96        mTarget->render(data, size, NULL);
97    }
98
99protected:
100    virtual ~AwesomeLocalRenderer() {
101        delete mTarget;
102        mTarget = NULL;
103    }
104
105private:
106    SoftwareRenderer *mTarget;
107
108    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
109    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
110};
111
112struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
113    AwesomeNativeWindowRenderer(
114            const sp<ANativeWindow> &nativeWindow,
115            int32_t rotationDegrees)
116        : mNativeWindow(nativeWindow) {
117        applyRotation(rotationDegrees);
118    }
119
120    virtual void render(MediaBuffer *buffer) {
121        status_t err = mNativeWindow->queueBuffer(
122                mNativeWindow.get(), buffer->graphicBuffer().get());
123        if (err != 0) {
124            LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
125                    -err);
126            return;
127        }
128
129        sp<MetaData> metaData = buffer->meta_data();
130        metaData->setInt32(kKeyRendered, 1);
131    }
132
133protected:
134    virtual ~AwesomeNativeWindowRenderer() {}
135
136private:
137    sp<ANativeWindow> mNativeWindow;
138
139    void applyRotation(int32_t rotationDegrees) {
140        uint32_t transform;
141        switch (rotationDegrees) {
142            case 0: transform = 0; break;
143            case 90: transform = HAL_TRANSFORM_ROT_90; break;
144            case 180: transform = HAL_TRANSFORM_ROT_180; break;
145            case 270: transform = HAL_TRANSFORM_ROT_270; break;
146            default: transform = 0; break;
147        }
148
149        if (transform) {
150            CHECK_EQ(0, native_window_set_buffers_transform(
151                        mNativeWindow.get(), transform));
152        }
153    }
154
155    AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
156    AwesomeNativeWindowRenderer &operator=(
157            const AwesomeNativeWindowRenderer &);
158};
159
160// To collect the decoder usage
161void addBatteryData(uint32_t params) {
162    sp<IBinder> binder =
163        defaultServiceManager()->getService(String16("media.player"));
164    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
165    CHECK(service.get() != NULL);
166
167    service->addBatteryData(params);
168}
169
170////////////////////////////////////////////////////////////////////////////////
171AwesomePlayer::AwesomePlayer()
172    : mQueueStarted(false),
173      mTimeSource(NULL),
174      mVideoRendererIsPreview(false),
175      mAudioPlayer(NULL),
176      mDisplayWidth(0),
177      mDisplayHeight(0),
178      mFlags(0),
179      mExtractorFlags(0),
180      mVideoBuffer(NULL),
181      mDecryptHandle(NULL) {
182    CHECK_EQ(mClient.connect(), (status_t)OK);
183
184    DataSource::RegisterDefaultSniffers();
185
186    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
187    mVideoEventPending = false;
188    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
189    mStreamDoneEventPending = false;
190    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
191    mBufferingEventPending = false;
192    mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
193    mVideoEventPending = false;
194
195    mCheckAudioStatusEvent = new AwesomeEvent(
196            this, &AwesomePlayer::onCheckAudioStatus);
197
198    mAudioStatusEventPending = false;
199
200    reset();
201}
202
203AwesomePlayer::~AwesomePlayer() {
204    if (mQueueStarted) {
205        mQueue.stop();
206    }
207
208    reset();
209
210    mClient.disconnect();
211}
212
213void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
214    mQueue.cancelEvent(mVideoEvent->eventID());
215    mVideoEventPending = false;
216    mQueue.cancelEvent(mStreamDoneEvent->eventID());
217    mStreamDoneEventPending = false;
218    mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
219    mAudioStatusEventPending = false;
220    mQueue.cancelEvent(mVideoLagEvent->eventID());
221    mVideoLagEventPending = false;
222
223    if (!keepBufferingGoing) {
224        mQueue.cancelEvent(mBufferingEvent->eventID());
225        mBufferingEventPending = false;
226    }
227}
228
229void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
230    Mutex::Autolock autoLock(mLock);
231    mListener = listener;
232}
233
234status_t AwesomePlayer::setDataSource(
235        const char *uri, const KeyedVector<String8, String8> *headers) {
236    Mutex::Autolock autoLock(mLock);
237    return setDataSource_l(uri, headers);
238}
239
240status_t AwesomePlayer::setDataSource_l(
241        const char *uri, const KeyedVector<String8, String8> *headers) {
242    reset_l();
243
244    mUri = uri;
245
246    if (headers) {
247        mUriHeaders = *headers;
248    }
249
250    // The actual work will be done during preparation in the call to
251    // ::finishSetDataSource_l to avoid blocking the calling thread in
252    // setDataSource for any significant time.
253
254    return OK;
255}
256
257status_t AwesomePlayer::setDataSource(
258        int fd, int64_t offset, int64_t length) {
259    Mutex::Autolock autoLock(mLock);
260
261    reset_l();
262
263    sp<DataSource> dataSource = new FileSource(fd, offset, length);
264
265    status_t err = dataSource->initCheck();
266
267    if (err != OK) {
268        return err;
269    }
270
271    mFileSource = dataSource;
272
273    return setDataSource_l(dataSource);
274}
275
276status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
277    return INVALID_OPERATION;
278}
279
280status_t AwesomePlayer::setDataSource_l(
281        const sp<DataSource> &dataSource) {
282    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
283
284    if (extractor == NULL) {
285        return UNKNOWN_ERROR;
286    }
287
288    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
289    if (mDecryptHandle != NULL) {
290        CHECK(mDrmManagerClient);
291        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
292            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
293        }
294    }
295
296    return setDataSource_l(extractor);
297}
298
299status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
300    // Attempt to approximate overall stream bitrate by summing all
301    // tracks' individual bitrates, if not all of them advertise bitrate,
302    // we have to fail.
303
304    int64_t totalBitRate = 0;
305
306    for (size_t i = 0; i < extractor->countTracks(); ++i) {
307        sp<MetaData> meta = extractor->getTrackMetaData(i);
308
309        int32_t bitrate;
310        if (!meta->findInt32(kKeyBitRate, &bitrate)) {
311            totalBitRate = -1;
312            break;
313        }
314
315        totalBitRate += bitrate;
316    }
317
318    mBitrate = totalBitRate;
319
320    LOGV("mBitrate = %lld bits/sec", mBitrate);
321
322    bool haveAudio = false;
323    bool haveVideo = false;
324    for (size_t i = 0; i < extractor->countTracks(); ++i) {
325        sp<MetaData> meta = extractor->getTrackMetaData(i);
326
327        const char *mime;
328        CHECK(meta->findCString(kKeyMIMEType, &mime));
329
330        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
331            setVideoSource(extractor->getTrack(i));
332            haveVideo = true;
333
334            // Set the presentation/display size
335            int32_t displayWidth, displayHeight;
336            bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
337            if (success) {
338                success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
339            }
340            if (success) {
341                mDisplayWidth = displayWidth;
342                mDisplayHeight = displayHeight;
343            }
344
345        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
346            setAudioSource(extractor->getTrack(i));
347            haveAudio = true;
348
349            if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
350                // Only do this for vorbis audio, none of the other audio
351                // formats even support this ringtone specific hack and
352                // retrieving the metadata on some extractors may turn out
353                // to be very expensive.
354                sp<MetaData> fileMeta = extractor->getMetaData();
355                int32_t loop;
356                if (fileMeta != NULL
357                        && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
358                    mFlags |= AUTO_LOOPING;
359                }
360            }
361        }
362
363        if (haveAudio && haveVideo) {
364            break;
365        }
366    }
367
368    if (!haveAudio && !haveVideo) {
369        return UNKNOWN_ERROR;
370    }
371
372    mExtractorFlags = extractor->flags();
373
374    return OK;
375}
376
377void AwesomePlayer::reset() {
378    Mutex::Autolock autoLock(mLock);
379    reset_l();
380}
381
382void AwesomePlayer::reset_l() {
383    mDisplayWidth = 0;
384    mDisplayHeight = 0;
385
386    if (mDecryptHandle != NULL) {
387            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
388                    Playback::STOP, 0);
389            mDecryptHandle = NULL;
390            mDrmManagerClient = NULL;
391    }
392
393    if (mFlags & PLAYING) {
394        uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
395        if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
396            params |= IMediaPlayerService::kBatteryDataTrackAudio;
397        }
398        if (mVideoSource != NULL) {
399            params |= IMediaPlayerService::kBatteryDataTrackVideo;
400        }
401        addBatteryData(params);
402    }
403
404    if (mFlags & PREPARING) {
405        mFlags |= PREPARE_CANCELLED;
406        if (mConnectingDataSource != NULL) {
407            LOGI("interrupting the connection process");
408            mConnectingDataSource->disconnect();
409        } else if (mConnectingRTSPController != NULL) {
410            LOGI("interrupting the connection process");
411            mConnectingRTSPController->disconnect();
412        }
413
414        if (mFlags & PREPARING_CONNECTED) {
415            // We are basically done preparing, we're just buffering
416            // enough data to start playback, we can safely interrupt that.
417            finishAsyncPrepare_l();
418        }
419    }
420
421    while (mFlags & PREPARING) {
422        mPreparedCondition.wait(mLock);
423    }
424
425    cancelPlayerEvents();
426
427    mCachedSource.clear();
428    mAudioTrack.clear();
429    mVideoTrack.clear();
430
431    // Shutdown audio first, so that the respone to the reset request
432    // appears to happen instantaneously as far as the user is concerned
433    // If we did this later, audio would continue playing while we
434    // shutdown the video-related resources and the player appear to
435    // not be as responsive to a reset request.
436    if (mAudioPlayer == NULL && mAudioSource != NULL) {
437        // If we had an audio player, it would have effectively
438        // taken possession of the audio source and stopped it when
439        // _it_ is stopped. Otherwise this is still our responsibility.
440        mAudioSource->stop();
441    }
442    mAudioSource.clear();
443
444    mTimeSource = NULL;
445
446    delete mAudioPlayer;
447    mAudioPlayer = NULL;
448
449    mVideoRenderer.clear();
450
451    if (mVideoBuffer) {
452        mVideoBuffer->release();
453        mVideoBuffer = NULL;
454    }
455
456    if (mRTSPController != NULL) {
457        mRTSPController->disconnect();
458        mRTSPController.clear();
459    }
460
461    if (mVideoSource != NULL) {
462        mVideoSource->stop();
463
464        // The following hack is necessary to ensure that the OMX
465        // component is completely released by the time we may try
466        // to instantiate it again.
467        wp<MediaSource> tmp = mVideoSource;
468        mVideoSource.clear();
469        while (tmp.promote() != NULL) {
470            usleep(1000);
471        }
472        IPCThreadState::self()->flushCommands();
473    }
474
475    mDurationUs = -1;
476    mFlags = 0;
477    mExtractorFlags = 0;
478    mTimeSourceDeltaUs = 0;
479    mVideoTimeUs = 0;
480
481    mSeeking = false;
482    mSeekNotificationSent = false;
483    mSeekTimeUs = 0;
484
485    mUri.setTo("");
486    mUriHeaders.clear();
487
488    mFileSource.clear();
489
490    mBitrate = -1;
491}
492
493void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
494    if (mListener != NULL) {
495        sp<MediaPlayerBase> listener = mListener.promote();
496
497        if (listener != NULL) {
498            listener->sendEvent(msg, ext1, ext2);
499        }
500    }
501}
502
503bool AwesomePlayer::getBitrate(int64_t *bitrate) {
504    off64_t size;
505    if (mDurationUs >= 0 && mCachedSource != NULL
506            && mCachedSource->getSize(&size) == OK) {
507        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
508        return true;
509    }
510
511    if (mBitrate >= 0) {
512        *bitrate = mBitrate;
513        return true;
514    }
515
516    *bitrate = 0;
517
518    return false;
519}
520
521// Returns true iff cached duration is available/applicable.
522bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
523    int64_t bitrate;
524
525    if (mRTSPController != NULL) {
526        *durationUs = mRTSPController->getQueueDurationUs(eos);
527        return true;
528    } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
529        status_t finalStatus;
530        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
531        *durationUs = cachedDataRemaining * 8000000ll / bitrate;
532        *eos = (finalStatus != OK);
533        return true;
534    }
535
536    return false;
537}
538
539void AwesomePlayer::ensureCacheIsFetching_l() {
540    if (mCachedSource != NULL) {
541        mCachedSource->resumeFetchingIfNecessary();
542    }
543}
544
545void AwesomePlayer::onVideoLagUpdate() {
546    Mutex::Autolock autoLock(mLock);
547    if (!mVideoLagEventPending) {
548        return;
549    }
550    mVideoLagEventPending = false;
551
552    int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
553    int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
554
555    if (videoLateByUs > 300000ll) {
556        LOGV("video late by %lld ms.", videoLateByUs / 1000ll);
557
558        notifyListener_l(
559                MEDIA_INFO,
560                MEDIA_INFO_VIDEO_TRACK_LAGGING,
561                videoLateByUs / 1000ll);
562    }
563
564    postVideoLagEvent_l();
565}
566
567void AwesomePlayer::onBufferingUpdate() {
568    Mutex::Autolock autoLock(mLock);
569    if (!mBufferingEventPending) {
570        return;
571    }
572    mBufferingEventPending = false;
573
574    if (mCachedSource != NULL) {
575        status_t finalStatus;
576        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
577        bool eos = (finalStatus != OK);
578
579        if (eos) {
580            if (finalStatus == ERROR_END_OF_STREAM) {
581                notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
582            }
583            if (mFlags & PREPARING) {
584                LOGV("cache has reached EOS, prepare is done.");
585                finishAsyncPrepare_l();
586            }
587        } else {
588            int64_t bitrate;
589            if (getBitrate(&bitrate)) {
590                size_t cachedSize = mCachedSource->cachedSize();
591                int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
592
593                int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
594                if (percentage > 100) {
595                    percentage = 100;
596                }
597
598                notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
599            } else {
600                // We don't know the bitrate of the stream, use absolute size
601                // limits to maintain the cache.
602
603                if ((mFlags & PLAYING) && !eos
604                        && (cachedDataRemaining < kLowWaterMarkBytes)) {
605                    LOGI("cache is running low (< %d) , pausing.",
606                         kLowWaterMarkBytes);
607                    mFlags |= CACHE_UNDERRUN;
608                    pause_l();
609                    ensureCacheIsFetching_l();
610                    notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
611                } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
612                    if (mFlags & CACHE_UNDERRUN) {
613                        LOGI("cache has filled up (> %d), resuming.",
614                             kHighWaterMarkBytes);
615                        mFlags &= ~CACHE_UNDERRUN;
616                        play_l();
617                        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
618                    } else if (mFlags & PREPARING) {
619                        LOGV("cache has filled up (> %d), prepare is done",
620                             kHighWaterMarkBytes);
621                        finishAsyncPrepare_l();
622                    }
623                }
624            }
625        }
626    }
627
628    int64_t cachedDurationUs;
629    bool eos;
630    if (getCachedDuration_l(&cachedDurationUs, &eos)) {
631        LOGV("cachedDurationUs = %.2f secs, eos=%d",
632             cachedDurationUs / 1E6, eos);
633
634        int64_t highWaterMarkUs =
635            (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
636
637        if ((mFlags & PLAYING) && !eos
638                && (cachedDurationUs < kLowWaterMarkUs)) {
639            LOGI("cache is running low (%.2f secs) , pausing.",
640                 cachedDurationUs / 1E6);
641            mFlags |= CACHE_UNDERRUN;
642            pause_l();
643            ensureCacheIsFetching_l();
644            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
645        } else if (eos || cachedDurationUs > highWaterMarkUs) {
646            if (mFlags & CACHE_UNDERRUN) {
647                LOGI("cache has filled up (%.2f secs), resuming.",
648                     cachedDurationUs / 1E6);
649                mFlags &= ~CACHE_UNDERRUN;
650                play_l();
651                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
652            } else if (mFlags & PREPARING) {
653                LOGV("cache has filled up (%.2f secs), prepare is done",
654                     cachedDurationUs / 1E6);
655                finishAsyncPrepare_l();
656            }
657        }
658    }
659
660    postBufferingEvent_l();
661}
662
663void AwesomePlayer::onStreamDone() {
664    // Posted whenever any stream finishes playing.
665
666    Mutex::Autolock autoLock(mLock);
667    if (!mStreamDoneEventPending) {
668        return;
669    }
670    mStreamDoneEventPending = false;
671
672    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
673        LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
674
675        notifyListener_l(
676                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
677
678        pause_l(true /* at eos */);
679
680        mFlags |= AT_EOS;
681        return;
682    }
683
684    const bool allDone =
685        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
686            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
687
688    if (!allDone) {
689        return;
690    }
691
692    if (mFlags & (LOOPING | AUTO_LOOPING)) {
693        seekTo_l(0);
694
695        if (mVideoSource != NULL) {
696            postVideoEvent_l();
697        }
698    } else {
699        LOGV("MEDIA_PLAYBACK_COMPLETE");
700        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
701
702        pause_l(true /* at eos */);
703
704        mFlags |= AT_EOS;
705    }
706}
707
708status_t AwesomePlayer::play() {
709    Mutex::Autolock autoLock(mLock);
710
711    mFlags &= ~CACHE_UNDERRUN;
712
713    return play_l();
714}
715
716status_t AwesomePlayer::play_l() {
717    mFlags &= ~SEEK_PREVIEW;
718
719    if (mFlags & PLAYING) {
720        return OK;
721    }
722
723    if (!(mFlags & PREPARED)) {
724        status_t err = prepare_l();
725
726        if (err != OK) {
727            return err;
728        }
729    }
730
731    mFlags |= PLAYING;
732    mFlags |= FIRST_FRAME;
733
734    bool deferredAudioSeek = false;
735
736    if (mDecryptHandle != NULL) {
737        int64_t position;
738        getPosition(&position);
739        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
740                Playback::START, position / 1000);
741    }
742
743    if (mAudioSource != NULL) {
744        if (mAudioPlayer == NULL) {
745            if (mAudioSink != NULL) {
746                mAudioPlayer = new AudioPlayer(mAudioSink, this);
747                mAudioPlayer->setSource(mAudioSource);
748
749                mTimeSource = mAudioPlayer;
750
751                deferredAudioSeek = true;
752
753                mWatchForAudioSeekComplete = false;
754                mWatchForAudioEOS = true;
755            }
756        }
757
758        CHECK(!(mFlags & AUDIO_RUNNING));
759
760        if (mVideoSource == NULL) {
761            status_t err = startAudioPlayer_l();
762
763            if (err != OK) {
764                delete mAudioPlayer;
765                mAudioPlayer = NULL;
766
767                mFlags &= ~(PLAYING | FIRST_FRAME);
768
769                if (mDecryptHandle != NULL) {
770                    mDrmManagerClient->setPlaybackStatus(
771                            mDecryptHandle, Playback::STOP, 0);
772                }
773
774                return err;
775            }
776        }
777    }
778
779    if (mTimeSource == NULL && mAudioPlayer == NULL) {
780        mTimeSource = &mSystemTimeSource;
781    }
782
783    if (mVideoSource != NULL) {
784        // Kick off video playback
785        postVideoEvent_l();
786
787        if (mAudioSource != NULL && mVideoSource != NULL) {
788            postVideoLagEvent_l();
789        }
790    }
791
792    if (deferredAudioSeek) {
793        // If there was a seek request while we were paused
794        // and we're just starting up again, honor the request now.
795        seekAudioIfNecessary_l();
796    }
797
798    if (mFlags & AT_EOS) {
799        // Legacy behaviour, if a stream finishes playing and then
800        // is started again, we play from the start...
801        seekTo_l(0);
802    }
803
804    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
805        | IMediaPlayerService::kBatteryDataTrackDecoder;
806    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
807        params |= IMediaPlayerService::kBatteryDataTrackAudio;
808    }
809    if (mVideoSource != NULL) {
810        params |= IMediaPlayerService::kBatteryDataTrackVideo;
811    }
812    addBatteryData(params);
813
814    return OK;
815}
816
817status_t AwesomePlayer::startAudioPlayer_l() {
818    CHECK(!(mFlags & AUDIO_RUNNING));
819
820    if (mAudioSource == NULL || mAudioPlayer == NULL) {
821        return OK;
822    }
823
824    if (!(mFlags & AUDIOPLAYER_STARTED)) {
825        mFlags |= AUDIOPLAYER_STARTED;
826
827        // We've already started the MediaSource in order to enable
828        // the prefetcher to read its data.
829        status_t err = mAudioPlayer->start(
830                true /* sourceAlreadyStarted */);
831
832        if (err != OK) {
833            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
834            return err;
835        }
836    } else {
837        mAudioPlayer->resume();
838    }
839
840    mFlags |= AUDIO_RUNNING;
841
842    mWatchForAudioEOS = true;
843
844    return OK;
845}
846
847void AwesomePlayer::notifyVideoSize_l() {
848    sp<MetaData> meta = mVideoSource->getFormat();
849
850    int32_t cropLeft, cropTop, cropRight, cropBottom;
851    if (!meta->findRect(
852                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
853        int32_t width, height;
854        CHECK(meta->findInt32(kKeyWidth, &width));
855        CHECK(meta->findInt32(kKeyHeight, &height));
856
857        cropLeft = cropTop = 0;
858        cropRight = width - 1;
859        cropBottom = height - 1;
860
861        LOGV("got dimensions only %d x %d", width, height);
862    } else {
863        LOGV("got crop rect %d, %d, %d, %d",
864             cropLeft, cropTop, cropRight, cropBottom);
865    }
866
867    int32_t usableWidth = cropRight - cropLeft + 1;
868    int32_t usableHeight = cropBottom - cropTop + 1;
869    if (mDisplayWidth != 0) {
870        usableWidth = mDisplayWidth;
871    }
872    if (mDisplayHeight != 0) {
873        usableHeight = mDisplayHeight;
874    }
875
876    int32_t rotationDegrees;
877    if (!mVideoTrack->getFormat()->findInt32(
878                kKeyRotation, &rotationDegrees)) {
879        rotationDegrees = 0;
880    }
881
882    if (rotationDegrees == 90 || rotationDegrees == 270) {
883        notifyListener_l(
884                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
885    } else {
886        notifyListener_l(
887                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
888    }
889}
890
891void AwesomePlayer::initRenderer_l() {
892    if (mSurface == NULL) {
893        return;
894    }
895
896    sp<MetaData> meta = mVideoSource->getFormat();
897
898    int32_t format;
899    const char *component;
900    int32_t decodedWidth, decodedHeight;
901    CHECK(meta->findInt32(kKeyColorFormat, &format));
902    CHECK(meta->findCString(kKeyDecoderComponent, &component));
903    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
904    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
905
906    int32_t rotationDegrees;
907    if (!mVideoTrack->getFormat()->findInt32(
908                kKeyRotation, &rotationDegrees)) {
909        rotationDegrees = 0;
910    }
911
912    mVideoRenderer.clear();
913
914    // Must ensure that mVideoRenderer's destructor is actually executed
915    // before creating a new one.
916    IPCThreadState::self()->flushCommands();
917
918    if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
919        // Hardware decoders avoid the CPU color conversion by decoding
920        // directly to ANativeBuffers, so we must use a renderer that
921        // just pushes those buffers to the ANativeWindow.
922        mVideoRenderer =
923            new AwesomeNativeWindowRenderer(mSurface, rotationDegrees);
924    } else {
925        // Other decoders are instantiated locally and as a consequence
926        // allocate their buffers in local address space.  This renderer
927        // then performs a color conversion and copy to get the data
928        // into the ANativeBuffer.
929        mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta);
930    }
931}
932
933status_t AwesomePlayer::pause() {
934    Mutex::Autolock autoLock(mLock);
935
936    mFlags &= ~CACHE_UNDERRUN;
937
938    return pause_l();
939}
940
941status_t AwesomePlayer::pause_l(bool at_eos) {
942    if (!(mFlags & PLAYING)) {
943        return OK;
944    }
945
946    cancelPlayerEvents(true /* keepBufferingGoing */);
947
948    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
949        if (at_eos) {
950            // If we played the audio stream to completion we
951            // want to make sure that all samples remaining in the audio
952            // track's queue are played out.
953            mAudioPlayer->pause(true /* playPendingSamples */);
954        } else {
955            mAudioPlayer->pause();
956        }
957
958        mFlags &= ~AUDIO_RUNNING;
959    }
960
961    mFlags &= ~PLAYING;
962
963    if (mDecryptHandle != NULL) {
964        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
965                Playback::PAUSE, 0);
966    }
967
968    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
969    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
970        params |= IMediaPlayerService::kBatteryDataTrackAudio;
971    }
972    if (mVideoSource != NULL) {
973        params |= IMediaPlayerService::kBatteryDataTrackVideo;
974    }
975
976    addBatteryData(params);
977
978    return OK;
979}
980
981bool AwesomePlayer::isPlaying() const {
982    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
983}
984
985void AwesomePlayer::setSurface(const sp<Surface> &surface) {
986    Mutex::Autolock autoLock(mLock);
987
988    mSurface = surface;
989}
990
991void AwesomePlayer::setAudioSink(
992        const sp<MediaPlayerBase::AudioSink> &audioSink) {
993    Mutex::Autolock autoLock(mLock);
994
995    mAudioSink = audioSink;
996}
997
998status_t AwesomePlayer::setLooping(bool shouldLoop) {
999    Mutex::Autolock autoLock(mLock);
1000
1001    mFlags = mFlags & ~LOOPING;
1002
1003    if (shouldLoop) {
1004        mFlags |= LOOPING;
1005    }
1006
1007    return OK;
1008}
1009
1010status_t AwesomePlayer::getDuration(int64_t *durationUs) {
1011    Mutex::Autolock autoLock(mMiscStateLock);
1012
1013    if (mDurationUs < 0) {
1014        return UNKNOWN_ERROR;
1015    }
1016
1017    *durationUs = mDurationUs;
1018
1019    return OK;
1020}
1021
1022status_t AwesomePlayer::getPosition(int64_t *positionUs) {
1023    if (mRTSPController != NULL) {
1024        *positionUs = mRTSPController->getNormalPlayTimeUs();
1025    }
1026    else if (mSeeking) {
1027        *positionUs = mSeekTimeUs;
1028    } else if (mVideoSource != NULL) {
1029        Mutex::Autolock autoLock(mMiscStateLock);
1030        *positionUs = mVideoTimeUs;
1031    } else if (mAudioPlayer != NULL) {
1032        *positionUs = mAudioPlayer->getMediaTimeUs();
1033    } else {
1034        *positionUs = 0;
1035    }
1036
1037    return OK;
1038}
1039
1040status_t AwesomePlayer::seekTo(int64_t timeUs) {
1041    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
1042        Mutex::Autolock autoLock(mLock);
1043        return seekTo_l(timeUs);
1044    }
1045
1046    return OK;
1047}
1048
1049// static
1050void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1051    static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1052}
1053
1054void AwesomePlayer::onRTSPSeekDone() {
1055    notifyListener_l(MEDIA_SEEK_COMPLETE);
1056    mSeekNotificationSent = true;
1057}
1058
1059status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
1060    if (mRTSPController != NULL) {
1061        mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
1062        return OK;
1063    }
1064
1065    if (mFlags & CACHE_UNDERRUN) {
1066        mFlags &= ~CACHE_UNDERRUN;
1067        play_l();
1068    }
1069
1070    mSeeking = true;
1071    mSeekNotificationSent = false;
1072    mSeekTimeUs = timeUs;
1073    mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1074
1075    seekAudioIfNecessary_l();
1076
1077    if (!(mFlags & PLAYING)) {
1078        LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1079             " immediately.");
1080
1081        notifyListener_l(MEDIA_SEEK_COMPLETE);
1082        mSeekNotificationSent = true;
1083
1084        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1085            mFlags |= SEEK_PREVIEW;
1086            postVideoEvent_l();
1087        }
1088    }
1089
1090    return OK;
1091}
1092
1093void AwesomePlayer::seekAudioIfNecessary_l() {
1094    if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
1095        mAudioPlayer->seekTo(mSeekTimeUs);
1096
1097        mWatchForAudioSeekComplete = true;
1098        mWatchForAudioEOS = true;
1099        mSeekNotificationSent = false;
1100
1101        if (mDecryptHandle != NULL) {
1102            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1103                    Playback::PAUSE, 0);
1104            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1105                    Playback::START, mSeekTimeUs / 1000);
1106        }
1107    }
1108}
1109
1110void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1111    CHECK(source != NULL);
1112
1113    mAudioTrack = source;
1114}
1115
1116status_t AwesomePlayer::initAudioDecoder() {
1117    sp<MetaData> meta = mAudioTrack->getFormat();
1118
1119    const char *mime;
1120    CHECK(meta->findCString(kKeyMIMEType, &mime));
1121
1122    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1123        mAudioSource = mAudioTrack;
1124    } else {
1125        mAudioSource = OMXCodec::Create(
1126                mClient.interface(), mAudioTrack->getFormat(),
1127                false, // createEncoder
1128                mAudioTrack);
1129    }
1130
1131    if (mAudioSource != NULL) {
1132        int64_t durationUs;
1133        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1134            Mutex::Autolock autoLock(mMiscStateLock);
1135            if (mDurationUs < 0 || durationUs > mDurationUs) {
1136                mDurationUs = durationUs;
1137            }
1138        }
1139
1140        status_t err = mAudioSource->start();
1141
1142        if (err != OK) {
1143            mAudioSource.clear();
1144            return err;
1145        }
1146    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1147        // For legacy reasons we're simply going to ignore the absence
1148        // of an audio decoder for QCELP instead of aborting playback
1149        // altogether.
1150        return OK;
1151    }
1152
1153    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1154}
1155
1156void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1157    CHECK(source != NULL);
1158
1159    mVideoTrack = source;
1160}
1161
1162status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1163    mVideoSource = OMXCodec::Create(
1164            mClient.interface(), mVideoTrack->getFormat(),
1165            false, // createEncoder
1166            mVideoTrack,
1167            NULL, flags, USE_SURFACE_ALLOC ? mSurface : NULL);
1168
1169    if (mVideoSource != NULL) {
1170        int64_t durationUs;
1171        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1172            Mutex::Autolock autoLock(mMiscStateLock);
1173            if (mDurationUs < 0 || durationUs > mDurationUs) {
1174                mDurationUs = durationUs;
1175            }
1176        }
1177
1178        status_t err = mVideoSource->start();
1179
1180        if (err != OK) {
1181            mVideoSource.clear();
1182            return err;
1183        }
1184    }
1185
1186    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1187}
1188
1189void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1190    if (!mSeeking || (mFlags & SEEK_PREVIEW)) {
1191        return;
1192    }
1193
1194    if (mAudioPlayer != NULL) {
1195        LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1196
1197        // If we don't have a video time, seek audio to the originally
1198        // requested seek time instead.
1199
1200        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1201        mWatchForAudioSeekComplete = true;
1202    } else if (!mSeekNotificationSent) {
1203        // If we're playing video only, report seek complete now,
1204        // otherwise audio player will notify us later.
1205        notifyListener_l(MEDIA_SEEK_COMPLETE);
1206    }
1207
1208    mFlags |= FIRST_FRAME;
1209    mSeeking = false;
1210    mSeekNotificationSent = false;
1211
1212    if (mDecryptHandle != NULL) {
1213        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1214                Playback::PAUSE, 0);
1215        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1216                Playback::START, videoTimeUs / 1000);
1217    }
1218}
1219
1220void AwesomePlayer::onVideoEvent() {
1221    Mutex::Autolock autoLock(mLock);
1222    if (!mVideoEventPending) {
1223        // The event has been cancelled in reset_l() but had already
1224        // been scheduled for execution at that time.
1225        return;
1226    }
1227    mVideoEventPending = false;
1228
1229    if (mSeeking) {
1230        if (mVideoBuffer) {
1231            mVideoBuffer->release();
1232            mVideoBuffer = NULL;
1233        }
1234
1235        if (mCachedSource != NULL && mAudioSource != NULL
1236                && !(mFlags & SEEK_PREVIEW)) {
1237            // We're going to seek the video source first, followed by
1238            // the audio source.
1239            // In order to avoid jumps in the DataSource offset caused by
1240            // the audio codec prefetching data from the old locations
1241            // while the video codec is already reading data from the new
1242            // locations, we'll "pause" the audio source, causing it to
1243            // stop reading input data until a subsequent seek.
1244
1245            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1246                mAudioPlayer->pause();
1247
1248                mFlags &= ~AUDIO_RUNNING;
1249            }
1250            mAudioSource->pause();
1251        }
1252    }
1253
1254    if (!mVideoBuffer) {
1255        MediaSource::ReadOptions options;
1256        if (mSeeking) {
1257            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1258
1259            options.setSeekTo(
1260                    mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1261        }
1262        for (;;) {
1263            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1264            options.clearSeekTo();
1265
1266            if (err != OK) {
1267                CHECK(mVideoBuffer == NULL);
1268
1269                if (err == INFO_FORMAT_CHANGED) {
1270                    LOGV("VideoSource signalled format change.");
1271
1272                    notifyVideoSize_l();
1273
1274                    if (mVideoRenderer != NULL) {
1275                        mVideoRendererIsPreview = false;
1276                        initRenderer_l();
1277                    }
1278                    continue;
1279                }
1280
1281                // So video playback is complete, but we may still have
1282                // a seek request pending that needs to be applied
1283                // to the audio track.
1284                if (mSeeking) {
1285                    LOGV("video stream ended while seeking!");
1286                }
1287                finishSeekIfNecessary(-1);
1288
1289                mFlags |= VIDEO_AT_EOS;
1290                postStreamDoneEvent_l(err);
1291                return;
1292            }
1293
1294            if (mVideoBuffer->range_length() == 0) {
1295                // Some decoders, notably the PV AVC software decoder
1296                // return spurious empty buffers that we just want to ignore.
1297
1298                mVideoBuffer->release();
1299                mVideoBuffer = NULL;
1300                continue;
1301            }
1302
1303            break;
1304        }
1305    }
1306
1307    int64_t timeUs;
1308    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1309
1310    {
1311        Mutex::Autolock autoLock(mMiscStateLock);
1312        mVideoTimeUs = timeUs;
1313    }
1314
1315    bool wasSeeking = mSeeking;
1316    finishSeekIfNecessary(timeUs);
1317
1318    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1319        status_t err = startAudioPlayer_l();
1320        if (err != OK) {
1321            LOGE("Startung the audio player failed w/ err %d", err);
1322            return;
1323        }
1324    }
1325
1326    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1327
1328    if (mFlags & FIRST_FRAME) {
1329        mFlags &= ~FIRST_FRAME;
1330        mSinceLastDropped = 0;
1331        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1332    }
1333
1334    int64_t realTimeUs, mediaTimeUs;
1335    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1336        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1337        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1338    }
1339
1340    if (!wasSeeking) {
1341        // Let's display the first frame after seeking right away.
1342
1343        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1344
1345        int64_t latenessUs = nowUs - timeUs;
1346
1347        if (latenessUs > 40000) {
1348            // We're more than 40ms late.
1349            LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
1350            if ( mSinceLastDropped > FRAME_DROP_FREQ)
1351            {
1352                LOGV("we're late by %lld us (%.2f secs) dropping one after %d frames", latenessUs, latenessUs / 1E6, mSinceLastDropped);
1353                mSinceLastDropped = 0;
1354                mVideoBuffer->release();
1355                mVideoBuffer = NULL;
1356
1357                postVideoEvent_l();
1358                return;
1359            }
1360        }
1361
1362        if (latenessUs < -10000) {
1363            // We're more than 10ms early.
1364
1365            postVideoEvent_l(10000);
1366            return;
1367        }
1368    }
1369
1370    if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1371        mVideoRendererIsPreview = false;
1372
1373        initRenderer_l();
1374    }
1375
1376    if (mVideoRenderer != NULL) {
1377        mSinceLastDropped++;
1378        mVideoRenderer->render(mVideoBuffer);
1379    }
1380
1381    mVideoBuffer->release();
1382    mVideoBuffer = NULL;
1383
1384    if (wasSeeking && (mFlags & SEEK_PREVIEW)) {
1385        mFlags &= ~SEEK_PREVIEW;
1386        return;
1387    }
1388
1389    postVideoEvent_l();
1390}
1391
1392void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1393    if (mVideoEventPending) {
1394        return;
1395    }
1396
1397    mVideoEventPending = true;
1398    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1399}
1400
1401void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1402    if (mStreamDoneEventPending) {
1403        return;
1404    }
1405    mStreamDoneEventPending = true;
1406
1407    mStreamDoneStatus = status;
1408    mQueue.postEvent(mStreamDoneEvent);
1409}
1410
1411void AwesomePlayer::postBufferingEvent_l() {
1412    if (mBufferingEventPending) {
1413        return;
1414    }
1415    mBufferingEventPending = true;
1416    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1417}
1418
1419void AwesomePlayer::postVideoLagEvent_l() {
1420    if (mVideoLagEventPending) {
1421        return;
1422    }
1423    mVideoLagEventPending = true;
1424    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1425}
1426
1427void AwesomePlayer::postCheckAudioStatusEvent_l() {
1428    if (mAudioStatusEventPending) {
1429        return;
1430    }
1431    mAudioStatusEventPending = true;
1432    mQueue.postEvent(mCheckAudioStatusEvent);
1433}
1434
1435void AwesomePlayer::onCheckAudioStatus() {
1436    Mutex::Autolock autoLock(mLock);
1437    if (!mAudioStatusEventPending) {
1438        // Event was dispatched and while we were blocking on the mutex,
1439        // has already been cancelled.
1440        return;
1441    }
1442
1443    mAudioStatusEventPending = false;
1444
1445    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1446        mWatchForAudioSeekComplete = false;
1447
1448        if (!mSeekNotificationSent) {
1449            notifyListener_l(MEDIA_SEEK_COMPLETE);
1450            mSeekNotificationSent = true;
1451        }
1452
1453        mSeeking = false;
1454    }
1455
1456    status_t finalStatus;
1457    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1458        mWatchForAudioEOS = false;
1459        mFlags |= AUDIO_AT_EOS;
1460        mFlags |= FIRST_FRAME;
1461        postStreamDoneEvent_l(finalStatus);
1462    }
1463}
1464
1465status_t AwesomePlayer::prepare() {
1466    Mutex::Autolock autoLock(mLock);
1467    return prepare_l();
1468}
1469
1470status_t AwesomePlayer::prepare_l() {
1471    if (mFlags & PREPARED) {
1472        return OK;
1473    }
1474
1475    if (mFlags & PREPARING) {
1476        return UNKNOWN_ERROR;
1477    }
1478
1479    mIsAsyncPrepare = false;
1480    status_t err = prepareAsync_l();
1481
1482    if (err != OK) {
1483        return err;
1484    }
1485
1486    while (mFlags & PREPARING) {
1487        mPreparedCondition.wait(mLock);
1488    }
1489
1490    return mPrepareResult;
1491}
1492
1493status_t AwesomePlayer::prepareAsync() {
1494    Mutex::Autolock autoLock(mLock);
1495
1496    if (mFlags & PREPARING) {
1497        return UNKNOWN_ERROR;  // async prepare already pending
1498    }
1499
1500    mIsAsyncPrepare = true;
1501    return prepareAsync_l();
1502}
1503
1504status_t AwesomePlayer::prepareAsync_l() {
1505    if (mFlags & PREPARING) {
1506        return UNKNOWN_ERROR;  // async prepare already pending
1507    }
1508
1509    if (!mQueueStarted) {
1510        mQueue.start();
1511        mQueueStarted = true;
1512    }
1513
1514    mFlags |= PREPARING;
1515    mAsyncPrepareEvent = new AwesomeEvent(
1516            this, &AwesomePlayer::onPrepareAsyncEvent);
1517
1518    mQueue.postEvent(mAsyncPrepareEvent);
1519
1520    return OK;
1521}
1522
1523status_t AwesomePlayer::finishSetDataSource_l() {
1524    sp<DataSource> dataSource;
1525
1526    if (!strncasecmp("http://", mUri.string(), 7)
1527            || !strncasecmp("https://", mUri.string(), 8)) {
1528        mConnectingDataSource = new NuHTTPDataSource;
1529
1530        mLock.unlock();
1531        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
1532        mLock.lock();
1533
1534        if (err != OK) {
1535            mConnectingDataSource.clear();
1536
1537            LOGI("mConnectingDataSource->connect() returned %d", err);
1538            return err;
1539        }
1540
1541#if 0
1542        mCachedSource = new NuCachedSource2(
1543                new ThrottledSource(
1544                    mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1545#else
1546        mCachedSource = new NuCachedSource2(mConnectingDataSource);
1547#endif
1548        mConnectingDataSource.clear();
1549
1550        dataSource = mCachedSource;
1551
1552        // We're going to prefill the cache before trying to instantiate
1553        // the extractor below, as the latter is an operation that otherwise
1554        // could block on the datasource for a significant amount of time.
1555        // During that time we'd be unable to abort the preparation phase
1556        // without this prefill.
1557
1558        mLock.unlock();
1559
1560        for (;;) {
1561            status_t finalStatus;
1562            size_t cachedDataRemaining =
1563                mCachedSource->approxDataRemaining(&finalStatus);
1564
1565            if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
1566                    || (mFlags & PREPARE_CANCELLED)) {
1567                break;
1568            }
1569
1570            usleep(200000);
1571        }
1572
1573        mLock.lock();
1574
1575        if (mFlags & PREPARE_CANCELLED) {
1576            LOGI("Prepare cancelled while waiting for initial cache fill.");
1577            return UNKNOWN_ERROR;
1578        }
1579    } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1580        if (mLooper == NULL) {
1581            mLooper = new ALooper;
1582            mLooper->setName("rtsp");
1583            mLooper->start();
1584        }
1585        mRTSPController = new ARTSPController(mLooper);
1586        mConnectingRTSPController = mRTSPController;
1587
1588        mLock.unlock();
1589        status_t err = mRTSPController->connect(mUri.string());
1590        mLock.lock();
1591
1592        mConnectingRTSPController.clear();
1593
1594        LOGI("ARTSPController::connect returned %d", err);
1595
1596        if (err != OK) {
1597            mRTSPController.clear();
1598            return err;
1599        }
1600
1601        sp<MediaExtractor> extractor = mRTSPController.get();
1602        return setDataSource_l(extractor);
1603    } else {
1604        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1605    }
1606
1607    if (dataSource == NULL) {
1608        return UNKNOWN_ERROR;
1609    }
1610
1611    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1612
1613    if (extractor == NULL) {
1614        return UNKNOWN_ERROR;
1615    }
1616
1617    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
1618    if (mDecryptHandle != NULL) {
1619        CHECK(mDrmManagerClient);
1620        if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
1621            if (DecryptApiType::WV_BASED == mDecryptHandle->decryptApiType) {
1622                LOGD("Setting mCachedSource to NULL for WVM\n");
1623                mCachedSource.clear();
1624            }
1625        } else {
1626            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
1627        }
1628    }
1629
1630    return setDataSource_l(extractor);
1631}
1632
1633void AwesomePlayer::abortPrepare(status_t err) {
1634    CHECK(err != OK);
1635
1636    if (mIsAsyncPrepare) {
1637        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1638    }
1639
1640    mPrepareResult = err;
1641    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
1642    mAsyncPrepareEvent = NULL;
1643    mPreparedCondition.broadcast();
1644}
1645
1646// static
1647bool AwesomePlayer::ContinuePreparation(void *cookie) {
1648    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1649
1650    return (me->mFlags & PREPARE_CANCELLED) == 0;
1651}
1652
1653void AwesomePlayer::onPrepareAsyncEvent() {
1654    Mutex::Autolock autoLock(mLock);
1655
1656    if (mFlags & PREPARE_CANCELLED) {
1657        LOGI("prepare was cancelled before doing anything");
1658        abortPrepare(UNKNOWN_ERROR);
1659        return;
1660    }
1661
1662    if (mUri.size() > 0) {
1663        status_t err = finishSetDataSource_l();
1664
1665        if (err != OK) {
1666            abortPrepare(err);
1667            return;
1668        }
1669    }
1670
1671    if (mVideoTrack != NULL && mVideoSource == NULL) {
1672        status_t err = initVideoDecoder();
1673
1674        if (err != OK) {
1675            abortPrepare(err);
1676            return;
1677        }
1678    }
1679
1680    if (mAudioTrack != NULL && mAudioSource == NULL) {
1681        status_t err = initAudioDecoder();
1682
1683        if (err != OK) {
1684            abortPrepare(err);
1685            return;
1686        }
1687    }
1688
1689    mFlags |= PREPARING_CONNECTED;
1690
1691    if (mCachedSource != NULL || mRTSPController != NULL) {
1692        postBufferingEvent_l();
1693    } else {
1694        finishAsyncPrepare_l();
1695    }
1696}
1697
1698void AwesomePlayer::finishAsyncPrepare_l() {
1699    if (mIsAsyncPrepare) {
1700        if (mVideoSource == NULL) {
1701            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1702        } else {
1703            notifyVideoSize_l();
1704        }
1705
1706        notifyListener_l(MEDIA_PREPARED);
1707    }
1708
1709    mPrepareResult = OK;
1710    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
1711    mFlags |= PREPARED;
1712    mAsyncPrepareEvent = NULL;
1713    mPreparedCondition.broadcast();
1714}
1715
1716uint32_t AwesomePlayer::flags() const {
1717    return mExtractorFlags;
1718}
1719
1720void AwesomePlayer::postAudioEOS() {
1721    postCheckAudioStatusEvent_l();
1722}
1723
1724void AwesomePlayer::postAudioSeekComplete() {
1725    postCheckAudioStatusEvent_l();
1726}
1727
1728}  // namespace android
1729