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