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