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