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