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