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