AwesomePlayer.cpp revision 2eb62955eb84b97695e8a7e56e14310cbb86412b
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    bool deferredAudioSeek = false;
754
755    if (mDecryptHandle != NULL) {
756        int64_t position;
757        getPosition(&position);
758        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
759                Playback::START, position / 1000);
760    }
761
762    if (mAudioSource != NULL) {
763        if (mAudioPlayer == NULL) {
764            if (mAudioSink != NULL) {
765                mAudioPlayer = new AudioPlayer(mAudioSink, this);
766                mAudioPlayer->setSource(mAudioSource);
767
768                mTimeSource = mAudioPlayer;
769
770                deferredAudioSeek = true;
771
772                mWatchForAudioSeekComplete = false;
773                mWatchForAudioEOS = true;
774            }
775        }
776
777        CHECK(!(mFlags & AUDIO_RUNNING));
778
779        if (mVideoSource == NULL) {
780            status_t err = startAudioPlayer_l();
781
782            if (err != OK) {
783                delete mAudioPlayer;
784                mAudioPlayer = NULL;
785
786                mFlags &= ~(PLAYING | FIRST_FRAME);
787
788                if (mDecryptHandle != NULL) {
789                    mDrmManagerClient->setPlaybackStatus(
790                            mDecryptHandle, Playback::STOP, 0);
791                }
792
793                return err;
794            }
795        }
796    }
797
798    if (mTimeSource == NULL && mAudioPlayer == NULL) {
799        mTimeSource = &mSystemTimeSource;
800    }
801
802    if (mVideoSource != NULL) {
803        // Kick off video playback
804        postVideoEvent_l();
805
806        if (mAudioSource != NULL && mVideoSource != NULL) {
807            postVideoLagEvent_l();
808        }
809    }
810
811    if (deferredAudioSeek) {
812        // If there was a seek request while we were paused
813        // and we're just starting up again, honor the request now.
814        seekAudioIfNecessary_l();
815    }
816
817    if (mFlags & AT_EOS) {
818        // Legacy behaviour, if a stream finishes playing and then
819        // is started again, we play from the start...
820        seekTo_l(0);
821    }
822
823    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
824        | IMediaPlayerService::kBatteryDataTrackDecoder;
825    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
826        params |= IMediaPlayerService::kBatteryDataTrackAudio;
827    }
828    if (mVideoSource != NULL) {
829        params |= IMediaPlayerService::kBatteryDataTrackVideo;
830    }
831    addBatteryData(params);
832
833    return OK;
834}
835
836status_t AwesomePlayer::startAudioPlayer_l() {
837    CHECK(!(mFlags & AUDIO_RUNNING));
838
839    if (mAudioSource == NULL || mAudioPlayer == NULL) {
840        return OK;
841    }
842
843    if (!(mFlags & AUDIOPLAYER_STARTED)) {
844        mFlags |= AUDIOPLAYER_STARTED;
845
846        // We've already started the MediaSource in order to enable
847        // the prefetcher to read its data.
848        status_t err = mAudioPlayer->start(
849                true /* sourceAlreadyStarted */);
850
851        if (err != OK) {
852            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
853            return err;
854        }
855    } else {
856        mAudioPlayer->resume();
857    }
858
859    mFlags |= AUDIO_RUNNING;
860
861    mWatchForAudioEOS = true;
862
863    return OK;
864}
865
866void AwesomePlayer::notifyVideoSize_l() {
867    sp<MetaData> meta = mVideoSource->getFormat();
868
869    int32_t cropLeft, cropTop, cropRight, cropBottom;
870    if (!meta->findRect(
871                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
872        int32_t width, height;
873        CHECK(meta->findInt32(kKeyWidth, &width));
874        CHECK(meta->findInt32(kKeyHeight, &height));
875
876        cropLeft = cropTop = 0;
877        cropRight = width - 1;
878        cropBottom = height - 1;
879
880        LOGV("got dimensions only %d x %d", width, height);
881    } else {
882        LOGV("got crop rect %d, %d, %d, %d",
883             cropLeft, cropTop, cropRight, cropBottom);
884    }
885
886    int32_t usableWidth = cropRight - cropLeft + 1;
887    int32_t usableHeight = cropBottom - cropTop + 1;
888    if (mDisplayWidth != 0) {
889        usableWidth = mDisplayWidth;
890    }
891    if (mDisplayHeight != 0) {
892        usableHeight = mDisplayHeight;
893    }
894
895    int32_t rotationDegrees;
896    if (!mVideoTrack->getFormat()->findInt32(
897                kKeyRotation, &rotationDegrees)) {
898        rotationDegrees = 0;
899    }
900
901    if (rotationDegrees == 90 || rotationDegrees == 270) {
902        notifyListener_l(
903                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
904    } else {
905        notifyListener_l(
906                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
907    }
908}
909
910void AwesomePlayer::initRenderer_l() {
911    if (mNativeWindow == NULL) {
912        return;
913    }
914
915    sp<MetaData> meta = mVideoSource->getFormat();
916
917    int32_t format;
918    const char *component;
919    int32_t decodedWidth, decodedHeight;
920    CHECK(meta->findInt32(kKeyColorFormat, &format));
921    CHECK(meta->findCString(kKeyDecoderComponent, &component));
922    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
923    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
924
925    int32_t rotationDegrees;
926    if (!mVideoTrack->getFormat()->findInt32(
927                kKeyRotation, &rotationDegrees)) {
928        rotationDegrees = 0;
929    }
930
931    mVideoRenderer.clear();
932
933    // Must ensure that mVideoRenderer's destructor is actually executed
934    // before creating a new one.
935    IPCThreadState::self()->flushCommands();
936
937    if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
938        // Hardware decoders avoid the CPU color conversion by decoding
939        // directly to ANativeBuffers, so we must use a renderer that
940        // just pushes those buffers to the ANativeWindow.
941        mVideoRenderer =
942            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
943    } else {
944        // Other decoders are instantiated locally and as a consequence
945        // allocate their buffers in local address space.  This renderer
946        // then performs a color conversion and copy to get the data
947        // into the ANativeBuffer.
948        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
949    }
950}
951
952status_t AwesomePlayer::pause() {
953    Mutex::Autolock autoLock(mLock);
954
955    mFlags &= ~CACHE_UNDERRUN;
956
957    return pause_l();
958}
959
960status_t AwesomePlayer::pause_l(bool at_eos) {
961    if (!(mFlags & PLAYING)) {
962        return OK;
963    }
964
965    cancelPlayerEvents(true /* keepBufferingGoing */);
966
967    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
968        if (at_eos) {
969            // If we played the audio stream to completion we
970            // want to make sure that all samples remaining in the audio
971            // track's queue are played out.
972            mAudioPlayer->pause(true /* playPendingSamples */);
973        } else {
974            mAudioPlayer->pause();
975        }
976
977        mFlags &= ~AUDIO_RUNNING;
978    }
979
980    mFlags &= ~PLAYING;
981
982    if (mDecryptHandle != NULL) {
983        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
984                Playback::PAUSE, 0);
985    }
986
987    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
988    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
989        params |= IMediaPlayerService::kBatteryDataTrackAudio;
990    }
991    if (mVideoSource != NULL) {
992        params |= IMediaPlayerService::kBatteryDataTrackVideo;
993    }
994
995    addBatteryData(params);
996
997    return OK;
998}
999
1000bool AwesomePlayer::isPlaying() const {
1001    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1002}
1003
1004void AwesomePlayer::setSurface(const sp<Surface> &surface) {
1005    Mutex::Autolock autoLock(mLock);
1006
1007    mSurface = surface;
1008    mNativeWindow = surface;
1009}
1010
1011void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1012    Mutex::Autolock autoLock(mLock);
1013
1014    mSurface.clear();
1015    if (surfaceTexture != NULL) {
1016        mNativeWindow = new SurfaceTextureClient(surfaceTexture);
1017    }
1018
1019}
1020
1021void AwesomePlayer::setAudioSink(
1022        const sp<MediaPlayerBase::AudioSink> &audioSink) {
1023    Mutex::Autolock autoLock(mLock);
1024
1025    mAudioSink = audioSink;
1026}
1027
1028status_t AwesomePlayer::setLooping(bool shouldLoop) {
1029    Mutex::Autolock autoLock(mLock);
1030
1031    mFlags = mFlags & ~LOOPING;
1032
1033    if (shouldLoop) {
1034        mFlags |= LOOPING;
1035    }
1036
1037    return OK;
1038}
1039
1040status_t AwesomePlayer::getDuration(int64_t *durationUs) {
1041    Mutex::Autolock autoLock(mMiscStateLock);
1042
1043    if (mDurationUs < 0) {
1044        return UNKNOWN_ERROR;
1045    }
1046
1047    *durationUs = mDurationUs;
1048
1049    return OK;
1050}
1051
1052status_t AwesomePlayer::getPosition(int64_t *positionUs) {
1053    if (mRTSPController != NULL) {
1054        *positionUs = mRTSPController->getNormalPlayTimeUs();
1055    }
1056    else if (mSeeking != NO_SEEK) {
1057        *positionUs = mSeekTimeUs;
1058    } else if (mVideoSource != NULL) {
1059        Mutex::Autolock autoLock(mMiscStateLock);
1060        *positionUs = mVideoTimeUs;
1061    } else if (mAudioPlayer != NULL) {
1062        *positionUs = mAudioPlayer->getMediaTimeUs();
1063    } else {
1064        *positionUs = 0;
1065    }
1066
1067    return OK;
1068}
1069
1070status_t AwesomePlayer::seekTo(int64_t timeUs) {
1071    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
1072        Mutex::Autolock autoLock(mLock);
1073        return seekTo_l(timeUs);
1074    }
1075
1076    return OK;
1077}
1078
1079// static
1080void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1081    static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1082}
1083
1084void AwesomePlayer::onRTSPSeekDone() {
1085    notifyListener_l(MEDIA_SEEK_COMPLETE);
1086    mSeekNotificationSent = true;
1087}
1088
1089status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
1090    if (mRTSPController != NULL) {
1091        mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
1092        return OK;
1093    }
1094
1095    if (mFlags & CACHE_UNDERRUN) {
1096        mFlags &= ~CACHE_UNDERRUN;
1097        play_l();
1098    }
1099
1100    mSeeking = SEEK;
1101    mSeekNotificationSent = false;
1102    mSeekTimeUs = timeUs;
1103    mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1104
1105    seekAudioIfNecessary_l();
1106
1107    if (!(mFlags & PLAYING)) {
1108        LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1109             " immediately.");
1110
1111        notifyListener_l(MEDIA_SEEK_COMPLETE);
1112        mSeekNotificationSent = true;
1113
1114        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1115            mFlags |= SEEK_PREVIEW;
1116            postVideoEvent_l();
1117        }
1118    }
1119
1120    return OK;
1121}
1122
1123void AwesomePlayer::seekAudioIfNecessary_l() {
1124    if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1125        mAudioPlayer->seekTo(mSeekTimeUs);
1126
1127        mWatchForAudioSeekComplete = true;
1128        mWatchForAudioEOS = true;
1129        mSeekNotificationSent = false;
1130
1131        if (mDecryptHandle != NULL) {
1132            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1133                    Playback::PAUSE, 0);
1134            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1135                    Playback::START, mSeekTimeUs / 1000);
1136        }
1137    }
1138}
1139
1140void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1141    CHECK(source != NULL);
1142
1143    mAudioTrack = source;
1144}
1145
1146status_t AwesomePlayer::initAudioDecoder() {
1147    sp<MetaData> meta = mAudioTrack->getFormat();
1148
1149    const char *mime;
1150    CHECK(meta->findCString(kKeyMIMEType, &mime));
1151
1152    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1153        mAudioSource = mAudioTrack;
1154    } else {
1155        mAudioSource = OMXCodec::Create(
1156                mClient.interface(), mAudioTrack->getFormat(),
1157                false, // createEncoder
1158                mAudioTrack);
1159    }
1160
1161    if (mAudioSource != NULL) {
1162        int64_t durationUs;
1163        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1164            Mutex::Autolock autoLock(mMiscStateLock);
1165            if (mDurationUs < 0 || durationUs > mDurationUs) {
1166                mDurationUs = durationUs;
1167            }
1168        }
1169
1170        status_t err = mAudioSource->start();
1171
1172        if (err != OK) {
1173            mAudioSource.clear();
1174            return err;
1175        }
1176    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1177        // For legacy reasons we're simply going to ignore the absence
1178        // of an audio decoder for QCELP instead of aborting playback
1179        // altogether.
1180        return OK;
1181    }
1182
1183    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1184}
1185
1186void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1187    CHECK(source != NULL);
1188
1189    mVideoTrack = source;
1190}
1191
1192status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1193
1194    // Either the application or the DRM system can independently say
1195    // that there must be a hardware-protected path to an external video sink.
1196    // For now we always require a hardware-protected path to external video sink
1197    // if content is DRMed, but eventually this could be optional per DRM agent.
1198    // When the application wants protection, then
1199    //   (USE_SURFACE_ALLOC && (mSurface != 0) &&
1200    //   (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1201    // will be true, but that part is already handled by SurfaceFlinger.
1202    if (mDecryptHandle != NULL) {
1203        flags |= OMXCodec::kEnableGrallocUsageProtected;
1204    }
1205    LOGV("initVideoDecoder flags=0x%x", flags);
1206    mVideoSource = OMXCodec::Create(
1207            mClient.interface(), mVideoTrack->getFormat(),
1208            false, // createEncoder
1209            mVideoTrack,
1210            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
1211
1212    if (mVideoSource != NULL) {
1213        int64_t durationUs;
1214        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1215            Mutex::Autolock autoLock(mMiscStateLock);
1216            if (mDurationUs < 0 || durationUs > mDurationUs) {
1217                mDurationUs = durationUs;
1218            }
1219        }
1220
1221        status_t err = mVideoSource->start();
1222
1223        if (err != OK) {
1224            mVideoSource.clear();
1225            return err;
1226        }
1227    }
1228
1229    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1230}
1231
1232void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1233    if (mSeeking == SEEK_VIDEO_ONLY) {
1234        mSeeking = NO_SEEK;
1235        return;
1236    }
1237
1238    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1239        return;
1240    }
1241
1242    if (mAudioPlayer != NULL) {
1243        LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1244
1245        // If we don't have a video time, seek audio to the originally
1246        // requested seek time instead.
1247
1248        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1249        mWatchForAudioSeekComplete = true;
1250    } else if (!mSeekNotificationSent) {
1251        // If we're playing video only, report seek complete now,
1252        // otherwise audio player will notify us later.
1253        notifyListener_l(MEDIA_SEEK_COMPLETE);
1254    }
1255
1256    mFlags |= FIRST_FRAME;
1257    mSeeking = NO_SEEK;
1258    mSeekNotificationSent = false;
1259
1260    if (mDecryptHandle != NULL) {
1261        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1262                Playback::PAUSE, 0);
1263        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1264                Playback::START, videoTimeUs / 1000);
1265    }
1266}
1267
1268void AwesomePlayer::onVideoEvent() {
1269    Mutex::Autolock autoLock(mLock);
1270    if (!mVideoEventPending) {
1271        // The event has been cancelled in reset_l() but had already
1272        // been scheduled for execution at that time.
1273        return;
1274    }
1275    mVideoEventPending = false;
1276
1277    if (mSeeking != NO_SEEK) {
1278        if (mVideoBuffer) {
1279            mVideoBuffer->release();
1280            mVideoBuffer = NULL;
1281        }
1282
1283        if (mSeeking == SEEK && mCachedSource != NULL && mAudioSource != NULL
1284                && !(mFlags & SEEK_PREVIEW)) {
1285            // We're going to seek the video source first, followed by
1286            // the audio source.
1287            // In order to avoid jumps in the DataSource offset caused by
1288            // the audio codec prefetching data from the old locations
1289            // while the video codec is already reading data from the new
1290            // locations, we'll "pause" the audio source, causing it to
1291            // stop reading input data until a subsequent seek.
1292
1293            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1294                mAudioPlayer->pause();
1295
1296                mFlags &= ~AUDIO_RUNNING;
1297            }
1298            mAudioSource->pause();
1299        }
1300    }
1301
1302    if (!mVideoBuffer) {
1303        MediaSource::ReadOptions options;
1304        if (mSeeking != NO_SEEK) {
1305            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1306
1307            options.setSeekTo(
1308                    mSeekTimeUs,
1309                    mSeeking == SEEK_VIDEO_ONLY
1310                        ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1311                        : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1312        }
1313        for (;;) {
1314            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1315            options.clearSeekTo();
1316
1317            if (err != OK) {
1318                CHECK(mVideoBuffer == NULL);
1319
1320                if (err == INFO_FORMAT_CHANGED) {
1321                    LOGV("VideoSource signalled format change.");
1322
1323                    notifyVideoSize_l();
1324
1325                    if (mVideoRenderer != NULL) {
1326                        mVideoRendererIsPreview = false;
1327                        initRenderer_l();
1328                    }
1329                    continue;
1330                }
1331
1332                // So video playback is complete, but we may still have
1333                // a seek request pending that needs to be applied
1334                // to the audio track.
1335                if (mSeeking != NO_SEEK) {
1336                    LOGV("video stream ended while seeking!");
1337                }
1338                finishSeekIfNecessary(-1);
1339
1340                mFlags |= VIDEO_AT_EOS;
1341                postStreamDoneEvent_l(err);
1342                return;
1343            }
1344
1345            if (mVideoBuffer->range_length() == 0) {
1346                // Some decoders, notably the PV AVC software decoder
1347                // return spurious empty buffers that we just want to ignore.
1348
1349                mVideoBuffer->release();
1350                mVideoBuffer = NULL;
1351                continue;
1352            }
1353
1354            break;
1355        }
1356    }
1357
1358    int64_t timeUs;
1359    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1360
1361    if (mSeeking == SEEK_VIDEO_ONLY) {
1362        if (mSeekTimeUs > timeUs) {
1363            LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1364                 mSeekTimeUs, timeUs);
1365        }
1366    }
1367
1368    {
1369        Mutex::Autolock autoLock(mMiscStateLock);
1370        mVideoTimeUs = timeUs;
1371    }
1372
1373    SeekType wasSeeking = mSeeking;
1374    finishSeekIfNecessary(timeUs);
1375
1376    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1377        status_t err = startAudioPlayer_l();
1378        if (err != OK) {
1379            LOGE("Startung the audio player failed w/ err %d", err);
1380            return;
1381        }
1382    }
1383
1384    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1385
1386    if (mFlags & FIRST_FRAME) {
1387        mFlags &= ~FIRST_FRAME;
1388        mSinceLastDropped = 0;
1389        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1390    }
1391
1392    int64_t realTimeUs, mediaTimeUs;
1393    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1394        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1395        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1396    }
1397
1398    if (wasSeeking == SEEK_VIDEO_ONLY) {
1399        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1400
1401        int64_t latenessUs = nowUs - timeUs;
1402
1403        if (latenessUs > 0) {
1404            LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1405        }
1406    }
1407
1408    if (wasSeeking == NO_SEEK) {
1409        // Let's display the first frame after seeking right away.
1410
1411        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1412
1413        int64_t latenessUs = nowUs - timeUs;
1414
1415        if (latenessUs > 500000ll
1416                && mRTSPController == NULL
1417                && mAudioPlayer != NULL
1418                && mAudioPlayer->getMediaTimeMapping(
1419                    &realTimeUs, &mediaTimeUs)) {
1420            LOGI("we're much too late (%.2f secs), video skipping ahead",
1421                 latenessUs / 1E6);
1422
1423            mVideoBuffer->release();
1424            mVideoBuffer = NULL;
1425
1426            mSeeking = SEEK_VIDEO_ONLY;
1427            mSeekTimeUs = mediaTimeUs;
1428
1429            postVideoEvent_l();
1430            return;
1431        }
1432
1433        if (latenessUs > 40000) {
1434            // We're more than 40ms late.
1435            LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
1436            if ( mSinceLastDropped > FRAME_DROP_FREQ)
1437            {
1438                LOGV("we're late by %lld us (%.2f secs) dropping one after %d frames", latenessUs, latenessUs / 1E6, mSinceLastDropped);
1439                mSinceLastDropped = 0;
1440                mVideoBuffer->release();
1441                mVideoBuffer = NULL;
1442
1443                postVideoEvent_l();
1444                return;
1445            }
1446        }
1447
1448        if (latenessUs < -10000) {
1449            // We're more than 10ms early.
1450
1451            postVideoEvent_l(10000);
1452            return;
1453        }
1454    }
1455
1456    if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1457        mVideoRendererIsPreview = false;
1458
1459        initRenderer_l();
1460    }
1461
1462    if (mVideoRenderer != NULL) {
1463        mSinceLastDropped++;
1464        mVideoRenderer->render(mVideoBuffer);
1465    }
1466
1467    mVideoBuffer->release();
1468    mVideoBuffer = NULL;
1469
1470    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
1471        mFlags &= ~SEEK_PREVIEW;
1472        return;
1473    }
1474
1475    postVideoEvent_l();
1476}
1477
1478void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1479    if (mVideoEventPending) {
1480        return;
1481    }
1482
1483    mVideoEventPending = true;
1484    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1485}
1486
1487void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1488    if (mStreamDoneEventPending) {
1489        return;
1490    }
1491    mStreamDoneEventPending = true;
1492
1493    mStreamDoneStatus = status;
1494    mQueue.postEvent(mStreamDoneEvent);
1495}
1496
1497void AwesomePlayer::postBufferingEvent_l() {
1498    if (mBufferingEventPending) {
1499        return;
1500    }
1501    mBufferingEventPending = true;
1502    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1503}
1504
1505void AwesomePlayer::postVideoLagEvent_l() {
1506    if (mVideoLagEventPending) {
1507        return;
1508    }
1509    mVideoLagEventPending = true;
1510    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1511}
1512
1513void AwesomePlayer::postCheckAudioStatusEvent_l() {
1514    if (mAudioStatusEventPending) {
1515        return;
1516    }
1517    mAudioStatusEventPending = true;
1518    mQueue.postEvent(mCheckAudioStatusEvent);
1519}
1520
1521void AwesomePlayer::onCheckAudioStatus() {
1522    Mutex::Autolock autoLock(mLock);
1523    if (!mAudioStatusEventPending) {
1524        // Event was dispatched and while we were blocking on the mutex,
1525        // has already been cancelled.
1526        return;
1527    }
1528
1529    mAudioStatusEventPending = false;
1530
1531    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1532        mWatchForAudioSeekComplete = false;
1533
1534        if (!mSeekNotificationSent) {
1535            notifyListener_l(MEDIA_SEEK_COMPLETE);
1536            mSeekNotificationSent = true;
1537        }
1538
1539        mSeeking = NO_SEEK;
1540    }
1541
1542    status_t finalStatus;
1543    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1544        mWatchForAudioEOS = false;
1545        mFlags |= AUDIO_AT_EOS;
1546        mFlags |= FIRST_FRAME;
1547        postStreamDoneEvent_l(finalStatus);
1548    }
1549}
1550
1551status_t AwesomePlayer::prepare() {
1552    Mutex::Autolock autoLock(mLock);
1553    return prepare_l();
1554}
1555
1556status_t AwesomePlayer::prepare_l() {
1557    if (mFlags & PREPARED) {
1558        return OK;
1559    }
1560
1561    if (mFlags & PREPARING) {
1562        return UNKNOWN_ERROR;
1563    }
1564
1565    mIsAsyncPrepare = false;
1566    status_t err = prepareAsync_l();
1567
1568    if (err != OK) {
1569        return err;
1570    }
1571
1572    while (mFlags & PREPARING) {
1573        mPreparedCondition.wait(mLock);
1574    }
1575
1576    return mPrepareResult;
1577}
1578
1579status_t AwesomePlayer::prepareAsync() {
1580    Mutex::Autolock autoLock(mLock);
1581
1582    if (mFlags & PREPARING) {
1583        return UNKNOWN_ERROR;  // async prepare already pending
1584    }
1585
1586    mIsAsyncPrepare = true;
1587    return prepareAsync_l();
1588}
1589
1590status_t AwesomePlayer::prepareAsync_l() {
1591    if (mFlags & PREPARING) {
1592        return UNKNOWN_ERROR;  // async prepare already pending
1593    }
1594
1595    if (!mQueueStarted) {
1596        mQueue.start();
1597        mQueueStarted = true;
1598    }
1599
1600    mFlags |= PREPARING;
1601    mAsyncPrepareEvent = new AwesomeEvent(
1602            this, &AwesomePlayer::onPrepareAsyncEvent);
1603
1604    mQueue.postEvent(mAsyncPrepareEvent);
1605
1606    return OK;
1607}
1608
1609status_t AwesomePlayer::finishSetDataSource_l() {
1610    sp<DataSource> dataSource;
1611
1612    if (!strncasecmp("http://", mUri.string(), 7)
1613            || !strncasecmp("https://", mUri.string(), 8)) {
1614        mConnectingDataSource = new NuHTTPDataSource(
1615                (mFlags & INCOGNITO) ? NuHTTPDataSource::kFlagIncognito : 0);
1616
1617        mLock.unlock();
1618        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
1619        mLock.lock();
1620
1621        if (err != OK) {
1622            mConnectingDataSource.clear();
1623
1624            LOGI("mConnectingDataSource->connect() returned %d", err);
1625            return err;
1626        }
1627
1628#if 0
1629        mCachedSource = new NuCachedSource2(
1630                new ThrottledSource(
1631                    mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1632#else
1633        mCachedSource = new NuCachedSource2(mConnectingDataSource);
1634#endif
1635        mConnectingDataSource.clear();
1636
1637        dataSource = mCachedSource;
1638
1639        // We're going to prefill the cache before trying to instantiate
1640        // the extractor below, as the latter is an operation that otherwise
1641        // could block on the datasource for a significant amount of time.
1642        // During that time we'd be unable to abort the preparation phase
1643        // without this prefill.
1644
1645        mLock.unlock();
1646
1647        for (;;) {
1648            status_t finalStatus;
1649            size_t cachedDataRemaining =
1650                mCachedSource->approxDataRemaining(&finalStatus);
1651
1652            if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
1653                    || (mFlags & PREPARE_CANCELLED)) {
1654                break;
1655            }
1656
1657            usleep(200000);
1658        }
1659
1660        mLock.lock();
1661
1662        if (mFlags & PREPARE_CANCELLED) {
1663            LOGI("Prepare cancelled while waiting for initial cache fill.");
1664            return UNKNOWN_ERROR;
1665        }
1666    } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1667        if (mLooper == NULL) {
1668            mLooper = new ALooper;
1669            mLooper->setName("rtsp");
1670            mLooper->start();
1671        }
1672        mRTSPController = new ARTSPController(mLooper);
1673        mConnectingRTSPController = mRTSPController;
1674
1675        mLock.unlock();
1676        status_t err = mRTSPController->connect(mUri.string());
1677        mLock.lock();
1678
1679        mConnectingRTSPController.clear();
1680
1681        LOGI("ARTSPController::connect returned %d", err);
1682
1683        if (err != OK) {
1684            mRTSPController.clear();
1685            return err;
1686        }
1687
1688        sp<MediaExtractor> extractor = mRTSPController.get();
1689        return setDataSource_l(extractor);
1690    } else {
1691        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1692    }
1693
1694    if (dataSource == NULL) {
1695        return UNKNOWN_ERROR;
1696    }
1697
1698    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1699
1700    if (extractor == NULL) {
1701        return UNKNOWN_ERROR;
1702    }
1703
1704    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
1705    if (mDecryptHandle != NULL) {
1706        CHECK(mDrmManagerClient);
1707        if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
1708            if (DecryptApiType::WV_BASED == mDecryptHandle->decryptApiType) {
1709                LOGD("Setting mCachedSource to NULL for WVM\n");
1710                mCachedSource.clear();
1711            }
1712        } else {
1713            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
1714        }
1715    }
1716
1717    return setDataSource_l(extractor);
1718}
1719
1720void AwesomePlayer::abortPrepare(status_t err) {
1721    CHECK(err != OK);
1722
1723    if (mIsAsyncPrepare) {
1724        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1725    }
1726
1727    mPrepareResult = err;
1728    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
1729    mAsyncPrepareEvent = NULL;
1730    mPreparedCondition.broadcast();
1731}
1732
1733// static
1734bool AwesomePlayer::ContinuePreparation(void *cookie) {
1735    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1736
1737    return (me->mFlags & PREPARE_CANCELLED) == 0;
1738}
1739
1740void AwesomePlayer::onPrepareAsyncEvent() {
1741    Mutex::Autolock autoLock(mLock);
1742
1743    if (mFlags & PREPARE_CANCELLED) {
1744        LOGI("prepare was cancelled before doing anything");
1745        abortPrepare(UNKNOWN_ERROR);
1746        return;
1747    }
1748
1749    if (mUri.size() > 0) {
1750        status_t err = finishSetDataSource_l();
1751
1752        if (err != OK) {
1753            abortPrepare(err);
1754            return;
1755        }
1756    }
1757
1758    if (mVideoTrack != NULL && mVideoSource == NULL) {
1759        status_t err = initVideoDecoder();
1760
1761        if (err != OK) {
1762            abortPrepare(err);
1763            return;
1764        }
1765    }
1766
1767    if (mAudioTrack != NULL && mAudioSource == NULL) {
1768        status_t err = initAudioDecoder();
1769
1770        if (err != OK) {
1771            abortPrepare(err);
1772            return;
1773        }
1774    }
1775
1776    mFlags |= PREPARING_CONNECTED;
1777
1778    if (mCachedSource != NULL || mRTSPController != NULL) {
1779        postBufferingEvent_l();
1780    } else {
1781        finishAsyncPrepare_l();
1782    }
1783}
1784
1785void AwesomePlayer::finishAsyncPrepare_l() {
1786    if (mIsAsyncPrepare) {
1787        if (mVideoSource == NULL) {
1788            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1789        } else {
1790            notifyVideoSize_l();
1791        }
1792
1793        notifyListener_l(MEDIA_PREPARED);
1794    }
1795
1796    mPrepareResult = OK;
1797    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
1798    mFlags |= PREPARED;
1799    mAsyncPrepareEvent = NULL;
1800    mPreparedCondition.broadcast();
1801}
1802
1803uint32_t AwesomePlayer::flags() const {
1804    return mExtractorFlags;
1805}
1806
1807void AwesomePlayer::postAudioEOS() {
1808    postCheckAudioStatusEvent_l();
1809}
1810
1811void AwesomePlayer::postAudioSeekComplete() {
1812    postCheckAudioStatusEvent_l();
1813}
1814
1815}  // namespace android
1816