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