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