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