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