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