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