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