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