AwesomePlayer.cpp revision a6e6c70a3c5403e178741eee20c7742e736c4818
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    int64_t looperTimeUs = ALooper::GetNowUs();
1867
1868    if (mFlags & FIRST_FRAME) {
1869        modifyFlags(FIRST_FRAME, CLEAR);
1870        mSinceLastDropped = 0;
1871        mClockEstimator->reset();
1872        mTimeSourceDeltaUs = estimateRealTimeUs(ts, systemTimeUs) - timeUs;
1873    }
1874
1875    int64_t realTimeUs, mediaTimeUs;
1876    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1877        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1878        ALOGV("updating TSdelta (%" PRId64 " => %" PRId64 " change %" PRId64 ")",
1879              mTimeSourceDeltaUs, realTimeUs - mediaTimeUs,
1880              mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs));
1881        ATRACE_INT("TS delta change (ms)", (mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)) / 1E3);
1882        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1883    }
1884
1885    if (wasSeeking == SEEK_VIDEO_ONLY) {
1886        int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs;
1887
1888        int64_t latenessUs = nowUs - timeUs;
1889
1890        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1891
1892        if (latenessUs > 0) {
1893            ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1894        }
1895    }
1896
1897    int64_t latenessUs = 0;
1898    if (wasSeeking == NO_SEEK) {
1899        // Let's display the first frame after seeking right away.
1900
1901        int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs;
1902
1903        latenessUs = nowUs - timeUs;
1904
1905        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1906
1907        if (latenessUs > 500000ll
1908                && mAudioPlayer != NULL
1909                && mAudioPlayer->getMediaTimeMapping(
1910                    &realTimeUs, &mediaTimeUs)) {
1911            if (mWVMExtractor == NULL) {
1912                ALOGI("we're much too late (%.2f secs), video skipping ahead",
1913                     latenessUs / 1E6);
1914
1915                mVideoBuffer->release();
1916                mVideoBuffer = NULL;
1917
1918                mSeeking = SEEK_VIDEO_ONLY;
1919                mSeekTimeUs = mediaTimeUs;
1920
1921                postVideoEvent_l();
1922                return;
1923            } else {
1924                // The widevine extractor doesn't deal well with seeking
1925                // audio and video independently. We'll just have to wait
1926                // until the decoder catches up, which won't be long at all.
1927                ALOGI("we're very late (%.2f secs)", latenessUs / 1E6);
1928            }
1929        }
1930
1931        if (latenessUs > 40000) {
1932            // We're more than 40ms late.
1933            ALOGV("we're late by %lld us (%.2f secs)",
1934                 latenessUs, latenessUs / 1E6);
1935
1936            if (!(mFlags & SLOW_DECODER_HACK)
1937                    || mSinceLastDropped > FRAME_DROP_FREQ)
1938            {
1939                ALOGV("we're late by %lld us (%.2f secs) dropping "
1940                     "one after %d frames",
1941                     latenessUs, latenessUs / 1E6, mSinceLastDropped);
1942
1943                mSinceLastDropped = 0;
1944                mVideoBuffer->release();
1945                mVideoBuffer = NULL;
1946
1947                {
1948                    Mutex::Autolock autoLock(mStatsLock);
1949                    ++mStats.mNumVideoFramesDropped;
1950                }
1951
1952                postVideoEvent_l(0);
1953                return;
1954            }
1955        }
1956
1957        if (latenessUs < -30000) {
1958            // We're more than 30ms early, schedule at most 20 ms before time due
1959            postVideoEvent_l(latenessUs < -60000 ? 30000 : -latenessUs - 20000);
1960            return;
1961        }
1962    }
1963
1964    if ((mNativeWindow != NULL)
1965            && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
1966        mVideoRendererIsPreview = false;
1967
1968        initRenderer_l();
1969    }
1970
1971    if (mVideoRenderer != NULL) {
1972        mSinceLastDropped++;
1973        mVideoBuffer->meta_data()->setInt64(kKeyTime, looperTimeUs - latenessUs);
1974
1975        mVideoRenderer->render(mVideoBuffer);
1976        if (!mVideoRenderingStarted) {
1977            mVideoRenderingStarted = true;
1978            notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
1979        }
1980
1981        if (mFlags & PLAYING) {
1982            notifyIfMediaStarted_l();
1983        }
1984    }
1985
1986    mVideoBuffer->release();
1987    mVideoBuffer = NULL;
1988
1989    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
1990        modifyFlags(SEEK_PREVIEW, CLEAR);
1991        return;
1992    }
1993
1994    /* get next frame time */
1995    if (wasSeeking == NO_SEEK) {
1996        MediaSource::ReadOptions options;
1997        for (;;) {
1998            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1999            if (err != OK) {
2000                // deal with any errors next time
2001                CHECK(mVideoBuffer == NULL);
2002                postVideoEvent_l(0);
2003                return;
2004            }
2005
2006            if (mVideoBuffer->range_length() != 0) {
2007                break;
2008            }
2009
2010            // Some decoders, notably the PV AVC software decoder
2011            // return spurious empty buffers that we just want to ignore.
2012
2013            mVideoBuffer->release();
2014            mVideoBuffer = NULL;
2015        }
2016
2017        {
2018            Mutex::Autolock autoLock(mStatsLock);
2019            ++mStats.mNumVideoFramesDecoded;
2020        }
2021
2022        int64_t nextTimeUs;
2023        CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs));
2024        systemTimeUs = mSystemTimeSource.getRealTimeUs();
2025        int64_t delayUs = nextTimeUs - estimateRealTimeUs(ts, systemTimeUs) + mTimeSourceDeltaUs;
2026        ATRACE_INT("Frame delta (ms)", (nextTimeUs - timeUs) / 1E3);
2027        ALOGV("next frame in %" PRId64, delayUs);
2028        // try to schedule 30ms before time due
2029        postVideoEvent_l(delayUs > 60000 ? 30000 : (delayUs < 30000 ? 0 : delayUs - 30000));
2030        return;
2031    }
2032
2033    postVideoEvent_l();
2034}
2035
2036int64_t AwesomePlayer::estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs) {
2037    if (ts == &mSystemTimeSource) {
2038        return systemTimeUs;
2039    } else {
2040        return (int64_t)mClockEstimator->estimate(systemTimeUs, ts->getRealTimeUs());
2041    }
2042}
2043
2044void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
2045    ATRACE_CALL();
2046
2047    if (mVideoEventPending) {
2048        return;
2049    }
2050
2051    mVideoEventPending = true;
2052    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
2053}
2054
2055void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
2056    if (mStreamDoneEventPending) {
2057        return;
2058    }
2059    mStreamDoneEventPending = true;
2060
2061    mStreamDoneStatus = status;
2062    mQueue.postEvent(mStreamDoneEvent);
2063}
2064
2065void AwesomePlayer::postBufferingEvent_l() {
2066    if (mBufferingEventPending) {
2067        return;
2068    }
2069    mBufferingEventPending = true;
2070    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
2071}
2072
2073void AwesomePlayer::postVideoLagEvent_l() {
2074    if (mVideoLagEventPending) {
2075        return;
2076    }
2077    mVideoLagEventPending = true;
2078    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
2079}
2080
2081void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
2082    Mutex::Autolock autoLock(mAudioLock);
2083    if (mAudioStatusEventPending) {
2084        return;
2085    }
2086    mAudioStatusEventPending = true;
2087    // Do not honor delay when looping in order to limit audio gap
2088    if (mFlags & (LOOPING | AUTO_LOOPING)) {
2089        delayUs = 0;
2090    }
2091    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
2092}
2093
2094void AwesomePlayer::postAudioTearDownEvent(int64_t delayUs) {
2095    Mutex::Autolock autoLock(mAudioLock);
2096    if (mAudioTearDownEventPending) {
2097        return;
2098    }
2099    mAudioTearDownEventPending = true;
2100    mQueue.postEventWithDelay(mAudioTearDownEvent, delayUs);
2101}
2102
2103void AwesomePlayer::onCheckAudioStatus() {
2104    {
2105        Mutex::Autolock autoLock(mAudioLock);
2106        if (!mAudioStatusEventPending) {
2107            // Event was dispatched and while we were blocking on the mutex,
2108            // has already been cancelled.
2109            return;
2110        }
2111
2112        mAudioStatusEventPending = false;
2113    }
2114
2115    Mutex::Autolock autoLock(mLock);
2116
2117    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
2118        mWatchForAudioSeekComplete = false;
2119
2120        if (!mSeekNotificationSent) {
2121            notifyListener_l(MEDIA_SEEK_COMPLETE);
2122            mSeekNotificationSent = true;
2123        }
2124
2125        if (mVideoSource == NULL) {
2126            // For video the mSeeking flag is always reset in finishSeekIfNecessary
2127            mSeeking = NO_SEEK;
2128        }
2129
2130        notifyIfMediaStarted_l();
2131    }
2132
2133    status_t finalStatus;
2134    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
2135        mWatchForAudioEOS = false;
2136        modifyFlags(AUDIO_AT_EOS, SET);
2137        modifyFlags(FIRST_FRAME, SET);
2138        postStreamDoneEvent_l(finalStatus);
2139    }
2140}
2141
2142status_t AwesomePlayer::prepare() {
2143    ATRACE_CALL();
2144    Mutex::Autolock autoLock(mLock);
2145    return prepare_l();
2146}
2147
2148status_t AwesomePlayer::prepare_l() {
2149    if (mFlags & PREPARED) {
2150        return OK;
2151    }
2152
2153    if (mFlags & PREPARING) {
2154        return UNKNOWN_ERROR;
2155    }
2156
2157    mIsAsyncPrepare = false;
2158    status_t err = prepareAsync_l();
2159
2160    if (err != OK) {
2161        return err;
2162    }
2163
2164    while (mFlags & PREPARING) {
2165        mPreparedCondition.wait(mLock);
2166    }
2167
2168    return mPrepareResult;
2169}
2170
2171status_t AwesomePlayer::prepareAsync() {
2172    ATRACE_CALL();
2173    Mutex::Autolock autoLock(mLock);
2174
2175    if (mFlags & PREPARING) {
2176        return UNKNOWN_ERROR;  // async prepare already pending
2177    }
2178
2179    mIsAsyncPrepare = true;
2180    return prepareAsync_l();
2181}
2182
2183status_t AwesomePlayer::prepareAsync_l() {
2184    if (mFlags & PREPARING) {
2185        return UNKNOWN_ERROR;  // async prepare already pending
2186    }
2187
2188    if (!mQueueStarted) {
2189        mQueue.start();
2190        mQueueStarted = true;
2191    }
2192
2193    modifyFlags(PREPARING, SET);
2194    mAsyncPrepareEvent = new AwesomeEvent(
2195            this, &AwesomePlayer::onPrepareAsyncEvent);
2196
2197    mQueue.postEvent(mAsyncPrepareEvent);
2198
2199    return OK;
2200}
2201
2202status_t AwesomePlayer::finishSetDataSource_l() {
2203    ATRACE_CALL();
2204    sp<DataSource> dataSource;
2205
2206    bool isWidevineStreaming = false;
2207    if (!strncasecmp("widevine://", mUri.string(), 11)) {
2208        isWidevineStreaming = true;
2209
2210        String8 newURI = String8("http://");
2211        newURI.append(mUri.string() + 11);
2212
2213        mUri = newURI;
2214    }
2215
2216    AString sniffedMIME;
2217
2218    if (!strncasecmp("http://", mUri.string(), 7)
2219            || !strncasecmp("https://", mUri.string(), 8)
2220            || isWidevineStreaming) {
2221        mConnectingDataSource = HTTPBase::Create(
2222                (mFlags & INCOGNITO)
2223                    ? HTTPBase::kFlagIncognito
2224                    : 0);
2225
2226        if (mUIDValid) {
2227            mConnectingDataSource->setUID(mUID);
2228        }
2229
2230        String8 cacheConfig;
2231        bool disconnectAtHighwatermark;
2232        NuCachedSource2::RemoveCacheSpecificHeaders(
2233                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
2234
2235        mLock.unlock();
2236        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
2237        mLock.lock();
2238
2239        if (err != OK) {
2240            mConnectingDataSource.clear();
2241
2242            ALOGI("mConnectingDataSource->connect() returned %d", err);
2243            return err;
2244        }
2245
2246        if (!isWidevineStreaming) {
2247            // The widevine extractor does its own caching.
2248
2249#if 0
2250            mCachedSource = new NuCachedSource2(
2251                    new ThrottledSource(
2252                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
2253#else
2254            mCachedSource = new NuCachedSource2(
2255                    mConnectingDataSource,
2256                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
2257                    disconnectAtHighwatermark);
2258#endif
2259
2260            dataSource = mCachedSource;
2261        } else {
2262            dataSource = mConnectingDataSource;
2263        }
2264
2265        mConnectingDataSource.clear();
2266
2267        String8 contentType = dataSource->getMIMEType();
2268
2269        if (strncasecmp(contentType.string(), "audio/", 6)) {
2270            // We're not doing this for streams that appear to be audio-only
2271            // streams to ensure that even low bandwidth streams start
2272            // playing back fairly instantly.
2273
2274            // We're going to prefill the cache before trying to instantiate
2275            // the extractor below, as the latter is an operation that otherwise
2276            // could block on the datasource for a significant amount of time.
2277            // During that time we'd be unable to abort the preparation phase
2278            // without this prefill.
2279            if (mCachedSource != NULL) {
2280                // We're going to prefill the cache before trying to instantiate
2281                // the extractor below, as the latter is an operation that otherwise
2282                // could block on the datasource for a significant amount of time.
2283                // During that time we'd be unable to abort the preparation phase
2284                // without this prefill.
2285
2286                mLock.unlock();
2287
2288                // Initially make sure we have at least 192 KB for the sniff
2289                // to complete without blocking.
2290                static const size_t kMinBytesForSniffing = 192 * 1024;
2291
2292                off64_t metaDataSize = -1ll;
2293                for (;;) {
2294                    status_t finalStatus;
2295                    size_t cachedDataRemaining =
2296                        mCachedSource->approxDataRemaining(&finalStatus);
2297
2298                    if (finalStatus != OK
2299                            || (metaDataSize >= 0
2300                                && cachedDataRemaining >= metaDataSize)
2301                            || (mFlags & PREPARE_CANCELLED)) {
2302                        break;
2303                    }
2304
2305                    ALOGV("now cached %d bytes of data", cachedDataRemaining);
2306
2307                    if (metaDataSize < 0
2308                            && cachedDataRemaining >= kMinBytesForSniffing) {
2309                        String8 tmp;
2310                        float confidence;
2311                        sp<AMessage> meta;
2312                        if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2313                            mLock.lock();
2314                            return UNKNOWN_ERROR;
2315                        }
2316
2317                        // We successfully identified the file's extractor to
2318                        // be, remember this mime type so we don't have to
2319                        // sniff it again when we call MediaExtractor::Create()
2320                        // below.
2321                        sniffedMIME = tmp.string();
2322
2323                        if (meta == NULL
2324                                || !meta->findInt64("meta-data-size",
2325                                     reinterpret_cast<int64_t*>(&metaDataSize))) {
2326                            metaDataSize = kHighWaterMarkBytes;
2327                        }
2328
2329                        CHECK_GE(metaDataSize, 0ll);
2330                        ALOGV("metaDataSize = %lld bytes", metaDataSize);
2331                    }
2332
2333                    usleep(200000);
2334                }
2335
2336                mLock.lock();
2337            }
2338
2339            if (mFlags & PREPARE_CANCELLED) {
2340                ALOGI("Prepare cancelled while waiting for initial cache fill.");
2341                return UNKNOWN_ERROR;
2342            }
2343        }
2344    } else {
2345        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2346    }
2347
2348    if (dataSource == NULL) {
2349        return UNKNOWN_ERROR;
2350    }
2351
2352    sp<MediaExtractor> extractor;
2353
2354    if (isWidevineStreaming) {
2355        String8 mimeType;
2356        float confidence;
2357        sp<AMessage> dummy;
2358        bool success;
2359
2360        // SniffWVM is potentially blocking since it may require network access.
2361        // Do not call it with mLock held.
2362        mLock.unlock();
2363        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
2364        mLock.lock();
2365
2366        if (!success
2367                || strcasecmp(
2368                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2369            return ERROR_UNSUPPORTED;
2370        }
2371
2372        mWVMExtractor = new WVMExtractor(dataSource);
2373        mWVMExtractor->setAdaptiveStreamingMode(true);
2374        if (mUIDValid)
2375            mWVMExtractor->setUID(mUID);
2376        extractor = mWVMExtractor;
2377    } else {
2378        extractor = MediaExtractor::Create(
2379                dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
2380
2381        if (extractor == NULL) {
2382            return UNKNOWN_ERROR;
2383        }
2384    }
2385
2386    if (extractor->getDrmFlag()) {
2387        checkDrmStatus(dataSource);
2388    }
2389
2390    status_t err = setDataSource_l(extractor);
2391
2392    if (err != OK) {
2393        mWVMExtractor.clear();
2394
2395        return err;
2396    }
2397
2398    return OK;
2399}
2400
2401void AwesomePlayer::abortPrepare(status_t err) {
2402    CHECK(err != OK);
2403
2404    if (mIsAsyncPrepare) {
2405        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2406    }
2407
2408    mPrepareResult = err;
2409    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2410    mAsyncPrepareEvent = NULL;
2411    mPreparedCondition.broadcast();
2412    mAudioTearDown = false;
2413}
2414
2415// static
2416bool AwesomePlayer::ContinuePreparation(void *cookie) {
2417    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2418
2419    return (me->mFlags & PREPARE_CANCELLED) == 0;
2420}
2421
2422void AwesomePlayer::onPrepareAsyncEvent() {
2423    Mutex::Autolock autoLock(mLock);
2424    beginPrepareAsync_l();
2425}
2426
2427void AwesomePlayer::beginPrepareAsync_l() {
2428    if (mFlags & PREPARE_CANCELLED) {
2429        ALOGI("prepare was cancelled before doing anything");
2430        abortPrepare(UNKNOWN_ERROR);
2431        return;
2432    }
2433
2434    if (mUri.size() > 0) {
2435        status_t err = finishSetDataSource_l();
2436
2437        if (err != OK) {
2438            abortPrepare(err);
2439            return;
2440        }
2441    }
2442
2443    if (mVideoTrack != NULL && mVideoSource == NULL) {
2444        status_t err = initVideoDecoder();
2445
2446        if (err != OK) {
2447            abortPrepare(err);
2448            return;
2449        }
2450    }
2451
2452    if (mAudioTrack != NULL && mAudioSource == NULL) {
2453        status_t err = initAudioDecoder();
2454
2455        if (err != OK) {
2456            abortPrepare(err);
2457            return;
2458        }
2459    }
2460
2461    modifyFlags(PREPARING_CONNECTED, SET);
2462
2463    if (isStreamingHTTP()) {
2464        postBufferingEvent_l();
2465    } else {
2466        finishAsyncPrepare_l();
2467    }
2468}
2469
2470void AwesomePlayer::finishAsyncPrepare_l() {
2471    if (mIsAsyncPrepare) {
2472        if (mVideoSource == NULL) {
2473            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2474        } else {
2475            notifyVideoSize_l();
2476        }
2477
2478        notifyListener_l(MEDIA_PREPARED);
2479    }
2480
2481    mPrepareResult = OK;
2482    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2483    modifyFlags(PREPARED, SET);
2484    mAsyncPrepareEvent = NULL;
2485    mPreparedCondition.broadcast();
2486
2487    if (mAudioTearDown) {
2488        if (mPrepareResult == OK) {
2489            if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
2490                seekTo_l(mAudioTearDownPosition);
2491            }
2492
2493            if (mAudioTearDownWasPlaying) {
2494                modifyFlags(CACHE_UNDERRUN, CLEAR);
2495                play_l();
2496            }
2497        }
2498        mAudioTearDown = false;
2499    }
2500}
2501
2502uint32_t AwesomePlayer::flags() const {
2503    return mExtractorFlags;
2504}
2505
2506void AwesomePlayer::postAudioEOS(int64_t delayUs) {
2507    postCheckAudioStatusEvent(delayUs);
2508}
2509
2510void AwesomePlayer::postAudioSeekComplete() {
2511    postCheckAudioStatusEvent(0);
2512}
2513
2514void AwesomePlayer::postAudioTearDown() {
2515    postAudioTearDownEvent(0);
2516}
2517
2518status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
2519    switch (key) {
2520        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2521        {
2522            return setCacheStatCollectFreq(request);
2523        }
2524        case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
2525        {
2526            if (mAudioPlayer != NULL) {
2527                return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
2528            } else {
2529                return NO_INIT;
2530            }
2531        }
2532        default:
2533        {
2534            return ERROR_UNSUPPORTED;
2535        }
2536    }
2537}
2538
2539status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2540    if (mCachedSource != NULL) {
2541        int32_t freqMs = request.readInt32();
2542        ALOGD("Request to keep cache stats in the past %d ms",
2543            freqMs);
2544        return mCachedSource->setCacheStatCollectFreq(freqMs);
2545    }
2546    return ERROR_UNSUPPORTED;
2547}
2548
2549status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
2550    switch (key) {
2551    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2552        {
2553            int32_t channelCount;
2554            if (mAudioTrack == 0 ||
2555                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2556                channelCount = 0;
2557            }
2558            reply->writeInt32(channelCount);
2559        }
2560        return OK;
2561    default:
2562        {
2563            return ERROR_UNSUPPORTED;
2564        }
2565    }
2566}
2567
2568status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
2569    Mutex::Autolock autoLock(mLock);
2570    size_t trackCount = mExtractor->countTracks();
2571    if (mTextDriver != NULL) {
2572        trackCount += mTextDriver->countExternalTracks();
2573    }
2574
2575    reply->writeInt32(trackCount);
2576    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
2577        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2578
2579        const char *_mime;
2580        CHECK(meta->findCString(kKeyMIMEType, &_mime));
2581
2582        String8 mime = String8(_mime);
2583
2584        reply->writeInt32(2); // 2 fields
2585
2586        if (!strncasecmp(mime.string(), "video/", 6)) {
2587            reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
2588        } else if (!strncasecmp(mime.string(), "audio/", 6)) {
2589            reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
2590        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
2591            reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
2592        } else {
2593            reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
2594        }
2595
2596        const char *lang;
2597        if (!meta->findCString(kKeyMediaLanguage, &lang)) {
2598            lang = "und";
2599        }
2600        reply->writeString16(String16(lang));
2601    }
2602
2603    if (mTextDriver != NULL) {
2604        mTextDriver->getExternalTrackInfo(reply);
2605    }
2606    return OK;
2607}
2608
2609status_t AwesomePlayer::selectAudioTrack_l(
2610        const sp<MediaSource>& source, size_t trackIndex) {
2611
2612    ALOGI("selectAudioTrack_l: trackIndex=%zu, mFlags=0x%x", trackIndex, mFlags);
2613
2614    {
2615        Mutex::Autolock autoLock(mStatsLock);
2616        if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
2617            ALOGI("Track %zu is active. Does nothing.", trackIndex);
2618            return OK;
2619        }
2620        //mStats.mFlags = mFlags;
2621    }
2622
2623    if (mSeeking != NO_SEEK) {
2624        ALOGE("Selecting a track while seeking is not supported");
2625        return ERROR_UNSUPPORTED;
2626    }
2627
2628    if ((mFlags & PREPARED) == 0) {
2629        ALOGE("Data source has not finished preparation");
2630        return ERROR_UNSUPPORTED;
2631    }
2632
2633    CHECK(source != NULL);
2634    bool wasPlaying = (mFlags & PLAYING) != 0;
2635
2636    pause_l();
2637
2638    int64_t curTimeUs;
2639    CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
2640
2641    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
2642            && mAudioSource != NULL) {
2643        // If we had an audio player, it would have effectively
2644        // taken possession of the audio source and stopped it when
2645        // _it_ is stopped. Otherwise this is still our responsibility.
2646        mAudioSource->stop();
2647    }
2648    mAudioSource.clear();
2649    mOmxSource.clear();
2650
2651    mTimeSource = NULL;
2652
2653    delete mAudioPlayer;
2654    mAudioPlayer = NULL;
2655
2656    modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
2657
2658    setAudioSource(source);
2659
2660    modifyFlags(AUDIO_AT_EOS, CLEAR);
2661    modifyFlags(AT_EOS, CLEAR);
2662
2663    status_t err;
2664    if ((err = initAudioDecoder()) != OK) {
2665        ALOGE("Failed to init audio decoder: 0x%x", err);
2666        return err;
2667    }
2668
2669    mSeekNotificationSent = true;
2670    seekTo_l(curTimeUs);
2671
2672    if (wasPlaying) {
2673        play_l();
2674    }
2675
2676    mActiveAudioTrackIndex = trackIndex;
2677
2678    return OK;
2679}
2680
2681status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
2682    ATRACE_CALL();
2683    ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
2684    Mutex::Autolock autoLock(mLock);
2685    size_t trackCount = mExtractor->countTracks();
2686    if (mTextDriver != NULL) {
2687        trackCount += mTextDriver->countExternalTracks();
2688    }
2689    if (trackIndex >= trackCount) {
2690        ALOGE("Track index (%zu) is out of range [0, %zu)", trackIndex, trackCount);
2691        return ERROR_OUT_OF_RANGE;
2692    }
2693
2694    bool isAudioTrack = false;
2695    if (trackIndex < mExtractor->countTracks()) {
2696        sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
2697        const char *mime;
2698        CHECK(meta->findCString(kKeyMIMEType, &mime));
2699        isAudioTrack = !strncasecmp(mime, "audio/", 6);
2700
2701        if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) {
2702            ALOGE("Track %zu is not either audio or timed text", trackIndex);
2703            return ERROR_UNSUPPORTED;
2704        }
2705    }
2706
2707    if (isAudioTrack) {
2708        if (!select) {
2709            ALOGE("Deselect an audio track (%zu) is not supported", trackIndex);
2710            return ERROR_UNSUPPORTED;
2711        }
2712        return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
2713    }
2714
2715    // Timed text track handling
2716    if (mTextDriver == NULL) {
2717        return INVALID_OPERATION;
2718    }
2719
2720    status_t err = OK;
2721    if (select) {
2722        err = mTextDriver->selectTrack(trackIndex);
2723        if (err == OK) {
2724            modifyFlags(TEXTPLAYER_INITIALIZED, SET);
2725            if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
2726                mTextDriver->start();
2727                modifyFlags(TEXT_RUNNING, SET);
2728            }
2729        }
2730    } else {
2731        err = mTextDriver->unselectTrack(trackIndex);
2732        if (err == OK) {
2733            modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
2734            modifyFlags(TEXT_RUNNING, CLEAR);
2735        }
2736    }
2737    return err;
2738}
2739
2740size_t AwesomePlayer::countTracks() const {
2741    return mExtractor->countTracks() + mTextDriver->countExternalTracks();
2742}
2743
2744status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
2745    Mutex::Autolock lock(mLock);
2746    return setVideoScalingMode_l(mode);
2747}
2748
2749status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
2750    mVideoScalingMode = mode;
2751    if (mNativeWindow != NULL) {
2752        status_t err = native_window_set_scaling_mode(
2753                mNativeWindow.get(), mVideoScalingMode);
2754        if (err != OK) {
2755            ALOGW("Failed to set scaling mode: %d", err);
2756        }
2757        return err;
2758    }
2759    return OK;
2760}
2761
2762status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
2763    ATRACE_CALL();
2764    if (NULL == reply) {
2765        return android::BAD_VALUE;
2766    }
2767    int32_t methodId;
2768    status_t ret = request.readInt32(&methodId);
2769    if (ret != android::OK) {
2770        return ret;
2771    }
2772    switch(methodId) {
2773        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
2774        {
2775            int mode = request.readInt32();
2776            return setVideoScalingMode(mode);
2777        }
2778
2779        case INVOKE_ID_GET_TRACK_INFO:
2780        {
2781            return getTrackInfo(reply);
2782        }
2783        case INVOKE_ID_ADD_EXTERNAL_SOURCE:
2784        {
2785            Mutex::Autolock autoLock(mLock);
2786            if (mTextDriver == NULL) {
2787                mTextDriver = new TimedTextDriver(mListener);
2788            }
2789            // String values written in Parcel are UTF-16 values.
2790            String8 uri(request.readString16());
2791            String8 mimeType(request.readString16());
2792            size_t nTracks = countTracks();
2793            return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
2794        }
2795        case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
2796        {
2797            Mutex::Autolock autoLock(mLock);
2798            if (mTextDriver == NULL) {
2799                mTextDriver = new TimedTextDriver(mListener);
2800            }
2801            int fd         = request.readFileDescriptor();
2802            off64_t offset = request.readInt64();
2803            off64_t length  = request.readInt64();
2804            String8 mimeType(request.readString16());
2805            size_t nTracks = countTracks();
2806            return mTextDriver->addOutOfBandTextSource(
2807                    nTracks, fd, offset, length, mimeType);
2808        }
2809        case INVOKE_ID_SELECT_TRACK:
2810        {
2811            int trackIndex = request.readInt32();
2812            return selectTrack(trackIndex, true /* select */);
2813        }
2814        case INVOKE_ID_UNSELECT_TRACK:
2815        {
2816            int trackIndex = request.readInt32();
2817            return selectTrack(trackIndex, false /* select */);
2818        }
2819        default:
2820        {
2821            return ERROR_UNSUPPORTED;
2822        }
2823    }
2824    // It will not reach here.
2825    return OK;
2826}
2827
2828bool AwesomePlayer::isStreamingHTTP() const {
2829    return mCachedSource != NULL || mWVMExtractor != NULL;
2830}
2831
2832status_t AwesomePlayer::dump(
2833        int fd, const Vector<String16> & /* args */) const {
2834    Mutex::Autolock autoLock(mStatsLock);
2835
2836    FILE *out = fdopen(dup(fd), "w");
2837
2838    fprintf(out, " AwesomePlayer\n");
2839    if (mStats.mFd < 0) {
2840        fprintf(out, "  URI(suppressed)");
2841    } else {
2842        fprintf(out, "  fd(%d)", mStats.mFd);
2843    }
2844
2845    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2846
2847    if (mStats.mBitrate >= 0) {
2848        fprintf(out, ", bitrate(%" PRId64 " bps)", mStats.mBitrate);
2849    }
2850
2851    fprintf(out, "\n");
2852
2853    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2854        const TrackStat &stat = mStats.mTracks.itemAt(i);
2855
2856        fprintf(out, "  Track %zu\n", i + 1);
2857        fprintf(out, "   MIME(%s)", stat.mMIME.string());
2858
2859        if (!stat.mDecoderName.isEmpty()) {
2860            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2861        }
2862
2863        fprintf(out, "\n");
2864
2865        if ((ssize_t)i == mStats.mVideoTrackIndex) {
2866            fprintf(out,
2867                    "   videoDimensions(%d x %d), "
2868                    "numVideoFramesDecoded(%" PRId64 "), "
2869                    "numVideoFramesDropped(%" PRId64 ")\n",
2870                    mStats.mVideoWidth,
2871                    mStats.mVideoHeight,
2872                    mStats.mNumVideoFramesDecoded,
2873                    mStats.mNumVideoFramesDropped);
2874        }
2875    }
2876
2877    fclose(out);
2878    out = NULL;
2879
2880    return OK;
2881}
2882
2883void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2884    switch (mode) {
2885        case SET:
2886            mFlags |= value;
2887            break;
2888        case CLEAR:
2889            if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) {
2890                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
2891            }
2892            mFlags &= ~value;
2893            break;
2894        case ASSIGN:
2895            mFlags = value;
2896            break;
2897        default:
2898            TRESPASS();
2899    }
2900
2901    {
2902        Mutex::Autolock autoLock(mStatsLock);
2903        mStats.mFlags = mFlags;
2904    }
2905}
2906
2907void AwesomePlayer::onAudioTearDownEvent() {
2908
2909    Mutex::Autolock autoLock(mLock);
2910    if (!mAudioTearDownEventPending) {
2911        return;
2912    }
2913    mAudioTearDownEventPending = false;
2914
2915    ALOGV("onAudioTearDownEvent");
2916
2917    // stream info is cleared by reset_l() so copy what we need
2918    mAudioTearDownWasPlaying = (mFlags & PLAYING);
2919    KeyedVector<String8, String8> uriHeaders(mUriHeaders);
2920    sp<DataSource> fileSource(mFileSource);
2921
2922    mStatsLock.lock();
2923    String8 uri(mStats.mURI);
2924    mStatsLock.unlock();
2925
2926    // get current position so we can start recreated stream from here
2927    getPosition(&mAudioTearDownPosition);
2928
2929    // Reset and recreate
2930    reset_l();
2931
2932    status_t err;
2933
2934    if (fileSource != NULL) {
2935        mFileSource = fileSource;
2936        err = setDataSource_l(fileSource);
2937    } else {
2938        err = setDataSource_l(uri, &uriHeaders);
2939    }
2940
2941    mFlags |= PREPARING;
2942    if ( err != OK ) {
2943        // This will force beingPrepareAsync_l() to notify
2944        // a MEDIA_ERROR to the client and abort the prepare
2945        mFlags |= PREPARE_CANCELLED;
2946    }
2947
2948    mAudioTearDown = true;
2949    mIsAsyncPrepare = true;
2950
2951    // Call prepare for the host decoding
2952    beginPrepareAsync_l();
2953}
2954
2955}  // namespace android
2956