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