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