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