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