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