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