AwesomePlayer.cpp revision 56477eb724972c2fe0441dfa7baaad00b7927add
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        // Hardware decoders avoid the CPU color conversion by decoding
1207        // directly to ANativeBuffers, so we must use a renderer that
1208        // just pushes those buffers to the ANativeWindow.
1209        mVideoRenderer =
1210            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
1211    } else {
1212        // Other decoders are instantiated locally and as a consequence
1213        // allocate their buffers in local address space.  This renderer
1214        // then performs a color conversion and copy to get the data
1215        // into the ANativeBuffer.
1216        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
1217    }
1218}
1219
1220status_t AwesomePlayer::pause() {
1221    ATRACE_CALL();
1222
1223    Mutex::Autolock autoLock(mLock);
1224
1225    modifyFlags(CACHE_UNDERRUN, CLEAR);
1226
1227    return pause_l();
1228}
1229
1230status_t AwesomePlayer::pause_l(bool at_eos) {
1231    if (!(mFlags & PLAYING)) {
1232        if (mAudioTearDown && mAudioTearDownWasPlaying) {
1233            ALOGV("pause_l() during teardown and finishSetDataSource_l() mFlags %x" , mFlags);
1234            mAudioTearDownWasPlaying = false;
1235            notifyListener_l(MEDIA_PAUSED);
1236            mMediaRenderingStartGeneration = ++mStartGeneration;
1237        }
1238        return OK;
1239    }
1240
1241    notifyListener_l(MEDIA_PAUSED);
1242    mMediaRenderingStartGeneration = ++mStartGeneration;
1243
1244    cancelPlayerEvents(true /* keepNotifications */);
1245
1246    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1247        // If we played the audio stream to completion we
1248        // want to make sure that all samples remaining in the audio
1249        // track's queue are played out.
1250        mAudioPlayer->pause(at_eos /* playPendingSamples */);
1251        // send us a reminder to tear down the AudioPlayer if paused for too long.
1252        if (mOffloadAudio) {
1253            postAudioTearDownEvent(kOffloadPauseMaxUs);
1254        }
1255        modifyFlags(AUDIO_RUNNING, CLEAR);
1256    }
1257
1258    if (mFlags & TEXTPLAYER_INITIALIZED) {
1259        mTextDriver->pause();
1260        modifyFlags(TEXT_RUNNING, CLEAR);
1261    }
1262
1263    modifyFlags(PLAYING, CLEAR);
1264
1265    if (mDecryptHandle != NULL) {
1266        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1267                Playback::PAUSE, 0);
1268    }
1269
1270    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1271    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1272        params |= IMediaPlayerService::kBatteryDataTrackAudio;
1273    }
1274    if (mVideoSource != NULL) {
1275        params |= IMediaPlayerService::kBatteryDataTrackVideo;
1276    }
1277
1278    addBatteryData(params);
1279
1280    return OK;
1281}
1282
1283bool AwesomePlayer::isPlaying() const {
1284    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1285}
1286
1287status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) {
1288    Mutex::Autolock autoLock(mLock);
1289
1290    status_t err;
1291    if (bufferProducer != NULL) {
1292        err = setNativeWindow_l(new Surface(bufferProducer));
1293    } else {
1294        err = setNativeWindow_l(NULL);
1295    }
1296
1297    return err;
1298}
1299
1300void AwesomePlayer::shutdownVideoDecoder_l() {
1301    if (mVideoBuffer) {
1302        mVideoBuffer->release();
1303        mVideoBuffer = NULL;
1304    }
1305
1306    mVideoSource->stop();
1307
1308    // The following hack is necessary to ensure that the OMX
1309    // component is completely released by the time we may try
1310    // to instantiate it again.
1311    wp<MediaSource> tmp = mVideoSource;
1312    mVideoSource.clear();
1313    while (tmp.promote() != NULL) {
1314        usleep(1000);
1315    }
1316    IPCThreadState::self()->flushCommands();
1317    ALOGV("video decoder shutdown completed");
1318}
1319
1320status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1321    mNativeWindow = native;
1322
1323    if (mVideoSource == NULL) {
1324        return OK;
1325    }
1326
1327    ALOGV("attempting to reconfigure to use new surface");
1328
1329    bool wasPlaying = (mFlags & PLAYING) != 0;
1330
1331    pause_l();
1332    mVideoRenderer.clear();
1333
1334    shutdownVideoDecoder_l();
1335
1336    status_t err = initVideoDecoder();
1337
1338    if (err != OK) {
1339        ALOGE("failed to reinstantiate video decoder after surface change.");
1340        return err;
1341    }
1342
1343    if (mLastVideoTimeUs >= 0) {
1344        mSeeking = SEEK;
1345        mSeekTimeUs = mLastVideoTimeUs;
1346        modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1347    }
1348
1349    if (wasPlaying) {
1350        play_l();
1351    }
1352
1353    return OK;
1354}
1355
1356void AwesomePlayer::setAudioSink(
1357        const sp<MediaPlayerBase::AudioSink> &audioSink) {
1358    Mutex::Autolock autoLock(mLock);
1359
1360    mAudioSink = audioSink;
1361}
1362
1363status_t AwesomePlayer::setLooping(bool shouldLoop) {
1364    Mutex::Autolock autoLock(mLock);
1365
1366    modifyFlags(LOOPING, CLEAR);
1367
1368    if (shouldLoop) {
1369        modifyFlags(LOOPING, SET);
1370    }
1371
1372    return OK;
1373}
1374
1375status_t AwesomePlayer::getDuration(int64_t *durationUs) {
1376    Mutex::Autolock autoLock(mMiscStateLock);
1377
1378    if (mDurationUs < 0) {
1379        return UNKNOWN_ERROR;
1380    }
1381
1382    *durationUs = mDurationUs;
1383
1384    return OK;
1385}
1386
1387status_t AwesomePlayer::getPosition(int64_t *positionUs) {
1388    if (mSeeking != NO_SEEK) {
1389        *positionUs = mSeekTimeUs;
1390    } else if (mVideoSource != NULL
1391            && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1392        Mutex::Autolock autoLock(mMiscStateLock);
1393        *positionUs = mVideoTimeUs;
1394    } else if (mAudioPlayer != NULL) {
1395        *positionUs = mAudioPlayer->getMediaTimeUs();
1396    } else {
1397        *positionUs = 0;
1398    }
1399    return OK;
1400}
1401
1402status_t AwesomePlayer::seekTo(int64_t timeUs) {
1403    ATRACE_CALL();
1404
1405    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
1406        Mutex::Autolock autoLock(mLock);
1407        return seekTo_l(timeUs);
1408    }
1409
1410    return OK;
1411}
1412
1413status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
1414    if (mFlags & CACHE_UNDERRUN) {
1415        modifyFlags(CACHE_UNDERRUN, CLEAR);
1416        play_l();
1417    }
1418
1419    if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1420        // Video playback completed before, there's no pending
1421        // video event right now. In order for this new seek
1422        // to be honored, we need to post one.
1423
1424        postVideoEvent_l();
1425    }
1426
1427    mSeeking = SEEK;
1428    mSeekNotificationSent = false;
1429    mSeekTimeUs = timeUs;
1430    modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1431
1432    if (mFlags & PLAYING) {
1433        notifyListener_l(MEDIA_PAUSED);
1434        mMediaRenderingStartGeneration = ++mStartGeneration;
1435    }
1436
1437    seekAudioIfNecessary_l();
1438
1439    if (mFlags & TEXTPLAYER_INITIALIZED) {
1440        mTextDriver->seekToAsync(mSeekTimeUs);
1441    }
1442
1443    if (!(mFlags & PLAYING)) {
1444        ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
1445             " immediately.");
1446
1447        notifyListener_l(MEDIA_SEEK_COMPLETE);
1448        mSeekNotificationSent = true;
1449
1450        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1451            modifyFlags(SEEK_PREVIEW, SET);
1452            postVideoEvent_l();
1453        }
1454    }
1455
1456    return OK;
1457}
1458
1459void AwesomePlayer::seekAudioIfNecessary_l() {
1460    if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1461        mAudioPlayer->seekTo(mSeekTimeUs);
1462
1463        mWatchForAudioSeekComplete = true;
1464        mWatchForAudioEOS = true;
1465
1466        if (mDecryptHandle != NULL) {
1467            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1468                    Playback::PAUSE, 0);
1469            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1470                    Playback::START, mSeekTimeUs / 1000);
1471        }
1472    }
1473}
1474
1475void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1476    CHECK(source != NULL);
1477
1478    mAudioTrack = source;
1479}
1480
1481void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) {
1482    CHECK(source != NULL);
1483
1484    if (mTextDriver == NULL) {
1485        mTextDriver = new TimedTextDriver(mListener);
1486    }
1487
1488    mTextDriver->addInBandTextSource(trackIndex, source);
1489}
1490
1491status_t AwesomePlayer::initAudioDecoder() {
1492    ATRACE_CALL();
1493
1494    sp<MetaData> meta = mAudioTrack->getFormat();
1495
1496    const char *mime;
1497    CHECK(meta->findCString(kKeyMIMEType, &mime));
1498    // Check whether there is a hardware codec for this stream
1499    // This doesn't guarantee that the hardware has a free stream
1500    // but it avoids us attempting to open (and re-open) an offload
1501    // stream to hardware that doesn't have the necessary codec
1502    mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), isStreamingHTTP());
1503
1504    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1505        ALOGV("createAudioPlayer: bypass OMX (raw)");
1506        mAudioSource = mAudioTrack;
1507    } else {
1508        // If offloading we still create a OMX decoder as a fall-back
1509        // but we don't start it
1510        mOmxSource = OMXCodec::Create(
1511                mClient.interface(), mAudioTrack->getFormat(),
1512                false, // createEncoder
1513                mAudioTrack);
1514
1515        if (mOffloadAudio) {
1516            ALOGV("createAudioPlayer: bypass OMX (offload)");
1517            mAudioSource = mAudioTrack;
1518        } else {
1519            mAudioSource = mOmxSource;
1520        }
1521    }
1522
1523    if (mAudioSource != NULL) {
1524        int64_t durationUs;
1525        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1526            Mutex::Autolock autoLock(mMiscStateLock);
1527            if (mDurationUs < 0 || durationUs > mDurationUs) {
1528                mDurationUs = durationUs;
1529            }
1530        }
1531
1532        status_t err = mAudioSource->start();
1533
1534        if (err != OK) {
1535            mAudioSource.clear();
1536            mOmxSource.clear();
1537            return err;
1538        }
1539    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1540        // For legacy reasons we're simply going to ignore the absence
1541        // of an audio decoder for QCELP instead of aborting playback
1542        // altogether.
1543        return OK;
1544    }
1545
1546    if (mAudioSource != NULL) {
1547        Mutex::Autolock autoLock(mStatsLock);
1548        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
1549        const char *component;
1550        if (!mAudioSource->getFormat()
1551                ->findCString(kKeyDecoderComponent, &component)) {
1552            component = "none";
1553        }
1554
1555        stat->mDecoderName = component;
1556    }
1557
1558    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1559}
1560
1561void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1562    CHECK(source != NULL);
1563
1564    mVideoTrack = source;
1565}
1566
1567status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1568    ATRACE_CALL();
1569
1570    // Either the application or the DRM system can independently say
1571    // that there must be a hardware-protected path to an external video sink.
1572    // For now we always require a hardware-protected path to external video sink
1573    // if content is DRMed, but eventually this could be optional per DRM agent.
1574    // When the application wants protection, then
1575    //   (USE_SURFACE_ALLOC && (mSurface != 0) &&
1576    //   (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1577    // will be true, but that part is already handled by SurfaceFlinger.
1578
1579#ifdef DEBUG_HDCP
1580    // For debugging, we allow a system property to control the protected usage.
1581    // In case of uninitialized or unexpected property, we default to "DRM only".
1582    bool setProtectionBit = false;
1583    char value[PROPERTY_VALUE_MAX];
1584    if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1585        if (!strcmp(value, "never")) {
1586            // nop
1587        } else if (!strcmp(value, "always")) {
1588            setProtectionBit = true;
1589        } else if (!strcmp(value, "drm-only")) {
1590            if (mDecryptHandle != NULL) {
1591                setProtectionBit = true;
1592            }
1593        // property value is empty, or unexpected value
1594        } else {
1595            if (mDecryptHandle != NULL) {
1596                setProtectionBit = true;
1597            }
1598        }
1599    // can' read property value
1600    } else {
1601        if (mDecryptHandle != NULL) {
1602            setProtectionBit = true;
1603        }
1604    }
1605    // note that usage bit is already cleared, so no need to clear it in the "else" case
1606    if (setProtectionBit) {
1607        flags |= OMXCodec::kEnableGrallocUsageProtected;
1608    }
1609#else
1610    if (mDecryptHandle != NULL) {
1611        flags |= OMXCodec::kEnableGrallocUsageProtected;
1612    }
1613#endif
1614    ALOGV("initVideoDecoder flags=0x%x", flags);
1615    mVideoSource = OMXCodec::Create(
1616            mClient.interface(), mVideoTrack->getFormat(),
1617            false, // createEncoder
1618            mVideoTrack,
1619            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
1620
1621    if (mVideoSource != NULL) {
1622        int64_t durationUs;
1623        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1624            Mutex::Autolock autoLock(mMiscStateLock);
1625            if (mDurationUs < 0 || durationUs > mDurationUs) {
1626                mDurationUs = durationUs;
1627            }
1628        }
1629
1630        status_t err = mVideoSource->start();
1631
1632        if (err != OK) {
1633            ALOGE("failed to start video source");
1634            mVideoSource.clear();
1635            return err;
1636        }
1637    }
1638
1639    if (mVideoSource != NULL) {
1640        const char *componentName;
1641        CHECK(mVideoSource->getFormat()
1642                ->findCString(kKeyDecoderComponent, &componentName));
1643
1644        {
1645            Mutex::Autolock autoLock(mStatsLock);
1646            TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1647
1648            stat->mDecoderName = componentName;
1649        }
1650
1651        static const char *kPrefix = "OMX.Nvidia.";
1652        static const char *kSuffix = ".decode";
1653        static const size_t kSuffixLength = strlen(kSuffix);
1654
1655        size_t componentNameLength = strlen(componentName);
1656
1657        if (!strncmp(componentName, kPrefix, strlen(kPrefix))
1658                && componentNameLength >= kSuffixLength
1659                && !strcmp(&componentName[
1660                    componentNameLength - kSuffixLength], kSuffix)) {
1661            modifyFlags(SLOW_DECODER_HACK, SET);
1662        }
1663    }
1664
1665    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1666}
1667
1668void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1669    ATRACE_CALL();
1670
1671    if (mSeeking == SEEK_VIDEO_ONLY) {
1672        mSeeking = NO_SEEK;
1673        return;
1674    }
1675
1676    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1677        return;
1678    }
1679
1680    // If we paused, then seeked, then resumed, it is possible that we have
1681    // signaled SEEK_COMPLETE at a copmletely different media time than where
1682    // we are now resuming.  Signal new position to media time provider.
1683    // Cannot signal another SEEK_COMPLETE, as existing clients may not expect
1684    // multiple SEEK_COMPLETE responses to a single seek() request.
1685    if (mSeekNotificationSent && abs(mSeekTimeUs - videoTimeUs) > 10000) {
1686        // notify if we are resuming more than 10ms away from desired seek time
1687        notifyListener_l(MEDIA_SKIPPED);
1688    }
1689
1690    if (mAudioPlayer != NULL) {
1691        ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1692
1693        // If we don't have a video time, seek audio to the originally
1694        // requested seek time instead.
1695
1696        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1697        mWatchForAudioSeekComplete = true;
1698        mWatchForAudioEOS = true;
1699    } else if (!mSeekNotificationSent) {
1700        // If we're playing video only, report seek complete now,
1701        // otherwise audio player will notify us later.
1702        notifyListener_l(MEDIA_SEEK_COMPLETE);
1703        mSeekNotificationSent = true;
1704    }
1705
1706    modifyFlags(FIRST_FRAME, SET);
1707    mSeeking = NO_SEEK;
1708
1709    if (mDecryptHandle != NULL) {
1710        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1711                Playback::PAUSE, 0);
1712        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1713                Playback::START, videoTimeUs / 1000);
1714    }
1715}
1716
1717void AwesomePlayer::onVideoEvent() {
1718    ATRACE_CALL();
1719    Mutex::Autolock autoLock(mLock);
1720    if (!mVideoEventPending) {
1721        // The event has been cancelled in reset_l() but had already
1722        // been scheduled for execution at that time.
1723        return;
1724    }
1725    mVideoEventPending = false;
1726
1727    if (mSeeking != NO_SEEK) {
1728        if (mVideoBuffer) {
1729            mVideoBuffer->release();
1730            mVideoBuffer = NULL;
1731        }
1732
1733        if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
1734                && !(mFlags & SEEK_PREVIEW)) {
1735            // We're going to seek the video source first, followed by
1736            // the audio source.
1737            // In order to avoid jumps in the DataSource offset caused by
1738            // the audio codec prefetching data from the old locations
1739            // while the video codec is already reading data from the new
1740            // locations, we'll "pause" the audio source, causing it to
1741            // stop reading input data until a subsequent seek.
1742
1743            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1744                mAudioPlayer->pause();
1745
1746                modifyFlags(AUDIO_RUNNING, CLEAR);
1747            }
1748            mAudioSource->pause();
1749        }
1750    }
1751
1752    if (!mVideoBuffer) {
1753        MediaSource::ReadOptions options;
1754        if (mSeeking != NO_SEEK) {
1755            ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1756
1757            options.setSeekTo(
1758                    mSeekTimeUs,
1759                    mSeeking == SEEK_VIDEO_ONLY
1760                        ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1761                        : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1762        }
1763        for (;;) {
1764            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1765            options.clearSeekTo();
1766
1767            if (err != OK) {
1768                CHECK(mVideoBuffer == NULL);
1769
1770                if (err == INFO_FORMAT_CHANGED) {
1771                    ALOGV("VideoSource signalled format change.");
1772
1773                    notifyVideoSize_l();
1774
1775                    if (mVideoRenderer != NULL) {
1776                        mVideoRendererIsPreview = false;
1777                        initRenderer_l();
1778                    }
1779                    continue;
1780                }
1781
1782                // So video playback is complete, but we may still have
1783                // a seek request pending that needs to be applied
1784                // to the audio track.
1785                if (mSeeking != NO_SEEK) {
1786                    ALOGV("video stream ended while seeking!");
1787                }
1788                finishSeekIfNecessary(-1);
1789
1790                if (mAudioPlayer != NULL
1791                        && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1792                    startAudioPlayer_l();
1793                }
1794
1795                modifyFlags(VIDEO_AT_EOS, SET);
1796                postStreamDoneEvent_l(err);
1797                return;
1798            }
1799
1800            if (mVideoBuffer->range_length() == 0) {
1801                // Some decoders, notably the PV AVC software decoder
1802                // return spurious empty buffers that we just want to ignore.
1803
1804                mVideoBuffer->release();
1805                mVideoBuffer = NULL;
1806                continue;
1807            }
1808
1809            break;
1810        }
1811
1812        {
1813            Mutex::Autolock autoLock(mStatsLock);
1814            ++mStats.mNumVideoFramesDecoded;
1815        }
1816    }
1817
1818    int64_t timeUs;
1819    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1820
1821    mLastVideoTimeUs = timeUs;
1822
1823    if (mSeeking == SEEK_VIDEO_ONLY) {
1824        if (mSeekTimeUs > timeUs) {
1825            ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1826                 mSeekTimeUs, timeUs);
1827        }
1828    }
1829
1830    {
1831        Mutex::Autolock autoLock(mMiscStateLock);
1832        mVideoTimeUs = timeUs;
1833    }
1834
1835    SeekType wasSeeking = mSeeking;
1836    finishSeekIfNecessary(timeUs);
1837
1838    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1839        status_t err = startAudioPlayer_l();
1840        if (err != OK) {
1841            ALOGE("Starting the audio player failed w/ err %d", err);
1842            return;
1843        }
1844    }
1845
1846    if ((mFlags & TEXTPLAYER_INITIALIZED)
1847            && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1848        mTextDriver->start();
1849        modifyFlags(TEXT_RUNNING, SET);
1850    }
1851
1852    TimeSource *ts =
1853        ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
1854            ? &mSystemTimeSource : mTimeSource;
1855
1856    if (mFlags & FIRST_FRAME) {
1857        modifyFlags(FIRST_FRAME, CLEAR);
1858        mSinceLastDropped = 0;
1859        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1860    }
1861
1862    int64_t realTimeUs, mediaTimeUs;
1863    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1864        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1865        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1866    }
1867
1868    if (wasSeeking == SEEK_VIDEO_ONLY) {
1869        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1870
1871        int64_t latenessUs = nowUs - timeUs;
1872
1873        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1874
1875        if (latenessUs > 0) {
1876            ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1877        }
1878    }
1879
1880    if (wasSeeking == NO_SEEK) {
1881        // Let's display the first frame after seeking right away.
1882
1883        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1884
1885        int64_t latenessUs = nowUs - timeUs;
1886
1887        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1888
1889        if (latenessUs > 500000ll
1890                && mAudioPlayer != NULL
1891                && mAudioPlayer->getMediaTimeMapping(
1892                    &realTimeUs, &mediaTimeUs)) {
1893            if (mWVMExtractor == NULL) {
1894                ALOGI("we're much too late (%.2f secs), video skipping ahead",
1895                     latenessUs / 1E6);
1896
1897                mVideoBuffer->release();
1898                mVideoBuffer = NULL;
1899
1900                mSeeking = SEEK_VIDEO_ONLY;
1901                mSeekTimeUs = mediaTimeUs;
1902
1903                postVideoEvent_l();
1904                return;
1905            } else {
1906                // The widevine extractor doesn't deal well with seeking
1907                // audio and video independently. We'll just have to wait
1908                // until the decoder catches up, which won't be long at all.
1909                ALOGI("we're very late (%.2f secs)", latenessUs / 1E6);
1910            }
1911        }
1912
1913        if (latenessUs > 40000) {
1914            // We're more than 40ms late.
1915            ALOGV("we're late by %lld us (%.2f secs)",
1916                 latenessUs, latenessUs / 1E6);
1917
1918            if (!(mFlags & SLOW_DECODER_HACK)
1919                    || mSinceLastDropped > FRAME_DROP_FREQ)
1920            {
1921                ALOGV("we're late by %lld us (%.2f secs) dropping "
1922                     "one after %d frames",
1923                     latenessUs, latenessUs / 1E6, mSinceLastDropped);
1924
1925                mSinceLastDropped = 0;
1926                mVideoBuffer->release();
1927                mVideoBuffer = NULL;
1928
1929                {
1930                    Mutex::Autolock autoLock(mStatsLock);
1931                    ++mStats.mNumVideoFramesDropped;
1932                }
1933
1934                postVideoEvent_l();
1935                return;
1936            }
1937        }
1938
1939        if (latenessUs < -10000) {
1940            // We're more than 10ms early.
1941            postVideoEvent_l(10000);
1942            return;
1943        }
1944    }
1945
1946    if ((mNativeWindow != NULL)
1947            && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
1948        mVideoRendererIsPreview = false;
1949
1950        initRenderer_l();
1951    }
1952
1953    if (mVideoRenderer != NULL) {
1954        mSinceLastDropped++;
1955        mVideoRenderer->render(mVideoBuffer);
1956        if (!mVideoRenderingStarted) {
1957            mVideoRenderingStarted = true;
1958            notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
1959        }
1960
1961        if (mFlags & PLAYING) {
1962            notifyIfMediaStarted_l();
1963        }
1964    }
1965
1966    mVideoBuffer->release();
1967    mVideoBuffer = NULL;
1968
1969    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
1970        modifyFlags(SEEK_PREVIEW, CLEAR);
1971        return;
1972    }
1973
1974    postVideoEvent_l();
1975}
1976
1977void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1978    ATRACE_CALL();
1979
1980    if (mVideoEventPending) {
1981        return;
1982    }
1983
1984    mVideoEventPending = true;
1985    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1986}
1987
1988void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1989    if (mStreamDoneEventPending) {
1990        return;
1991    }
1992    mStreamDoneEventPending = true;
1993
1994    mStreamDoneStatus = status;
1995    mQueue.postEvent(mStreamDoneEvent);
1996}
1997
1998void AwesomePlayer::postBufferingEvent_l() {
1999    if (mBufferingEventPending) {
2000        return;
2001    }
2002    mBufferingEventPending = true;
2003    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
2004}
2005
2006void AwesomePlayer::postVideoLagEvent_l() {
2007    if (mVideoLagEventPending) {
2008        return;
2009    }
2010    mVideoLagEventPending = true;
2011    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
2012}
2013
2014void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
2015    Mutex::Autolock autoLock(mAudioLock);
2016    if (mAudioStatusEventPending) {
2017        return;
2018    }
2019    mAudioStatusEventPending = true;
2020    // Do not honor delay when looping in order to limit audio gap
2021    if (mFlags & (LOOPING | AUTO_LOOPING)) {
2022        delayUs = 0;
2023    }
2024    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
2025}
2026
2027void AwesomePlayer::postAudioTearDownEvent(int64_t delayUs) {
2028    Mutex::Autolock autoLock(mAudioLock);
2029    if (mAudioTearDownEventPending) {
2030        return;
2031    }
2032    mAudioTearDownEventPending = true;
2033    mQueue.postEventWithDelay(mAudioTearDownEvent, delayUs);
2034}
2035
2036void AwesomePlayer::onCheckAudioStatus() {
2037    {
2038        Mutex::Autolock autoLock(mAudioLock);
2039        if (!mAudioStatusEventPending) {
2040            // Event was dispatched and while we were blocking on the mutex,
2041            // has already been cancelled.
2042            return;
2043        }
2044
2045        mAudioStatusEventPending = false;
2046    }
2047
2048    Mutex::Autolock autoLock(mLock);
2049
2050    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
2051        mWatchForAudioSeekComplete = false;
2052
2053        if (!mSeekNotificationSent) {
2054            notifyListener_l(MEDIA_SEEK_COMPLETE);
2055            mSeekNotificationSent = true;
2056        }
2057
2058        mSeeking = NO_SEEK;
2059
2060        notifyIfMediaStarted_l();
2061    }
2062
2063    status_t finalStatus;
2064    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
2065        mWatchForAudioEOS = false;
2066        modifyFlags(AUDIO_AT_EOS, SET);
2067        modifyFlags(FIRST_FRAME, SET);
2068        postStreamDoneEvent_l(finalStatus);
2069    }
2070}
2071
2072status_t AwesomePlayer::prepare() {
2073    ATRACE_CALL();
2074    Mutex::Autolock autoLock(mLock);
2075    return prepare_l();
2076}
2077
2078status_t AwesomePlayer::prepare_l() {
2079    if (mFlags & PREPARED) {
2080        return OK;
2081    }
2082
2083    if (mFlags & PREPARING) {
2084        return UNKNOWN_ERROR;
2085    }
2086
2087    mIsAsyncPrepare = false;
2088    status_t err = prepareAsync_l();
2089
2090    if (err != OK) {
2091        return err;
2092    }
2093
2094    while (mFlags & PREPARING) {
2095        mPreparedCondition.wait(mLock);
2096    }
2097
2098    return mPrepareResult;
2099}
2100
2101status_t AwesomePlayer::prepareAsync() {
2102    ATRACE_CALL();
2103    Mutex::Autolock autoLock(mLock);
2104
2105    if (mFlags & PREPARING) {
2106        return UNKNOWN_ERROR;  // async prepare already pending
2107    }
2108
2109    mIsAsyncPrepare = true;
2110    return prepareAsync_l();
2111}
2112
2113status_t AwesomePlayer::prepareAsync_l() {
2114    if (mFlags & PREPARING) {
2115        return UNKNOWN_ERROR;  // async prepare already pending
2116    }
2117
2118    if (!mQueueStarted) {
2119        mQueue.start();
2120        mQueueStarted = true;
2121    }
2122
2123    modifyFlags(PREPARING, SET);
2124    mAsyncPrepareEvent = new AwesomeEvent(
2125            this, &AwesomePlayer::onPrepareAsyncEvent);
2126
2127    mQueue.postEvent(mAsyncPrepareEvent);
2128
2129    return OK;
2130}
2131
2132status_t AwesomePlayer::finishSetDataSource_l() {
2133    ATRACE_CALL();
2134    sp<DataSource> dataSource;
2135
2136    bool isWidevineStreaming = false;
2137    if (!strncasecmp("widevine://", mUri.string(), 11)) {
2138        isWidevineStreaming = true;
2139
2140        String8 newURI = String8("http://");
2141        newURI.append(mUri.string() + 11);
2142
2143        mUri = newURI;
2144    }
2145
2146    AString sniffedMIME;
2147
2148    if (!strncasecmp("http://", mUri.string(), 7)
2149            || !strncasecmp("https://", mUri.string(), 8)
2150            || isWidevineStreaming) {
2151        mConnectingDataSource = HTTPBase::Create(
2152                (mFlags & INCOGNITO)
2153                    ? HTTPBase::kFlagIncognito
2154                    : 0);
2155
2156        if (mUIDValid) {
2157            mConnectingDataSource->setUID(mUID);
2158        }
2159
2160        String8 cacheConfig;
2161        bool disconnectAtHighwatermark;
2162        NuCachedSource2::RemoveCacheSpecificHeaders(
2163                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
2164
2165        mLock.unlock();
2166        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
2167        mLock.lock();
2168
2169        if (err != OK) {
2170            mConnectingDataSource.clear();
2171
2172            ALOGI("mConnectingDataSource->connect() returned %d", err);
2173            return err;
2174        }
2175
2176        if (!isWidevineStreaming) {
2177            // The widevine extractor does its own caching.
2178
2179#if 0
2180            mCachedSource = new NuCachedSource2(
2181                    new ThrottledSource(
2182                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
2183#else
2184            mCachedSource = new NuCachedSource2(
2185                    mConnectingDataSource,
2186                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
2187                    disconnectAtHighwatermark);
2188#endif
2189
2190            dataSource = mCachedSource;
2191        } else {
2192            dataSource = mConnectingDataSource;
2193        }
2194
2195        mConnectingDataSource.clear();
2196
2197        String8 contentType = dataSource->getMIMEType();
2198
2199        if (strncasecmp(contentType.string(), "audio/", 6)) {
2200            // We're not doing this for streams that appear to be audio-only
2201            // streams to ensure that even low bandwidth streams start
2202            // playing back fairly instantly.
2203
2204            // We're going to prefill the cache before trying to instantiate
2205            // the extractor below, as the latter is an operation that otherwise
2206            // could block on the datasource for a significant amount of time.
2207            // During that time we'd be unable to abort the preparation phase
2208            // without this prefill.
2209            if (mCachedSource != NULL) {
2210                // We're going to prefill the cache before trying to instantiate
2211                // the extractor below, as the latter is an operation that otherwise
2212                // could block on the datasource for a significant amount of time.
2213                // During that time we'd be unable to abort the preparation phase
2214                // without this prefill.
2215
2216                mLock.unlock();
2217
2218                // Initially make sure we have at least 192 KB for the sniff
2219                // to complete without blocking.
2220                static const size_t kMinBytesForSniffing = 192 * 1024;
2221
2222                off64_t metaDataSize = -1ll;
2223                for (;;) {
2224                    status_t finalStatus;
2225                    size_t cachedDataRemaining =
2226                        mCachedSource->approxDataRemaining(&finalStatus);
2227
2228                    if (finalStatus != OK
2229                            || (metaDataSize >= 0
2230                                && cachedDataRemaining >= metaDataSize)
2231                            || (mFlags & PREPARE_CANCELLED)) {
2232                        break;
2233                    }
2234
2235                    ALOGV("now cached %d bytes of data", cachedDataRemaining);
2236
2237                    if (metaDataSize < 0
2238                            && cachedDataRemaining >= kMinBytesForSniffing) {
2239                        String8 tmp;
2240                        float confidence;
2241                        sp<AMessage> meta;
2242                        if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2243                            mLock.lock();
2244                            return UNKNOWN_ERROR;
2245                        }
2246
2247                        // We successfully identified the file's extractor to
2248                        // be, remember this mime type so we don't have to
2249                        // sniff it again when we call MediaExtractor::Create()
2250                        // below.
2251                        sniffedMIME = tmp.string();
2252
2253                        if (meta == NULL
2254                                || !meta->findInt64(
2255                                    "meta-data-size", &metaDataSize)) {
2256                            metaDataSize = kHighWaterMarkBytes;
2257                        }
2258
2259                        CHECK_GE(metaDataSize, 0ll);
2260                        ALOGV("metaDataSize = %lld bytes", metaDataSize);
2261                    }
2262
2263                    usleep(200000);
2264                }
2265
2266                mLock.lock();
2267            }
2268
2269            if (mFlags & PREPARE_CANCELLED) {
2270                ALOGI("Prepare cancelled while waiting for initial cache fill.");
2271                return UNKNOWN_ERROR;
2272            }
2273        }
2274    } else {
2275        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2276    }
2277
2278    if (dataSource == NULL) {
2279        return UNKNOWN_ERROR;
2280    }
2281
2282    sp<MediaExtractor> extractor;
2283
2284    if (isWidevineStreaming) {
2285        String8 mimeType;
2286        float confidence;
2287        sp<AMessage> dummy;
2288        bool success;
2289
2290        // SniffWVM is potentially blocking since it may require network access.
2291        // Do not call it with mLock held.
2292        mLock.unlock();
2293        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
2294        mLock.lock();
2295
2296        if (!success
2297                || strcasecmp(
2298                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2299            return ERROR_UNSUPPORTED;
2300        }
2301
2302        mWVMExtractor = new WVMExtractor(dataSource);
2303        mWVMExtractor->setAdaptiveStreamingMode(true);
2304        if (mUIDValid)
2305            mWVMExtractor->setUID(mUID);
2306        extractor = mWVMExtractor;
2307    } else {
2308        extractor = MediaExtractor::Create(
2309                dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
2310
2311        if (extractor == NULL) {
2312            return UNKNOWN_ERROR;
2313        }
2314    }
2315
2316    if (extractor->getDrmFlag()) {
2317        checkDrmStatus(dataSource);
2318    }
2319
2320    status_t err = setDataSource_l(extractor);
2321
2322    if (err != OK) {
2323        mWVMExtractor.clear();
2324
2325        return err;
2326    }
2327
2328    return OK;
2329}
2330
2331void AwesomePlayer::abortPrepare(status_t err) {
2332    CHECK(err != OK);
2333
2334    if (mIsAsyncPrepare) {
2335        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2336    }
2337
2338    mPrepareResult = err;
2339    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2340    mAsyncPrepareEvent = NULL;
2341    mPreparedCondition.broadcast();
2342    mAudioTearDown = false;
2343}
2344
2345// static
2346bool AwesomePlayer::ContinuePreparation(void *cookie) {
2347    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2348
2349    return (me->mFlags & PREPARE_CANCELLED) == 0;
2350}
2351
2352void AwesomePlayer::onPrepareAsyncEvent() {
2353    Mutex::Autolock autoLock(mLock);
2354    beginPrepareAsync_l();
2355}
2356
2357void AwesomePlayer::beginPrepareAsync_l() {
2358    if (mFlags & PREPARE_CANCELLED) {
2359        ALOGI("prepare was cancelled before doing anything");
2360        abortPrepare(UNKNOWN_ERROR);
2361        return;
2362    }
2363
2364    if (mUri.size() > 0) {
2365        status_t err = finishSetDataSource_l();
2366
2367        if (err != OK) {
2368            abortPrepare(err);
2369            return;
2370        }
2371    }
2372
2373    if (mVideoTrack != NULL && mVideoSource == NULL) {
2374        status_t err = initVideoDecoder();
2375
2376        if (err != OK) {
2377            abortPrepare(err);
2378            return;
2379        }
2380    }
2381
2382    if (mAudioTrack != NULL && mAudioSource == NULL) {
2383        status_t err = initAudioDecoder();
2384
2385        if (err != OK) {
2386            abortPrepare(err);
2387            return;
2388        }
2389    }
2390
2391    modifyFlags(PREPARING_CONNECTED, SET);
2392
2393    if (isStreamingHTTP()) {
2394        postBufferingEvent_l();
2395    } else {
2396        finishAsyncPrepare_l();
2397    }
2398}
2399
2400void AwesomePlayer::finishAsyncPrepare_l() {
2401    if (mIsAsyncPrepare) {
2402        if (mVideoSource == NULL) {
2403            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2404        } else {
2405            notifyVideoSize_l();
2406        }
2407
2408        notifyListener_l(MEDIA_PREPARED);
2409    }
2410
2411    mPrepareResult = OK;
2412    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2413    modifyFlags(PREPARED, SET);
2414    mAsyncPrepareEvent = NULL;
2415    mPreparedCondition.broadcast();
2416
2417    if (mAudioTearDown) {
2418        if (mPrepareResult == OK) {
2419            if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
2420                seekTo_l(mAudioTearDownPosition);
2421            }
2422
2423            if (mAudioTearDownWasPlaying) {
2424                modifyFlags(CACHE_UNDERRUN, CLEAR);
2425                play_l();
2426            }
2427        }
2428        mAudioTearDown = false;
2429    }
2430}
2431
2432uint32_t AwesomePlayer::flags() const {
2433    return mExtractorFlags;
2434}
2435
2436void AwesomePlayer::postAudioEOS(int64_t delayUs) {
2437    postCheckAudioStatusEvent(delayUs);
2438}
2439
2440void AwesomePlayer::postAudioSeekComplete() {
2441    postCheckAudioStatusEvent(0);
2442}
2443
2444void AwesomePlayer::postAudioTearDown() {
2445    postAudioTearDownEvent(0);
2446}
2447
2448status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
2449    switch (key) {
2450        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2451        {
2452            return setCacheStatCollectFreq(request);
2453        }
2454        case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
2455        {
2456            if (mAudioPlayer != NULL) {
2457                return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
2458            } else {
2459                return NO_INIT;
2460            }
2461        }
2462        default:
2463        {
2464            return ERROR_UNSUPPORTED;
2465        }
2466    }
2467}
2468
2469status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2470    if (mCachedSource != NULL) {
2471        int32_t freqMs = request.readInt32();
2472        ALOGD("Request to keep cache stats in the past %d ms",
2473            freqMs);
2474        return mCachedSource->setCacheStatCollectFreq(freqMs);
2475    }
2476    return ERROR_UNSUPPORTED;
2477}
2478
2479status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
2480    switch (key) {
2481    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2482        {
2483            int32_t channelCount;
2484            if (mAudioTrack == 0 ||
2485                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2486                channelCount = 0;
2487            }
2488            reply->writeInt32(channelCount);
2489        }
2490        return OK;
2491    default:
2492        {
2493            return ERROR_UNSUPPORTED;
2494        }
2495    }
2496}
2497
2498status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
2499    Mutex::Autolock autoLock(mLock);
2500    size_t trackCount = mExtractor->countTracks();
2501    if (mTextDriver != NULL) {
2502        trackCount += mTextDriver->countExternalTracks();
2503    }
2504
2505    reply->writeInt32(trackCount);
2506    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
2507        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2508
2509        const char *_mime;
2510        CHECK(meta->findCString(kKeyMIMEType, &_mime));
2511
2512        String8 mime = String8(_mime);
2513
2514        reply->writeInt32(2); // 2 fields
2515
2516        if (!strncasecmp(mime.string(), "video/", 6)) {
2517            reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
2518        } else if (!strncasecmp(mime.string(), "audio/", 6)) {
2519            reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
2520        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
2521            reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
2522        } else {
2523            reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
2524        }
2525
2526        const char *lang;
2527        if (!meta->findCString(kKeyMediaLanguage, &lang)) {
2528            lang = "und";
2529        }
2530        reply->writeString16(String16(lang));
2531    }
2532
2533    if (mTextDriver != NULL) {
2534        mTextDriver->getExternalTrackInfo(reply);
2535    }
2536    return OK;
2537}
2538
2539status_t AwesomePlayer::selectAudioTrack_l(
2540        const sp<MediaSource>& source, size_t trackIndex) {
2541
2542    ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags);
2543
2544    {
2545        Mutex::Autolock autoLock(mStatsLock);
2546        if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
2547            ALOGI("Track %d is active. Does nothing.", trackIndex);
2548            return OK;
2549        }
2550        //mStats.mFlags = mFlags;
2551    }
2552
2553    if (mSeeking != NO_SEEK) {
2554        ALOGE("Selecting a track while seeking is not supported");
2555        return ERROR_UNSUPPORTED;
2556    }
2557
2558    if ((mFlags & PREPARED) == 0) {
2559        ALOGE("Data source has not finished preparation");
2560        return ERROR_UNSUPPORTED;
2561    }
2562
2563    CHECK(source != NULL);
2564    bool wasPlaying = (mFlags & PLAYING) != 0;
2565
2566    pause_l();
2567
2568    int64_t curTimeUs;
2569    CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
2570
2571    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
2572            && mAudioSource != NULL) {
2573        // If we had an audio player, it would have effectively
2574        // taken possession of the audio source and stopped it when
2575        // _it_ is stopped. Otherwise this is still our responsibility.
2576        mAudioSource->stop();
2577    }
2578    mAudioSource.clear();
2579    mOmxSource.clear();
2580
2581    mTimeSource = NULL;
2582
2583    delete mAudioPlayer;
2584    mAudioPlayer = NULL;
2585
2586    modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
2587
2588    setAudioSource(source);
2589
2590    modifyFlags(AUDIO_AT_EOS, CLEAR);
2591    modifyFlags(AT_EOS, CLEAR);
2592
2593    status_t err;
2594    if ((err = initAudioDecoder()) != OK) {
2595        ALOGE("Failed to init audio decoder: 0x%x", err);
2596        return err;
2597    }
2598
2599    mSeekNotificationSent = true;
2600    seekTo_l(curTimeUs);
2601
2602    if (wasPlaying) {
2603        play_l();
2604    }
2605
2606    mActiveAudioTrackIndex = trackIndex;
2607
2608    return OK;
2609}
2610
2611status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
2612    ATRACE_CALL();
2613    ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
2614    Mutex::Autolock autoLock(mLock);
2615    size_t trackCount = mExtractor->countTracks();
2616    if (mTextDriver != NULL) {
2617        trackCount += mTextDriver->countExternalTracks();
2618    }
2619    if (trackIndex >= trackCount) {
2620        ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount);
2621        return ERROR_OUT_OF_RANGE;
2622    }
2623
2624    bool isAudioTrack = false;
2625    if (trackIndex < mExtractor->countTracks()) {
2626        sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
2627        const char *mime;
2628        CHECK(meta->findCString(kKeyMIMEType, &mime));
2629        isAudioTrack = !strncasecmp(mime, "audio/", 6);
2630
2631        if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) {
2632            ALOGE("Track %d is not either audio or timed text", trackIndex);
2633            return ERROR_UNSUPPORTED;
2634        }
2635    }
2636
2637    if (isAudioTrack) {
2638        if (!select) {
2639            ALOGE("Deselect an audio track (%d) is not supported", trackIndex);
2640            return ERROR_UNSUPPORTED;
2641        }
2642        return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
2643    }
2644
2645    // Timed text track handling
2646    if (mTextDriver == NULL) {
2647        return INVALID_OPERATION;
2648    }
2649
2650    status_t err = OK;
2651    if (select) {
2652        err = mTextDriver->selectTrack(trackIndex);
2653        if (err == OK) {
2654            modifyFlags(TEXTPLAYER_INITIALIZED, SET);
2655            if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
2656                mTextDriver->start();
2657                modifyFlags(TEXT_RUNNING, SET);
2658            }
2659        }
2660    } else {
2661        err = mTextDriver->unselectTrack(trackIndex);
2662        if (err == OK) {
2663            modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
2664            modifyFlags(TEXT_RUNNING, CLEAR);
2665        }
2666    }
2667    return err;
2668}
2669
2670size_t AwesomePlayer::countTracks() const {
2671    return mExtractor->countTracks() + mTextDriver->countExternalTracks();
2672}
2673
2674status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
2675    Mutex::Autolock lock(mLock);
2676    return setVideoScalingMode_l(mode);
2677}
2678
2679status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
2680    mVideoScalingMode = mode;
2681    if (mNativeWindow != NULL) {
2682        status_t err = native_window_set_scaling_mode(
2683                mNativeWindow.get(), mVideoScalingMode);
2684        if (err != OK) {
2685            ALOGW("Failed to set scaling mode: %d", err);
2686        }
2687        return err;
2688    }
2689    return OK;
2690}
2691
2692status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
2693    ATRACE_CALL();
2694    if (NULL == reply) {
2695        return android::BAD_VALUE;
2696    }
2697    int32_t methodId;
2698    status_t ret = request.readInt32(&methodId);
2699    if (ret != android::OK) {
2700        return ret;
2701    }
2702    switch(methodId) {
2703        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
2704        {
2705            int mode = request.readInt32();
2706            return setVideoScalingMode(mode);
2707        }
2708
2709        case INVOKE_ID_GET_TRACK_INFO:
2710        {
2711            return getTrackInfo(reply);
2712        }
2713        case INVOKE_ID_ADD_EXTERNAL_SOURCE:
2714        {
2715            Mutex::Autolock autoLock(mLock);
2716            if (mTextDriver == NULL) {
2717                mTextDriver = new TimedTextDriver(mListener);
2718            }
2719            // String values written in Parcel are UTF-16 values.
2720            String8 uri(request.readString16());
2721            String8 mimeType(request.readString16());
2722            size_t nTracks = countTracks();
2723            return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
2724        }
2725        case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
2726        {
2727            Mutex::Autolock autoLock(mLock);
2728            if (mTextDriver == NULL) {
2729                mTextDriver = new TimedTextDriver(mListener);
2730            }
2731            int fd         = request.readFileDescriptor();
2732            off64_t offset = request.readInt64();
2733            off64_t length  = request.readInt64();
2734            String8 mimeType(request.readString16());
2735            size_t nTracks = countTracks();
2736            return mTextDriver->addOutOfBandTextSource(
2737                    nTracks, fd, offset, length, mimeType);
2738        }
2739        case INVOKE_ID_SELECT_TRACK:
2740        {
2741            int trackIndex = request.readInt32();
2742            return selectTrack(trackIndex, true /* select */);
2743        }
2744        case INVOKE_ID_UNSELECT_TRACK:
2745        {
2746            int trackIndex = request.readInt32();
2747            return selectTrack(trackIndex, false /* select */);
2748        }
2749        default:
2750        {
2751            return ERROR_UNSUPPORTED;
2752        }
2753    }
2754    // It will not reach here.
2755    return OK;
2756}
2757
2758bool AwesomePlayer::isStreamingHTTP() const {
2759    return mCachedSource != NULL || mWVMExtractor != NULL;
2760}
2761
2762status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2763    Mutex::Autolock autoLock(mStatsLock);
2764
2765    FILE *out = fdopen(dup(fd), "w");
2766
2767    fprintf(out, " AwesomePlayer\n");
2768    if (mStats.mFd < 0) {
2769        fprintf(out, "  URI(suppressed)");
2770    } else {
2771        fprintf(out, "  fd(%d)", mStats.mFd);
2772    }
2773
2774    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2775
2776    if (mStats.mBitrate >= 0) {
2777        fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2778    }
2779
2780    fprintf(out, "\n");
2781
2782    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2783        const TrackStat &stat = mStats.mTracks.itemAt(i);
2784
2785        fprintf(out, "  Track %d\n", i + 1);
2786        fprintf(out, "   MIME(%s)", stat.mMIME.string());
2787
2788        if (!stat.mDecoderName.isEmpty()) {
2789            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2790        }
2791
2792        fprintf(out, "\n");
2793
2794        if ((ssize_t)i == mStats.mVideoTrackIndex) {
2795            fprintf(out,
2796                    "   videoDimensions(%d x %d), "
2797                    "numVideoFramesDecoded(%lld), "
2798                    "numVideoFramesDropped(%lld)\n",
2799                    mStats.mVideoWidth,
2800                    mStats.mVideoHeight,
2801                    mStats.mNumVideoFramesDecoded,
2802                    mStats.mNumVideoFramesDropped);
2803        }
2804    }
2805
2806    fclose(out);
2807    out = NULL;
2808
2809    return OK;
2810}
2811
2812void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2813    switch (mode) {
2814        case SET:
2815            mFlags |= value;
2816            break;
2817        case CLEAR:
2818            if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) {
2819                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
2820            }
2821            mFlags &= ~value;
2822            break;
2823        case ASSIGN:
2824            mFlags = value;
2825            break;
2826        default:
2827            TRESPASS();
2828    }
2829
2830    {
2831        Mutex::Autolock autoLock(mStatsLock);
2832        mStats.mFlags = mFlags;
2833    }
2834}
2835
2836void AwesomePlayer::onAudioTearDownEvent() {
2837
2838    Mutex::Autolock autoLock(mLock);
2839    if (!mAudioTearDownEventPending) {
2840        return;
2841    }
2842    mAudioTearDownEventPending = false;
2843
2844    ALOGV("onAudioTearDownEvent");
2845
2846    // stream info is cleared by reset_l() so copy what we need
2847    mAudioTearDownWasPlaying = (mFlags & PLAYING);
2848    KeyedVector<String8, String8> uriHeaders(mUriHeaders);
2849    sp<DataSource> fileSource(mFileSource);
2850
2851    mStatsLock.lock();
2852    String8 uri(mStats.mURI);
2853    mStatsLock.unlock();
2854
2855    // get current position so we can start recreated stream from here
2856    getPosition(&mAudioTearDownPosition);
2857
2858    // Reset and recreate
2859    reset_l();
2860
2861    status_t err;
2862
2863    if (fileSource != NULL) {
2864        mFileSource = fileSource;
2865        err = setDataSource_l(fileSource);
2866    } else {
2867        err = setDataSource_l(uri, &uriHeaders);
2868    }
2869
2870    mFlags |= PREPARING;
2871    if ( err != OK ) {
2872        // This will force beingPrepareAsync_l() to notify
2873        // a MEDIA_ERROR to the client and abort the prepare
2874        mFlags |= PREPARE_CANCELLED;
2875    }
2876
2877    mAudioTearDown = true;
2878    mIsAsyncPrepare = true;
2879
2880    // Call prepare for the host decoding
2881    beginPrepareAsync_l();
2882}
2883
2884}  // namespace android
2885