AwesomePlayer.cpp revision 5432aea4b1b107b722ddb507c610bdfc4c61c8aa
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        if (mVideoSource == NULL) {
2100            // For video the mSeeking flag is always reset in finishSeekIfNecessary
2101            mSeeking = NO_SEEK;
2102        }
2103
2104        notifyIfMediaStarted_l();
2105    }
2106
2107    status_t finalStatus;
2108    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
2109        mWatchForAudioEOS = false;
2110        modifyFlags(AUDIO_AT_EOS, SET);
2111        modifyFlags(FIRST_FRAME, SET);
2112        postStreamDoneEvent_l(finalStatus);
2113    }
2114}
2115
2116status_t AwesomePlayer::prepare() {
2117    ATRACE_CALL();
2118    Mutex::Autolock autoLock(mLock);
2119    return prepare_l();
2120}
2121
2122status_t AwesomePlayer::prepare_l() {
2123    if (mFlags & PREPARED) {
2124        return OK;
2125    }
2126
2127    if (mFlags & PREPARING) {
2128        return UNKNOWN_ERROR;
2129    }
2130
2131    mIsAsyncPrepare = false;
2132    status_t err = prepareAsync_l();
2133
2134    if (err != OK) {
2135        return err;
2136    }
2137
2138    while (mFlags & PREPARING) {
2139        mPreparedCondition.wait(mLock);
2140    }
2141
2142    return mPrepareResult;
2143}
2144
2145status_t AwesomePlayer::prepareAsync() {
2146    ATRACE_CALL();
2147    Mutex::Autolock autoLock(mLock);
2148
2149    if (mFlags & PREPARING) {
2150        return UNKNOWN_ERROR;  // async prepare already pending
2151    }
2152
2153    mIsAsyncPrepare = true;
2154    return prepareAsync_l();
2155}
2156
2157status_t AwesomePlayer::prepareAsync_l() {
2158    if (mFlags & PREPARING) {
2159        return UNKNOWN_ERROR;  // async prepare already pending
2160    }
2161
2162    if (!mQueueStarted) {
2163        mQueue.start();
2164        mQueueStarted = true;
2165    }
2166
2167    modifyFlags(PREPARING, SET);
2168    mAsyncPrepareEvent = new AwesomeEvent(
2169            this, &AwesomePlayer::onPrepareAsyncEvent);
2170
2171    mQueue.postEvent(mAsyncPrepareEvent);
2172
2173    return OK;
2174}
2175
2176status_t AwesomePlayer::finishSetDataSource_l() {
2177    ATRACE_CALL();
2178    sp<DataSource> dataSource;
2179
2180    bool isWidevineStreaming = false;
2181    if (!strncasecmp("widevine://", mUri.string(), 11)) {
2182        isWidevineStreaming = true;
2183
2184        String8 newURI = String8("http://");
2185        newURI.append(mUri.string() + 11);
2186
2187        mUri = newURI;
2188    }
2189
2190    AString sniffedMIME;
2191
2192    if (!strncasecmp("http://", mUri.string(), 7)
2193            || !strncasecmp("https://", mUri.string(), 8)
2194            || isWidevineStreaming) {
2195        mConnectingDataSource = HTTPBase::Create(
2196                (mFlags & INCOGNITO)
2197                    ? HTTPBase::kFlagIncognito
2198                    : 0);
2199
2200        if (mUIDValid) {
2201            mConnectingDataSource->setUID(mUID);
2202        }
2203
2204        String8 cacheConfig;
2205        bool disconnectAtHighwatermark;
2206        NuCachedSource2::RemoveCacheSpecificHeaders(
2207                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
2208
2209        mLock.unlock();
2210        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
2211        mLock.lock();
2212
2213        if (err != OK) {
2214            mConnectingDataSource.clear();
2215
2216            ALOGI("mConnectingDataSource->connect() returned %d", err);
2217            return err;
2218        }
2219
2220        if (!isWidevineStreaming) {
2221            // The widevine extractor does its own caching.
2222
2223#if 0
2224            mCachedSource = new NuCachedSource2(
2225                    new ThrottledSource(
2226                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
2227#else
2228            mCachedSource = new NuCachedSource2(
2229                    mConnectingDataSource,
2230                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
2231                    disconnectAtHighwatermark);
2232#endif
2233
2234            dataSource = mCachedSource;
2235        } else {
2236            dataSource = mConnectingDataSource;
2237        }
2238
2239        mConnectingDataSource.clear();
2240
2241        String8 contentType = dataSource->getMIMEType();
2242
2243        if (strncasecmp(contentType.string(), "audio/", 6)) {
2244            // We're not doing this for streams that appear to be audio-only
2245            // streams to ensure that even low bandwidth streams start
2246            // playing back fairly instantly.
2247
2248            // We're going to prefill the cache before trying to instantiate
2249            // the extractor below, as the latter is an operation that otherwise
2250            // could block on the datasource for a significant amount of time.
2251            // During that time we'd be unable to abort the preparation phase
2252            // without this prefill.
2253            if (mCachedSource != NULL) {
2254                // We're going to prefill the cache before trying to instantiate
2255                // the extractor below, as the latter is an operation that otherwise
2256                // could block on the datasource for a significant amount of time.
2257                // During that time we'd be unable to abort the preparation phase
2258                // without this prefill.
2259
2260                mLock.unlock();
2261
2262                // Initially make sure we have at least 192 KB for the sniff
2263                // to complete without blocking.
2264                static const size_t kMinBytesForSniffing = 192 * 1024;
2265
2266                off64_t metaDataSize = -1ll;
2267                for (;;) {
2268                    status_t finalStatus;
2269                    size_t cachedDataRemaining =
2270                        mCachedSource->approxDataRemaining(&finalStatus);
2271
2272                    if (finalStatus != OK
2273                            || (metaDataSize >= 0
2274                                && cachedDataRemaining >= metaDataSize)
2275                            || (mFlags & PREPARE_CANCELLED)) {
2276                        break;
2277                    }
2278
2279                    ALOGV("now cached %d bytes of data", cachedDataRemaining);
2280
2281                    if (metaDataSize < 0
2282                            && cachedDataRemaining >= kMinBytesForSniffing) {
2283                        String8 tmp;
2284                        float confidence;
2285                        sp<AMessage> meta;
2286                        if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2287                            mLock.lock();
2288                            return UNKNOWN_ERROR;
2289                        }
2290
2291                        // We successfully identified the file's extractor to
2292                        // be, remember this mime type so we don't have to
2293                        // sniff it again when we call MediaExtractor::Create()
2294                        // below.
2295                        sniffedMIME = tmp.string();
2296
2297                        if (meta == NULL
2298                                || !meta->findInt64(
2299                                    "meta-data-size", &metaDataSize)) {
2300                            metaDataSize = kHighWaterMarkBytes;
2301                        }
2302
2303                        CHECK_GE(metaDataSize, 0ll);
2304                        ALOGV("metaDataSize = %lld bytes", metaDataSize);
2305                    }
2306
2307                    usleep(200000);
2308                }
2309
2310                mLock.lock();
2311            }
2312
2313            if (mFlags & PREPARE_CANCELLED) {
2314                ALOGI("Prepare cancelled while waiting for initial cache fill.");
2315                return UNKNOWN_ERROR;
2316            }
2317        }
2318    } else {
2319        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2320    }
2321
2322    if (dataSource == NULL) {
2323        return UNKNOWN_ERROR;
2324    }
2325
2326    sp<MediaExtractor> extractor;
2327
2328    if (isWidevineStreaming) {
2329        String8 mimeType;
2330        float confidence;
2331        sp<AMessage> dummy;
2332        bool success;
2333
2334        // SniffWVM is potentially blocking since it may require network access.
2335        // Do not call it with mLock held.
2336        mLock.unlock();
2337        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
2338        mLock.lock();
2339
2340        if (!success
2341                || strcasecmp(
2342                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2343            return ERROR_UNSUPPORTED;
2344        }
2345
2346        mWVMExtractor = new WVMExtractor(dataSource);
2347        mWVMExtractor->setAdaptiveStreamingMode(true);
2348        if (mUIDValid)
2349            mWVMExtractor->setUID(mUID);
2350        extractor = mWVMExtractor;
2351    } else {
2352        extractor = MediaExtractor::Create(
2353                dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
2354
2355        if (extractor == NULL) {
2356            return UNKNOWN_ERROR;
2357        }
2358    }
2359
2360    if (extractor->getDrmFlag()) {
2361        checkDrmStatus(dataSource);
2362    }
2363
2364    status_t err = setDataSource_l(extractor);
2365
2366    if (err != OK) {
2367        mWVMExtractor.clear();
2368
2369        return err;
2370    }
2371
2372    return OK;
2373}
2374
2375void AwesomePlayer::abortPrepare(status_t err) {
2376    CHECK(err != OK);
2377
2378    if (mIsAsyncPrepare) {
2379        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2380    }
2381
2382    mPrepareResult = err;
2383    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2384    mAsyncPrepareEvent = NULL;
2385    mPreparedCondition.broadcast();
2386    mAudioTearDown = false;
2387}
2388
2389// static
2390bool AwesomePlayer::ContinuePreparation(void *cookie) {
2391    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2392
2393    return (me->mFlags & PREPARE_CANCELLED) == 0;
2394}
2395
2396void AwesomePlayer::onPrepareAsyncEvent() {
2397    Mutex::Autolock autoLock(mLock);
2398    beginPrepareAsync_l();
2399}
2400
2401void AwesomePlayer::beginPrepareAsync_l() {
2402    if (mFlags & PREPARE_CANCELLED) {
2403        ALOGI("prepare was cancelled before doing anything");
2404        abortPrepare(UNKNOWN_ERROR);
2405        return;
2406    }
2407
2408    if (mUri.size() > 0) {
2409        status_t err = finishSetDataSource_l();
2410
2411        if (err != OK) {
2412            abortPrepare(err);
2413            return;
2414        }
2415    }
2416
2417    if (mVideoTrack != NULL && mVideoSource == NULL) {
2418        status_t err = initVideoDecoder();
2419
2420        if (err != OK) {
2421            abortPrepare(err);
2422            return;
2423        }
2424    }
2425
2426    if (mAudioTrack != NULL && mAudioSource == NULL) {
2427        status_t err = initAudioDecoder();
2428
2429        if (err != OK) {
2430            abortPrepare(err);
2431            return;
2432        }
2433    }
2434
2435    modifyFlags(PREPARING_CONNECTED, SET);
2436
2437    if (isStreamingHTTP()) {
2438        postBufferingEvent_l();
2439    } else {
2440        finishAsyncPrepare_l();
2441    }
2442}
2443
2444void AwesomePlayer::finishAsyncPrepare_l() {
2445    if (mIsAsyncPrepare) {
2446        if (mVideoSource == NULL) {
2447            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2448        } else {
2449            notifyVideoSize_l();
2450        }
2451
2452        notifyListener_l(MEDIA_PREPARED);
2453    }
2454
2455    mPrepareResult = OK;
2456    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2457    modifyFlags(PREPARED, SET);
2458    mAsyncPrepareEvent = NULL;
2459    mPreparedCondition.broadcast();
2460
2461    if (mAudioTearDown) {
2462        if (mPrepareResult == OK) {
2463            if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
2464                seekTo_l(mAudioTearDownPosition);
2465            }
2466
2467            if (mAudioTearDownWasPlaying) {
2468                modifyFlags(CACHE_UNDERRUN, CLEAR);
2469                play_l();
2470            }
2471        }
2472        mAudioTearDown = false;
2473    }
2474}
2475
2476uint32_t AwesomePlayer::flags() const {
2477    return mExtractorFlags;
2478}
2479
2480void AwesomePlayer::postAudioEOS(int64_t delayUs) {
2481    postCheckAudioStatusEvent(delayUs);
2482}
2483
2484void AwesomePlayer::postAudioSeekComplete() {
2485    postCheckAudioStatusEvent(0);
2486}
2487
2488void AwesomePlayer::postAudioTearDown() {
2489    postAudioTearDownEvent(0);
2490}
2491
2492status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
2493    switch (key) {
2494        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2495        {
2496            return setCacheStatCollectFreq(request);
2497        }
2498        case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
2499        {
2500            if (mAudioPlayer != NULL) {
2501                return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
2502            } else {
2503                return NO_INIT;
2504            }
2505        }
2506        default:
2507        {
2508            return ERROR_UNSUPPORTED;
2509        }
2510    }
2511}
2512
2513status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2514    if (mCachedSource != NULL) {
2515        int32_t freqMs = request.readInt32();
2516        ALOGD("Request to keep cache stats in the past %d ms",
2517            freqMs);
2518        return mCachedSource->setCacheStatCollectFreq(freqMs);
2519    }
2520    return ERROR_UNSUPPORTED;
2521}
2522
2523status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
2524    switch (key) {
2525    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2526        {
2527            int32_t channelCount;
2528            if (mAudioTrack == 0 ||
2529                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2530                channelCount = 0;
2531            }
2532            reply->writeInt32(channelCount);
2533        }
2534        return OK;
2535    default:
2536        {
2537            return ERROR_UNSUPPORTED;
2538        }
2539    }
2540}
2541
2542status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
2543    Mutex::Autolock autoLock(mLock);
2544    size_t trackCount = mExtractor->countTracks();
2545    if (mTextDriver != NULL) {
2546        trackCount += mTextDriver->countExternalTracks();
2547    }
2548
2549    reply->writeInt32(trackCount);
2550    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
2551        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2552
2553        const char *_mime;
2554        CHECK(meta->findCString(kKeyMIMEType, &_mime));
2555
2556        String8 mime = String8(_mime);
2557
2558        reply->writeInt32(2); // 2 fields
2559
2560        if (!strncasecmp(mime.string(), "video/", 6)) {
2561            reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
2562        } else if (!strncasecmp(mime.string(), "audio/", 6)) {
2563            reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
2564        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
2565            reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
2566        } else {
2567            reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
2568        }
2569
2570        const char *lang;
2571        if (!meta->findCString(kKeyMediaLanguage, &lang)) {
2572            lang = "und";
2573        }
2574        reply->writeString16(String16(lang));
2575    }
2576
2577    if (mTextDriver != NULL) {
2578        mTextDriver->getExternalTrackInfo(reply);
2579    }
2580    return OK;
2581}
2582
2583status_t AwesomePlayer::selectAudioTrack_l(
2584        const sp<MediaSource>& source, size_t trackIndex) {
2585
2586    ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags);
2587
2588    {
2589        Mutex::Autolock autoLock(mStatsLock);
2590        if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
2591            ALOGI("Track %d is active. Does nothing.", trackIndex);
2592            return OK;
2593        }
2594        //mStats.mFlags = mFlags;
2595    }
2596
2597    if (mSeeking != NO_SEEK) {
2598        ALOGE("Selecting a track while seeking is not supported");
2599        return ERROR_UNSUPPORTED;
2600    }
2601
2602    if ((mFlags & PREPARED) == 0) {
2603        ALOGE("Data source has not finished preparation");
2604        return ERROR_UNSUPPORTED;
2605    }
2606
2607    CHECK(source != NULL);
2608    bool wasPlaying = (mFlags & PLAYING) != 0;
2609
2610    pause_l();
2611
2612    int64_t curTimeUs;
2613    CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
2614
2615    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
2616            && mAudioSource != NULL) {
2617        // If we had an audio player, it would have effectively
2618        // taken possession of the audio source and stopped it when
2619        // _it_ is stopped. Otherwise this is still our responsibility.
2620        mAudioSource->stop();
2621    }
2622    mAudioSource.clear();
2623    mOmxSource.clear();
2624
2625    mTimeSource = NULL;
2626
2627    delete mAudioPlayer;
2628    mAudioPlayer = NULL;
2629
2630    modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
2631
2632    setAudioSource(source);
2633
2634    modifyFlags(AUDIO_AT_EOS, CLEAR);
2635    modifyFlags(AT_EOS, CLEAR);
2636
2637    status_t err;
2638    if ((err = initAudioDecoder()) != OK) {
2639        ALOGE("Failed to init audio decoder: 0x%x", err);
2640        return err;
2641    }
2642
2643    mSeekNotificationSent = true;
2644    seekTo_l(curTimeUs);
2645
2646    if (wasPlaying) {
2647        play_l();
2648    }
2649
2650    mActiveAudioTrackIndex = trackIndex;
2651
2652    return OK;
2653}
2654
2655status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
2656    ATRACE_CALL();
2657    ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
2658    Mutex::Autolock autoLock(mLock);
2659    size_t trackCount = mExtractor->countTracks();
2660    if (mTextDriver != NULL) {
2661        trackCount += mTextDriver->countExternalTracks();
2662    }
2663    if (trackIndex >= trackCount) {
2664        ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount);
2665        return ERROR_OUT_OF_RANGE;
2666    }
2667
2668    bool isAudioTrack = false;
2669    if (trackIndex < mExtractor->countTracks()) {
2670        sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
2671        const char *mime;
2672        CHECK(meta->findCString(kKeyMIMEType, &mime));
2673        isAudioTrack = !strncasecmp(mime, "audio/", 6);
2674
2675        if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) {
2676            ALOGE("Track %d is not either audio or timed text", trackIndex);
2677            return ERROR_UNSUPPORTED;
2678        }
2679    }
2680
2681    if (isAudioTrack) {
2682        if (!select) {
2683            ALOGE("Deselect an audio track (%d) is not supported", trackIndex);
2684            return ERROR_UNSUPPORTED;
2685        }
2686        return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
2687    }
2688
2689    // Timed text track handling
2690    if (mTextDriver == NULL) {
2691        return INVALID_OPERATION;
2692    }
2693
2694    status_t err = OK;
2695    if (select) {
2696        err = mTextDriver->selectTrack(trackIndex);
2697        if (err == OK) {
2698            modifyFlags(TEXTPLAYER_INITIALIZED, SET);
2699            if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
2700                mTextDriver->start();
2701                modifyFlags(TEXT_RUNNING, SET);
2702            }
2703        }
2704    } else {
2705        err = mTextDriver->unselectTrack(trackIndex);
2706        if (err == OK) {
2707            modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
2708            modifyFlags(TEXT_RUNNING, CLEAR);
2709        }
2710    }
2711    return err;
2712}
2713
2714size_t AwesomePlayer::countTracks() const {
2715    return mExtractor->countTracks() + mTextDriver->countExternalTracks();
2716}
2717
2718status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
2719    Mutex::Autolock lock(mLock);
2720    return setVideoScalingMode_l(mode);
2721}
2722
2723status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
2724    mVideoScalingMode = mode;
2725    if (mNativeWindow != NULL) {
2726        status_t err = native_window_set_scaling_mode(
2727                mNativeWindow.get(), mVideoScalingMode);
2728        if (err != OK) {
2729            ALOGW("Failed to set scaling mode: %d", err);
2730        }
2731        return err;
2732    }
2733    return OK;
2734}
2735
2736status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
2737    ATRACE_CALL();
2738    if (NULL == reply) {
2739        return android::BAD_VALUE;
2740    }
2741    int32_t methodId;
2742    status_t ret = request.readInt32(&methodId);
2743    if (ret != android::OK) {
2744        return ret;
2745    }
2746    switch(methodId) {
2747        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
2748        {
2749            int mode = request.readInt32();
2750            return setVideoScalingMode(mode);
2751        }
2752
2753        case INVOKE_ID_GET_TRACK_INFO:
2754        {
2755            return getTrackInfo(reply);
2756        }
2757        case INVOKE_ID_ADD_EXTERNAL_SOURCE:
2758        {
2759            Mutex::Autolock autoLock(mLock);
2760            if (mTextDriver == NULL) {
2761                mTextDriver = new TimedTextDriver(mListener);
2762            }
2763            // String values written in Parcel are UTF-16 values.
2764            String8 uri(request.readString16());
2765            String8 mimeType(request.readString16());
2766            size_t nTracks = countTracks();
2767            return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
2768        }
2769        case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
2770        {
2771            Mutex::Autolock autoLock(mLock);
2772            if (mTextDriver == NULL) {
2773                mTextDriver = new TimedTextDriver(mListener);
2774            }
2775            int fd         = request.readFileDescriptor();
2776            off64_t offset = request.readInt64();
2777            off64_t length  = request.readInt64();
2778            String8 mimeType(request.readString16());
2779            size_t nTracks = countTracks();
2780            return mTextDriver->addOutOfBandTextSource(
2781                    nTracks, fd, offset, length, mimeType);
2782        }
2783        case INVOKE_ID_SELECT_TRACK:
2784        {
2785            int trackIndex = request.readInt32();
2786            return selectTrack(trackIndex, true /* select */);
2787        }
2788        case INVOKE_ID_UNSELECT_TRACK:
2789        {
2790            int trackIndex = request.readInt32();
2791            return selectTrack(trackIndex, false /* select */);
2792        }
2793        default:
2794        {
2795            return ERROR_UNSUPPORTED;
2796        }
2797    }
2798    // It will not reach here.
2799    return OK;
2800}
2801
2802bool AwesomePlayer::isStreamingHTTP() const {
2803    return mCachedSource != NULL || mWVMExtractor != NULL;
2804}
2805
2806status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2807    Mutex::Autolock autoLock(mStatsLock);
2808
2809    FILE *out = fdopen(dup(fd), "w");
2810
2811    fprintf(out, " AwesomePlayer\n");
2812    if (mStats.mFd < 0) {
2813        fprintf(out, "  URI(suppressed)");
2814    } else {
2815        fprintf(out, "  fd(%d)", mStats.mFd);
2816    }
2817
2818    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2819
2820    if (mStats.mBitrate >= 0) {
2821        fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2822    }
2823
2824    fprintf(out, "\n");
2825
2826    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2827        const TrackStat &stat = mStats.mTracks.itemAt(i);
2828
2829        fprintf(out, "  Track %d\n", i + 1);
2830        fprintf(out, "   MIME(%s)", stat.mMIME.string());
2831
2832        if (!stat.mDecoderName.isEmpty()) {
2833            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2834        }
2835
2836        fprintf(out, "\n");
2837
2838        if ((ssize_t)i == mStats.mVideoTrackIndex) {
2839            fprintf(out,
2840                    "   videoDimensions(%d x %d), "
2841                    "numVideoFramesDecoded(%lld), "
2842                    "numVideoFramesDropped(%lld)\n",
2843                    mStats.mVideoWidth,
2844                    mStats.mVideoHeight,
2845                    mStats.mNumVideoFramesDecoded,
2846                    mStats.mNumVideoFramesDropped);
2847        }
2848    }
2849
2850    fclose(out);
2851    out = NULL;
2852
2853    return OK;
2854}
2855
2856void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2857    switch (mode) {
2858        case SET:
2859            mFlags |= value;
2860            break;
2861        case CLEAR:
2862            if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) {
2863                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
2864            }
2865            mFlags &= ~value;
2866            break;
2867        case ASSIGN:
2868            mFlags = value;
2869            break;
2870        default:
2871            TRESPASS();
2872    }
2873
2874    {
2875        Mutex::Autolock autoLock(mStatsLock);
2876        mStats.mFlags = mFlags;
2877    }
2878}
2879
2880void AwesomePlayer::onAudioTearDownEvent() {
2881
2882    Mutex::Autolock autoLock(mLock);
2883    if (!mAudioTearDownEventPending) {
2884        return;
2885    }
2886    mAudioTearDownEventPending = false;
2887
2888    ALOGV("onAudioTearDownEvent");
2889
2890    // stream info is cleared by reset_l() so copy what we need
2891    mAudioTearDownWasPlaying = (mFlags & PLAYING);
2892    KeyedVector<String8, String8> uriHeaders(mUriHeaders);
2893    sp<DataSource> fileSource(mFileSource);
2894
2895    mStatsLock.lock();
2896    String8 uri(mStats.mURI);
2897    mStatsLock.unlock();
2898
2899    // get current position so we can start recreated stream from here
2900    getPosition(&mAudioTearDownPosition);
2901
2902    // Reset and recreate
2903    reset_l();
2904
2905    status_t err;
2906
2907    if (fileSource != NULL) {
2908        mFileSource = fileSource;
2909        err = setDataSource_l(fileSource);
2910    } else {
2911        err = setDataSource_l(uri, &uriHeaders);
2912    }
2913
2914    mFlags |= PREPARING;
2915    if ( err != OK ) {
2916        // This will force beingPrepareAsync_l() to notify
2917        // a MEDIA_ERROR to the client and abort the prepare
2918        mFlags |= PREPARE_CANCELLED;
2919    }
2920
2921    mAudioTearDown = true;
2922    mIsAsyncPrepare = true;
2923
2924    // Call prepare for the host decoding
2925    beginPrepareAsync_l();
2926}
2927
2928}  // namespace android
2929