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