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