AwesomePlayer.cpp revision 34242ac93467fc364bec435bf961283cd3d6ba0b
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        // Hardware decoders avoid the CPU color conversion by decoding
1108        // directly to ANativeBuffers, so we must use a renderer that
1109        // just pushes those buffers to the ANativeWindow.
1110        mVideoRenderer =
1111            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
1112    } else {
1113        // Other decoders are instantiated locally and as a consequence
1114        // allocate their buffers in local address space.  This renderer
1115        // then performs a color conversion and copy to get the data
1116        // into the ANativeBuffer.
1117        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
1118    }
1119}
1120
1121status_t AwesomePlayer::pause() {
1122    ATRACE_CALL();
1123
1124    Mutex::Autolock autoLock(mLock);
1125
1126    modifyFlags(CACHE_UNDERRUN, CLEAR);
1127
1128    return pause_l();
1129}
1130
1131status_t AwesomePlayer::pause_l(bool at_eos) {
1132    if (!(mFlags & PLAYING)) {
1133        return OK;
1134    }
1135
1136    cancelPlayerEvents(true /* keepNotifications */);
1137
1138    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1139        if (at_eos) {
1140            // If we played the audio stream to completion we
1141            // want to make sure that all samples remaining in the audio
1142            // track's queue are played out.
1143            mAudioPlayer->pause(true /* playPendingSamples */);
1144        } else {
1145            mAudioPlayer->pause();
1146        }
1147
1148        modifyFlags(AUDIO_RUNNING, CLEAR);
1149    }
1150
1151    if (mFlags & TEXTPLAYER_INITIALIZED) {
1152        mTextDriver->pause();
1153        modifyFlags(TEXT_RUNNING, CLEAR);
1154    }
1155
1156    modifyFlags(PLAYING, CLEAR);
1157
1158    if (mDecryptHandle != NULL) {
1159        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1160                Playback::PAUSE, 0);
1161    }
1162
1163    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1164    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1165        params |= IMediaPlayerService::kBatteryDataTrackAudio;
1166    }
1167    if (mVideoSource != NULL) {
1168        params |= IMediaPlayerService::kBatteryDataTrackVideo;
1169    }
1170
1171    addBatteryData(params);
1172
1173    return OK;
1174}
1175
1176bool AwesomePlayer::isPlaying() const {
1177    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1178}
1179
1180status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) {
1181    Mutex::Autolock autoLock(mLock);
1182
1183    status_t err;
1184    if (bufferProducer != NULL) {
1185        err = setNativeWindow_l(new Surface(bufferProducer));
1186    } else {
1187        err = setNativeWindow_l(NULL);
1188    }
1189
1190    return err;
1191}
1192
1193void AwesomePlayer::shutdownVideoDecoder_l() {
1194    if (mVideoBuffer) {
1195        mVideoBuffer->release();
1196        mVideoBuffer = NULL;
1197    }
1198
1199    mVideoSource->stop();
1200
1201    // The following hack is necessary to ensure that the OMX
1202    // component is completely released by the time we may try
1203    // to instantiate it again.
1204    wp<MediaSource> tmp = mVideoSource;
1205    mVideoSource.clear();
1206    while (tmp.promote() != NULL) {
1207        usleep(1000);
1208    }
1209    IPCThreadState::self()->flushCommands();
1210    ALOGV("video decoder shutdown completed");
1211}
1212
1213status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1214    mNativeWindow = native;
1215
1216    if (mVideoSource == NULL) {
1217        return OK;
1218    }
1219
1220    ALOGV("attempting to reconfigure to use new surface");
1221
1222    bool wasPlaying = (mFlags & PLAYING) != 0;
1223
1224    pause_l();
1225    mVideoRenderer.clear();
1226
1227    shutdownVideoDecoder_l();
1228
1229    status_t err = initVideoDecoder();
1230
1231    if (err != OK) {
1232        ALOGE("failed to reinstantiate video decoder after surface change.");
1233        return err;
1234    }
1235
1236    if (mLastVideoTimeUs >= 0) {
1237        mSeeking = SEEK;
1238        mSeekTimeUs = mLastVideoTimeUs;
1239        modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1240    }
1241
1242    if (wasPlaying) {
1243        play_l();
1244    }
1245
1246    return OK;
1247}
1248
1249void AwesomePlayer::setAudioSink(
1250        const sp<MediaPlayerBase::AudioSink> &audioSink) {
1251    Mutex::Autolock autoLock(mLock);
1252
1253    mAudioSink = audioSink;
1254}
1255
1256status_t AwesomePlayer::setLooping(bool shouldLoop) {
1257    Mutex::Autolock autoLock(mLock);
1258
1259    modifyFlags(LOOPING, CLEAR);
1260
1261    if (shouldLoop) {
1262        modifyFlags(LOOPING, SET);
1263    }
1264
1265    return OK;
1266}
1267
1268status_t AwesomePlayer::getDuration(int64_t *durationUs) {
1269    Mutex::Autolock autoLock(mMiscStateLock);
1270
1271    if (mDurationUs < 0) {
1272        return UNKNOWN_ERROR;
1273    }
1274
1275    *durationUs = mDurationUs;
1276
1277    return OK;
1278}
1279
1280status_t AwesomePlayer::getPosition(int64_t *positionUs) {
1281    if (mSeeking != NO_SEEK) {
1282        *positionUs = mSeekTimeUs;
1283    } else if (mVideoSource != NULL
1284            && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1285        Mutex::Autolock autoLock(mMiscStateLock);
1286        *positionUs = mVideoTimeUs;
1287    } else if (mAudioPlayer != NULL) {
1288        *positionUs = mAudioPlayer->getMediaTimeUs();
1289    } else {
1290        *positionUs = 0;
1291    }
1292
1293    return OK;
1294}
1295
1296status_t AwesomePlayer::seekTo(int64_t timeUs) {
1297    ATRACE_CALL();
1298
1299    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
1300        Mutex::Autolock autoLock(mLock);
1301        return seekTo_l(timeUs);
1302    }
1303
1304    return OK;
1305}
1306
1307status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
1308    if (mFlags & CACHE_UNDERRUN) {
1309        modifyFlags(CACHE_UNDERRUN, CLEAR);
1310        play_l();
1311    }
1312
1313    if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1314        // Video playback completed before, there's no pending
1315        // video event right now. In order for this new seek
1316        // to be honored, we need to post one.
1317
1318        postVideoEvent_l();
1319    }
1320
1321    mSeeking = SEEK;
1322    mSeekNotificationSent = false;
1323    mSeekTimeUs = timeUs;
1324    modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1325
1326    seekAudioIfNecessary_l();
1327
1328    if (mFlags & TEXTPLAYER_INITIALIZED) {
1329        mTextDriver->seekToAsync(mSeekTimeUs);
1330    }
1331
1332    if (!(mFlags & PLAYING)) {
1333        ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
1334             " immediately.");
1335
1336        notifyListener_l(MEDIA_SEEK_COMPLETE);
1337        mSeekNotificationSent = true;
1338
1339        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1340            modifyFlags(SEEK_PREVIEW, SET);
1341            postVideoEvent_l();
1342        }
1343    }
1344
1345    return OK;
1346}
1347
1348void AwesomePlayer::seekAudioIfNecessary_l() {
1349    if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1350        mAudioPlayer->seekTo(mSeekTimeUs);
1351
1352        mWatchForAudioSeekComplete = true;
1353        mWatchForAudioEOS = true;
1354
1355        if (mDecryptHandle != NULL) {
1356            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1357                    Playback::PAUSE, 0);
1358            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1359                    Playback::START, mSeekTimeUs / 1000);
1360        }
1361    }
1362}
1363
1364void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1365    CHECK(source != NULL);
1366
1367    mAudioTrack = source;
1368}
1369
1370void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) {
1371    CHECK(source != NULL);
1372
1373    if (mTextDriver == NULL) {
1374        mTextDriver = new TimedTextDriver(mListener);
1375    }
1376
1377    mTextDriver->addInBandTextSource(trackIndex, source);
1378}
1379
1380status_t AwesomePlayer::initAudioDecoder() {
1381    ATRACE_CALL();
1382
1383    sp<MetaData> meta = mAudioTrack->getFormat();
1384
1385    const char *mime;
1386    CHECK(meta->findCString(kKeyMIMEType, &mime));
1387
1388    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1389        mAudioSource = mAudioTrack;
1390    } else {
1391        mAudioSource = OMXCodec::Create(
1392                mClient.interface(), mAudioTrack->getFormat(),
1393                false, // createEncoder
1394                mAudioTrack);
1395    }
1396
1397    if (mAudioSource != NULL) {
1398        int64_t durationUs;
1399        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1400            Mutex::Autolock autoLock(mMiscStateLock);
1401            if (mDurationUs < 0 || durationUs > mDurationUs) {
1402                mDurationUs = durationUs;
1403            }
1404        }
1405
1406        status_t err = mAudioSource->start();
1407
1408        if (err != OK) {
1409            mAudioSource.clear();
1410            return err;
1411        }
1412    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1413        // For legacy reasons we're simply going to ignore the absence
1414        // of an audio decoder for QCELP instead of aborting playback
1415        // altogether.
1416        return OK;
1417    }
1418
1419    if (mAudioSource != NULL) {
1420        Mutex::Autolock autoLock(mStatsLock);
1421        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
1422        const char *component;
1423        if (!mAudioSource->getFormat()
1424                ->findCString(kKeyDecoderComponent, &component)) {
1425            component = "none";
1426        }
1427
1428        stat->mDecoderName = component;
1429    }
1430
1431    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1432}
1433
1434void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1435    CHECK(source != NULL);
1436
1437    mVideoTrack = source;
1438}
1439
1440status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1441    ATRACE_CALL();
1442
1443    // Either the application or the DRM system can independently say
1444    // that there must be a hardware-protected path to an external video sink.
1445    // For now we always require a hardware-protected path to external video sink
1446    // if content is DRMed, but eventually this could be optional per DRM agent.
1447    // When the application wants protection, then
1448    //   (USE_SURFACE_ALLOC && (mSurface != 0) &&
1449    //   (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1450    // will be true, but that part is already handled by SurfaceFlinger.
1451
1452#ifdef DEBUG_HDCP
1453    // For debugging, we allow a system property to control the protected usage.
1454    // In case of uninitialized or unexpected property, we default to "DRM only".
1455    bool setProtectionBit = false;
1456    char value[PROPERTY_VALUE_MAX];
1457    if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1458        if (!strcmp(value, "never")) {
1459            // nop
1460        } else if (!strcmp(value, "always")) {
1461            setProtectionBit = true;
1462        } else if (!strcmp(value, "drm-only")) {
1463            if (mDecryptHandle != NULL) {
1464                setProtectionBit = true;
1465            }
1466        // property value is empty, or unexpected value
1467        } else {
1468            if (mDecryptHandle != NULL) {
1469                setProtectionBit = true;
1470            }
1471        }
1472    // can' read property value
1473    } else {
1474        if (mDecryptHandle != NULL) {
1475            setProtectionBit = true;
1476        }
1477    }
1478    // note that usage bit is already cleared, so no need to clear it in the "else" case
1479    if (setProtectionBit) {
1480        flags |= OMXCodec::kEnableGrallocUsageProtected;
1481    }
1482#else
1483    if (mDecryptHandle != NULL) {
1484        flags |= OMXCodec::kEnableGrallocUsageProtected;
1485    }
1486#endif
1487    ALOGV("initVideoDecoder flags=0x%x", flags);
1488    mVideoSource = OMXCodec::Create(
1489            mClient.interface(), mVideoTrack->getFormat(),
1490            false, // createEncoder
1491            mVideoTrack,
1492            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
1493
1494    if (mVideoSource != NULL) {
1495        int64_t durationUs;
1496        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1497            Mutex::Autolock autoLock(mMiscStateLock);
1498            if (mDurationUs < 0 || durationUs > mDurationUs) {
1499                mDurationUs = durationUs;
1500            }
1501        }
1502
1503        status_t err = mVideoSource->start();
1504
1505        if (err != OK) {
1506            ALOGE("failed to start video source");
1507            mVideoSource.clear();
1508            return err;
1509        }
1510    }
1511
1512    if (mVideoSource != NULL) {
1513        const char *componentName;
1514        CHECK(mVideoSource->getFormat()
1515                ->findCString(kKeyDecoderComponent, &componentName));
1516
1517        {
1518            Mutex::Autolock autoLock(mStatsLock);
1519            TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1520
1521            stat->mDecoderName = componentName;
1522        }
1523
1524        static const char *kPrefix = "OMX.Nvidia.";
1525        static const char *kSuffix = ".decode";
1526        static const size_t kSuffixLength = strlen(kSuffix);
1527
1528        size_t componentNameLength = strlen(componentName);
1529
1530        if (!strncmp(componentName, kPrefix, strlen(kPrefix))
1531                && componentNameLength >= kSuffixLength
1532                && !strcmp(&componentName[
1533                    componentNameLength - kSuffixLength], kSuffix)) {
1534            modifyFlags(SLOW_DECODER_HACK, SET);
1535        }
1536    }
1537
1538    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1539}
1540
1541void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1542    ATRACE_CALL();
1543
1544    if (mSeeking == SEEK_VIDEO_ONLY) {
1545        mSeeking = NO_SEEK;
1546        return;
1547    }
1548
1549    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1550        return;
1551    }
1552
1553    if (mAudioPlayer != NULL) {
1554        ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1555
1556        // If we don't have a video time, seek audio to the originally
1557        // requested seek time instead.
1558
1559        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1560        mWatchForAudioSeekComplete = true;
1561        mWatchForAudioEOS = true;
1562    } else if (!mSeekNotificationSent) {
1563        // If we're playing video only, report seek complete now,
1564        // otherwise audio player will notify us later.
1565        notifyListener_l(MEDIA_SEEK_COMPLETE);
1566        mSeekNotificationSent = true;
1567    }
1568
1569    modifyFlags(FIRST_FRAME, SET);
1570    mSeeking = NO_SEEK;
1571
1572    if (mDecryptHandle != NULL) {
1573        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1574                Playback::PAUSE, 0);
1575        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1576                Playback::START, videoTimeUs / 1000);
1577    }
1578}
1579
1580void AwesomePlayer::onVideoEvent() {
1581    ATRACE_CALL();
1582    Mutex::Autolock autoLock(mLock);
1583    if (!mVideoEventPending) {
1584        // The event has been cancelled in reset_l() but had already
1585        // been scheduled for execution at that time.
1586        return;
1587    }
1588    mVideoEventPending = false;
1589
1590    if (mSeeking != NO_SEEK) {
1591        if (mVideoBuffer) {
1592            mVideoBuffer->release();
1593            mVideoBuffer = NULL;
1594        }
1595
1596        if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
1597                && !(mFlags & SEEK_PREVIEW)) {
1598            // We're going to seek the video source first, followed by
1599            // the audio source.
1600            // In order to avoid jumps in the DataSource offset caused by
1601            // the audio codec prefetching data from the old locations
1602            // while the video codec is already reading data from the new
1603            // locations, we'll "pause" the audio source, causing it to
1604            // stop reading input data until a subsequent seek.
1605
1606            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1607                mAudioPlayer->pause();
1608
1609                modifyFlags(AUDIO_RUNNING, CLEAR);
1610            }
1611            mAudioSource->pause();
1612        }
1613    }
1614
1615    if (!mVideoBuffer) {
1616        MediaSource::ReadOptions options;
1617        if (mSeeking != NO_SEEK) {
1618            ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1619
1620            options.setSeekTo(
1621                    mSeekTimeUs,
1622                    mSeeking == SEEK_VIDEO_ONLY
1623                        ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1624                        : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1625        }
1626        for (;;) {
1627            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1628            options.clearSeekTo();
1629
1630            if (err != OK) {
1631                CHECK(mVideoBuffer == NULL);
1632
1633                if (err == INFO_FORMAT_CHANGED) {
1634                    ALOGV("VideoSource signalled format change.");
1635
1636                    notifyVideoSize_l();
1637
1638                    if (mVideoRenderer != NULL) {
1639                        mVideoRendererIsPreview = false;
1640                        initRenderer_l();
1641                    }
1642                    continue;
1643                }
1644
1645                // So video playback is complete, but we may still have
1646                // a seek request pending that needs to be applied
1647                // to the audio track.
1648                if (mSeeking != NO_SEEK) {
1649                    ALOGV("video stream ended while seeking!");
1650                }
1651                finishSeekIfNecessary(-1);
1652
1653                if (mAudioPlayer != NULL
1654                        && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1655                    startAudioPlayer_l();
1656                }
1657
1658                modifyFlags(VIDEO_AT_EOS, SET);
1659                postStreamDoneEvent_l(err);
1660                return;
1661            }
1662
1663            if (mVideoBuffer->range_length() == 0) {
1664                // Some decoders, notably the PV AVC software decoder
1665                // return spurious empty buffers that we just want to ignore.
1666
1667                mVideoBuffer->release();
1668                mVideoBuffer = NULL;
1669                continue;
1670            }
1671
1672            break;
1673        }
1674
1675        {
1676            Mutex::Autolock autoLock(mStatsLock);
1677            ++mStats.mNumVideoFramesDecoded;
1678        }
1679    }
1680
1681    int64_t timeUs;
1682    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1683
1684    mLastVideoTimeUs = timeUs;
1685
1686    if (mSeeking == SEEK_VIDEO_ONLY) {
1687        if (mSeekTimeUs > timeUs) {
1688            ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1689                 mSeekTimeUs, timeUs);
1690        }
1691    }
1692
1693    {
1694        Mutex::Autolock autoLock(mMiscStateLock);
1695        mVideoTimeUs = timeUs;
1696    }
1697
1698    SeekType wasSeeking = mSeeking;
1699    finishSeekIfNecessary(timeUs);
1700
1701    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1702        status_t err = startAudioPlayer_l();
1703        if (err != OK) {
1704            ALOGE("Starting the audio player failed w/ err %d", err);
1705            return;
1706        }
1707    }
1708
1709    if ((mFlags & TEXTPLAYER_INITIALIZED)
1710            && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1711        mTextDriver->start();
1712        modifyFlags(TEXT_RUNNING, SET);
1713    }
1714
1715    TimeSource *ts =
1716        ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
1717            ? &mSystemTimeSource : mTimeSource;
1718
1719    if (mFlags & FIRST_FRAME) {
1720        modifyFlags(FIRST_FRAME, CLEAR);
1721        mSinceLastDropped = 0;
1722        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1723    }
1724
1725    int64_t realTimeUs, mediaTimeUs;
1726    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1727        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1728        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1729    }
1730
1731    if (wasSeeking == SEEK_VIDEO_ONLY) {
1732        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1733
1734        int64_t latenessUs = nowUs - timeUs;
1735
1736        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1737
1738        if (latenessUs > 0) {
1739            ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1740        }
1741    }
1742
1743    if (wasSeeking == NO_SEEK) {
1744        // Let's display the first frame after seeking right away.
1745
1746        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1747
1748        int64_t latenessUs = nowUs - timeUs;
1749
1750        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1751
1752        if (latenessUs > 500000ll
1753                && mAudioPlayer != NULL
1754                && mAudioPlayer->getMediaTimeMapping(
1755                    &realTimeUs, &mediaTimeUs)) {
1756            if (mWVMExtractor == NULL) {
1757                ALOGI("we're much too late (%.2f secs), video skipping ahead",
1758                     latenessUs / 1E6);
1759
1760                mVideoBuffer->release();
1761                mVideoBuffer = NULL;
1762
1763                mSeeking = SEEK_VIDEO_ONLY;
1764                mSeekTimeUs = mediaTimeUs;
1765
1766                postVideoEvent_l();
1767                return;
1768            } else {
1769                // The widevine extractor doesn't deal well with seeking
1770                // audio and video independently. We'll just have to wait
1771                // until the decoder catches up, which won't be long at all.
1772                ALOGI("we're very late (%.2f secs)", latenessUs / 1E6);
1773            }
1774        }
1775
1776        if (latenessUs > 40000) {
1777            // We're more than 40ms late.
1778            ALOGV("we're late by %lld us (%.2f secs)",
1779                 latenessUs, latenessUs / 1E6);
1780
1781            if (!(mFlags & SLOW_DECODER_HACK)
1782                    || mSinceLastDropped > FRAME_DROP_FREQ)
1783            {
1784                ALOGV("we're late by %lld us (%.2f secs) dropping "
1785                     "one after %d frames",
1786                     latenessUs, latenessUs / 1E6, mSinceLastDropped);
1787
1788                mSinceLastDropped = 0;
1789                mVideoBuffer->release();
1790                mVideoBuffer = NULL;
1791
1792                {
1793                    Mutex::Autolock autoLock(mStatsLock);
1794                    ++mStats.mNumVideoFramesDropped;
1795                }
1796
1797                postVideoEvent_l();
1798                return;
1799            }
1800        }
1801
1802        if (latenessUs < -10000) {
1803            // We're more than 10ms early.
1804            postVideoEvent_l(10000);
1805            return;
1806        }
1807    }
1808
1809    if ((mNativeWindow != NULL)
1810            && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
1811        mVideoRendererIsPreview = false;
1812
1813        initRenderer_l();
1814    }
1815
1816    if (mVideoRenderer != NULL) {
1817        mSinceLastDropped++;
1818        mVideoRenderer->render(mVideoBuffer);
1819        if (!mVideoRenderingStarted) {
1820            mVideoRenderingStarted = true;
1821            notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
1822        }
1823
1824    }
1825
1826    mVideoBuffer->release();
1827    mVideoBuffer = NULL;
1828
1829    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
1830        modifyFlags(SEEK_PREVIEW, CLEAR);
1831        return;
1832    }
1833
1834    postVideoEvent_l();
1835}
1836
1837void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1838    ATRACE_CALL();
1839
1840    if (mVideoEventPending) {
1841        return;
1842    }
1843
1844    mVideoEventPending = true;
1845    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1846}
1847
1848void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1849    if (mStreamDoneEventPending) {
1850        return;
1851    }
1852    mStreamDoneEventPending = true;
1853
1854    mStreamDoneStatus = status;
1855    mQueue.postEvent(mStreamDoneEvent);
1856}
1857
1858void AwesomePlayer::postBufferingEvent_l() {
1859    if (mBufferingEventPending) {
1860        return;
1861    }
1862    mBufferingEventPending = true;
1863    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1864}
1865
1866void AwesomePlayer::postVideoLagEvent_l() {
1867    if (mVideoLagEventPending) {
1868        return;
1869    }
1870    mVideoLagEventPending = true;
1871    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1872}
1873
1874void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
1875    Mutex::Autolock autoLock(mAudioLock);
1876    if (mAudioStatusEventPending) {
1877        return;
1878    }
1879    mAudioStatusEventPending = true;
1880    // Do not honor delay when looping in order to limit audio gap
1881    if (mFlags & (LOOPING | AUTO_LOOPING)) {
1882        delayUs = 0;
1883    }
1884    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
1885}
1886
1887void AwesomePlayer::onCheckAudioStatus() {
1888    {
1889        Mutex::Autolock autoLock(mAudioLock);
1890        if (!mAudioStatusEventPending) {
1891            // Event was dispatched and while we were blocking on the mutex,
1892            // has already been cancelled.
1893            return;
1894        }
1895
1896        mAudioStatusEventPending = false;
1897    }
1898
1899    Mutex::Autolock autoLock(mLock);
1900
1901    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1902        mWatchForAudioSeekComplete = false;
1903
1904        if (!mSeekNotificationSent) {
1905            notifyListener_l(MEDIA_SEEK_COMPLETE);
1906            mSeekNotificationSent = true;
1907        }
1908
1909        mSeeking = NO_SEEK;
1910    }
1911
1912    status_t finalStatus;
1913    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1914        mWatchForAudioEOS = false;
1915        modifyFlags(AUDIO_AT_EOS, SET);
1916        modifyFlags(FIRST_FRAME, SET);
1917        postStreamDoneEvent_l(finalStatus);
1918    }
1919}
1920
1921status_t AwesomePlayer::prepare() {
1922    ATRACE_CALL();
1923    Mutex::Autolock autoLock(mLock);
1924    return prepare_l();
1925}
1926
1927status_t AwesomePlayer::prepare_l() {
1928    if (mFlags & PREPARED) {
1929        return OK;
1930    }
1931
1932    if (mFlags & PREPARING) {
1933        return UNKNOWN_ERROR;
1934    }
1935
1936    mIsAsyncPrepare = false;
1937    status_t err = prepareAsync_l();
1938
1939    if (err != OK) {
1940        return err;
1941    }
1942
1943    while (mFlags & PREPARING) {
1944        mPreparedCondition.wait(mLock);
1945    }
1946
1947    return mPrepareResult;
1948}
1949
1950status_t AwesomePlayer::prepareAsync() {
1951    ATRACE_CALL();
1952    Mutex::Autolock autoLock(mLock);
1953
1954    if (mFlags & PREPARING) {
1955        return UNKNOWN_ERROR;  // async prepare already pending
1956    }
1957
1958    mIsAsyncPrepare = true;
1959    return prepareAsync_l();
1960}
1961
1962status_t AwesomePlayer::prepareAsync_l() {
1963    if (mFlags & PREPARING) {
1964        return UNKNOWN_ERROR;  // async prepare already pending
1965    }
1966
1967    if (!mQueueStarted) {
1968        mQueue.start();
1969        mQueueStarted = true;
1970    }
1971
1972    modifyFlags(PREPARING, SET);
1973    mAsyncPrepareEvent = new AwesomeEvent(
1974            this, &AwesomePlayer::onPrepareAsyncEvent);
1975
1976    mQueue.postEvent(mAsyncPrepareEvent);
1977
1978    return OK;
1979}
1980
1981status_t AwesomePlayer::finishSetDataSource_l() {
1982    ATRACE_CALL();
1983    sp<DataSource> dataSource;
1984
1985    bool isWidevineStreaming = false;
1986    if (!strncasecmp("widevine://", mUri.string(), 11)) {
1987        isWidevineStreaming = true;
1988
1989        String8 newURI = String8("http://");
1990        newURI.append(mUri.string() + 11);
1991
1992        mUri = newURI;
1993    }
1994
1995    AString sniffedMIME;
1996
1997    if (!strncasecmp("http://", mUri.string(), 7)
1998            || !strncasecmp("https://", mUri.string(), 8)
1999            || isWidevineStreaming) {
2000        mConnectingDataSource = HTTPBase::Create(
2001                (mFlags & INCOGNITO)
2002                    ? HTTPBase::kFlagIncognito
2003                    : 0);
2004
2005        if (mUIDValid) {
2006            mConnectingDataSource->setUID(mUID);
2007        }
2008
2009        String8 cacheConfig;
2010        bool disconnectAtHighwatermark;
2011        NuCachedSource2::RemoveCacheSpecificHeaders(
2012                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
2013
2014        mLock.unlock();
2015        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
2016        mLock.lock();
2017
2018        if (err != OK) {
2019            mConnectingDataSource.clear();
2020
2021            ALOGI("mConnectingDataSource->connect() returned %d", err);
2022            return err;
2023        }
2024
2025        if (!isWidevineStreaming) {
2026            // The widevine extractor does its own caching.
2027
2028#if 0
2029            mCachedSource = new NuCachedSource2(
2030                    new ThrottledSource(
2031                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
2032#else
2033            mCachedSource = new NuCachedSource2(
2034                    mConnectingDataSource,
2035                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
2036                    disconnectAtHighwatermark);
2037#endif
2038
2039            dataSource = mCachedSource;
2040        } else {
2041            dataSource = mConnectingDataSource;
2042        }
2043
2044        mConnectingDataSource.clear();
2045
2046        String8 contentType = dataSource->getMIMEType();
2047
2048        if (strncasecmp(contentType.string(), "audio/", 6)) {
2049            // We're not doing this for streams that appear to be audio-only
2050            // streams to ensure that even low bandwidth streams start
2051            // playing back fairly instantly.
2052
2053            // We're going to prefill the cache before trying to instantiate
2054            // the extractor below, as the latter is an operation that otherwise
2055            // could block on the datasource for a significant amount of time.
2056            // During that time we'd be unable to abort the preparation phase
2057            // without this prefill.
2058            if (mCachedSource != NULL) {
2059                // We're going to prefill the cache before trying to instantiate
2060                // the extractor below, as the latter is an operation that otherwise
2061                // could block on the datasource for a significant amount of time.
2062                // During that time we'd be unable to abort the preparation phase
2063                // without this prefill.
2064
2065                mLock.unlock();
2066
2067                // Initially make sure we have at least 192 KB for the sniff
2068                // to complete without blocking.
2069                static const size_t kMinBytesForSniffing = 192 * 1024;
2070
2071                off64_t metaDataSize = -1ll;
2072                for (;;) {
2073                    status_t finalStatus;
2074                    size_t cachedDataRemaining =
2075                        mCachedSource->approxDataRemaining(&finalStatus);
2076
2077                    if (finalStatus != OK
2078                            || (metaDataSize >= 0
2079                                && cachedDataRemaining >= metaDataSize)
2080                            || (mFlags & PREPARE_CANCELLED)) {
2081                        break;
2082                    }
2083
2084                    ALOGV("now cached %d bytes of data", cachedDataRemaining);
2085
2086                    if (metaDataSize < 0
2087                            && cachedDataRemaining >= kMinBytesForSniffing) {
2088                        String8 tmp;
2089                        float confidence;
2090                        sp<AMessage> meta;
2091                        if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2092                            mLock.lock();
2093                            return UNKNOWN_ERROR;
2094                        }
2095
2096                        // We successfully identified the file's extractor to
2097                        // be, remember this mime type so we don't have to
2098                        // sniff it again when we call MediaExtractor::Create()
2099                        // below.
2100                        sniffedMIME = tmp.string();
2101
2102                        if (meta == NULL
2103                                || !meta->findInt64(
2104                                    "meta-data-size", &metaDataSize)) {
2105                            metaDataSize = kHighWaterMarkBytes;
2106                        }
2107
2108                        CHECK_GE(metaDataSize, 0ll);
2109                        ALOGV("metaDataSize = %lld bytes", metaDataSize);
2110                    }
2111
2112                    usleep(200000);
2113                }
2114
2115                mLock.lock();
2116            }
2117
2118            if (mFlags & PREPARE_CANCELLED) {
2119                ALOGI("Prepare cancelled while waiting for initial cache fill.");
2120                return UNKNOWN_ERROR;
2121            }
2122        }
2123    } else {
2124        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2125    }
2126
2127    if (dataSource == NULL) {
2128        return UNKNOWN_ERROR;
2129    }
2130
2131    sp<MediaExtractor> extractor;
2132
2133    if (isWidevineStreaming) {
2134        String8 mimeType;
2135        float confidence;
2136        sp<AMessage> dummy;
2137        bool success;
2138
2139        // SniffWVM is potentially blocking since it may require network access.
2140        // Do not call it with mLock held.
2141        mLock.unlock();
2142        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
2143        mLock.lock();
2144
2145        if (!success
2146                || strcasecmp(
2147                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2148            return ERROR_UNSUPPORTED;
2149        }
2150
2151        mWVMExtractor = new WVMExtractor(dataSource);
2152        mWVMExtractor->setAdaptiveStreamingMode(true);
2153        if (mUIDValid)
2154            mWVMExtractor->setUID(mUID);
2155        extractor = mWVMExtractor;
2156    } else {
2157        extractor = MediaExtractor::Create(
2158                dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
2159
2160        if (extractor == NULL) {
2161            return UNKNOWN_ERROR;
2162        }
2163    }
2164
2165    if (extractor->getDrmFlag()) {
2166        checkDrmStatus(dataSource);
2167    }
2168
2169    status_t err = setDataSource_l(extractor);
2170
2171    if (err != OK) {
2172        mWVMExtractor.clear();
2173
2174        return err;
2175    }
2176
2177    return OK;
2178}
2179
2180void AwesomePlayer::abortPrepare(status_t err) {
2181    CHECK(err != OK);
2182
2183    if (mIsAsyncPrepare) {
2184        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2185    }
2186
2187    mPrepareResult = err;
2188    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2189    mAsyncPrepareEvent = NULL;
2190    mPreparedCondition.broadcast();
2191}
2192
2193// static
2194bool AwesomePlayer::ContinuePreparation(void *cookie) {
2195    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2196
2197    return (me->mFlags & PREPARE_CANCELLED) == 0;
2198}
2199
2200void AwesomePlayer::onPrepareAsyncEvent() {
2201    Mutex::Autolock autoLock(mLock);
2202
2203    if (mFlags & PREPARE_CANCELLED) {
2204        ALOGI("prepare was cancelled before doing anything");
2205        abortPrepare(UNKNOWN_ERROR);
2206        return;
2207    }
2208
2209    if (mUri.size() > 0) {
2210        status_t err = finishSetDataSource_l();
2211
2212        if (err != OK) {
2213            abortPrepare(err);
2214            return;
2215        }
2216    }
2217
2218    if (mVideoTrack != NULL && mVideoSource == NULL) {
2219        status_t err = initVideoDecoder();
2220
2221        if (err != OK) {
2222            abortPrepare(err);
2223            return;
2224        }
2225    }
2226
2227    if (mAudioTrack != NULL && mAudioSource == NULL) {
2228        status_t err = initAudioDecoder();
2229
2230        if (err != OK) {
2231            abortPrepare(err);
2232            return;
2233        }
2234    }
2235
2236    modifyFlags(PREPARING_CONNECTED, SET);
2237
2238    if (isStreamingHTTP()) {
2239        postBufferingEvent_l();
2240    } else {
2241        finishAsyncPrepare_l();
2242    }
2243}
2244
2245void AwesomePlayer::finishAsyncPrepare_l() {
2246    if (mIsAsyncPrepare) {
2247        if (mVideoSource == NULL) {
2248            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2249        } else {
2250            notifyVideoSize_l();
2251        }
2252
2253        notifyListener_l(MEDIA_PREPARED);
2254    }
2255
2256    mPrepareResult = OK;
2257    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2258    modifyFlags(PREPARED, SET);
2259    mAsyncPrepareEvent = NULL;
2260    mPreparedCondition.broadcast();
2261}
2262
2263uint32_t AwesomePlayer::flags() const {
2264    return mExtractorFlags;
2265}
2266
2267void AwesomePlayer::postAudioEOS(int64_t delayUs) {
2268    postCheckAudioStatusEvent(delayUs);
2269}
2270
2271void AwesomePlayer::postAudioSeekComplete() {
2272    postCheckAudioStatusEvent(0);
2273}
2274
2275status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
2276    switch (key) {
2277        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2278        {
2279            return setCacheStatCollectFreq(request);
2280        }
2281        case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
2282        {
2283            if (mAudioPlayer != NULL) {
2284                return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
2285            } else {
2286                return NO_INIT;
2287            }
2288        }
2289        default:
2290        {
2291            return ERROR_UNSUPPORTED;
2292        }
2293    }
2294}
2295
2296status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2297    if (mCachedSource != NULL) {
2298        int32_t freqMs = request.readInt32();
2299        ALOGD("Request to keep cache stats in the past %d ms",
2300            freqMs);
2301        return mCachedSource->setCacheStatCollectFreq(freqMs);
2302    }
2303    return ERROR_UNSUPPORTED;
2304}
2305
2306status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
2307    switch (key) {
2308    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2309        {
2310            int32_t channelCount;
2311            if (mAudioTrack == 0 ||
2312                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2313                channelCount = 0;
2314            }
2315            reply->writeInt32(channelCount);
2316        }
2317        return OK;
2318    default:
2319        {
2320            return ERROR_UNSUPPORTED;
2321        }
2322    }
2323}
2324
2325status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
2326    Mutex::Autolock autoLock(mLock);
2327    size_t trackCount = mExtractor->countTracks();
2328    if (mTextDriver != NULL) {
2329        trackCount += mTextDriver->countExternalTracks();
2330    }
2331
2332    reply->writeInt32(trackCount);
2333    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
2334        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2335
2336        const char *_mime;
2337        CHECK(meta->findCString(kKeyMIMEType, &_mime));
2338
2339        String8 mime = String8(_mime);
2340
2341        reply->writeInt32(2); // 2 fields
2342
2343        if (!strncasecmp(mime.string(), "video/", 6)) {
2344            reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
2345        } else if (!strncasecmp(mime.string(), "audio/", 6)) {
2346            reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
2347        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
2348            reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
2349        } else {
2350            reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
2351        }
2352
2353        const char *lang;
2354        if (!meta->findCString(kKeyMediaLanguage, &lang)) {
2355            lang = "und";
2356        }
2357        reply->writeString16(String16(lang));
2358    }
2359
2360    if (mTextDriver != NULL) {
2361        mTextDriver->getExternalTrackInfo(reply);
2362    }
2363    return OK;
2364}
2365
2366status_t AwesomePlayer::selectAudioTrack_l(
2367        const sp<MediaSource>& source, size_t trackIndex) {
2368
2369    ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags);
2370
2371    {
2372        Mutex::Autolock autoLock(mStatsLock);
2373        if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
2374            ALOGI("Track %d is active. Does nothing.", trackIndex);
2375            return OK;
2376        }
2377        //mStats.mFlags = mFlags;
2378    }
2379
2380    if (mSeeking != NO_SEEK) {
2381        ALOGE("Selecting a track while seeking is not supported");
2382        return ERROR_UNSUPPORTED;
2383    }
2384
2385    if ((mFlags & PREPARED) == 0) {
2386        ALOGE("Data source has not finished preparation");
2387        return ERROR_UNSUPPORTED;
2388    }
2389
2390    CHECK(source != NULL);
2391    bool wasPlaying = (mFlags & PLAYING) != 0;
2392
2393    pause_l();
2394
2395    int64_t curTimeUs;
2396    CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
2397
2398    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
2399            && mAudioSource != NULL) {
2400        // If we had an audio player, it would have effectively
2401        // taken possession of the audio source and stopped it when
2402        // _it_ is stopped. Otherwise this is still our responsibility.
2403        mAudioSource->stop();
2404    }
2405    mAudioSource.clear();
2406
2407    mTimeSource = NULL;
2408
2409    delete mAudioPlayer;
2410    mAudioPlayer = NULL;
2411
2412    modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
2413
2414    setAudioSource(source);
2415
2416    modifyFlags(AUDIO_AT_EOS, CLEAR);
2417    modifyFlags(AT_EOS, CLEAR);
2418
2419    status_t err;
2420    if ((err = initAudioDecoder()) != OK) {
2421        ALOGE("Failed to init audio decoder: 0x%x", err);
2422        return err;
2423    }
2424
2425    mSeekNotificationSent = true;
2426    seekTo_l(curTimeUs);
2427
2428    if (wasPlaying) {
2429        play_l();
2430    }
2431
2432    mActiveAudioTrackIndex = trackIndex;
2433
2434    return OK;
2435}
2436
2437status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
2438    ATRACE_CALL();
2439    ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
2440    Mutex::Autolock autoLock(mLock);
2441    size_t trackCount = mExtractor->countTracks();
2442    if (mTextDriver != NULL) {
2443        trackCount += mTextDriver->countExternalTracks();
2444    }
2445    if (trackIndex >= trackCount) {
2446        ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount);
2447        return ERROR_OUT_OF_RANGE;
2448    }
2449
2450    bool isAudioTrack = false;
2451    if (trackIndex < mExtractor->countTracks()) {
2452        sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
2453        const char *mime;
2454        CHECK(meta->findCString(kKeyMIMEType, &mime));
2455        isAudioTrack = !strncasecmp(mime, "audio/", 6);
2456
2457        if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) {
2458            ALOGE("Track %d is not either audio or timed text", trackIndex);
2459            return ERROR_UNSUPPORTED;
2460        }
2461    }
2462
2463    if (isAudioTrack) {
2464        if (!select) {
2465            ALOGE("Deselect an audio track (%d) is not supported", trackIndex);
2466            return ERROR_UNSUPPORTED;
2467        }
2468        return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
2469    }
2470
2471    // Timed text track handling
2472    if (mTextDriver == NULL) {
2473        return INVALID_OPERATION;
2474    }
2475
2476    status_t err = OK;
2477    if (select) {
2478        err = mTextDriver->selectTrack(trackIndex);
2479        if (err == OK) {
2480            modifyFlags(TEXTPLAYER_INITIALIZED, SET);
2481            if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
2482                mTextDriver->start();
2483                modifyFlags(TEXT_RUNNING, SET);
2484            }
2485        }
2486    } else {
2487        err = mTextDriver->unselectTrack(trackIndex);
2488        if (err == OK) {
2489            modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
2490            modifyFlags(TEXT_RUNNING, CLEAR);
2491        }
2492    }
2493    return err;
2494}
2495
2496size_t AwesomePlayer::countTracks() const {
2497    return mExtractor->countTracks() + mTextDriver->countExternalTracks();
2498}
2499
2500status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
2501    Mutex::Autolock lock(mLock);
2502    return setVideoScalingMode_l(mode);
2503}
2504
2505status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
2506    mVideoScalingMode = mode;
2507    if (mNativeWindow != NULL) {
2508        status_t err = native_window_set_scaling_mode(
2509                mNativeWindow.get(), mVideoScalingMode);
2510        if (err != OK) {
2511            ALOGW("Failed to set scaling mode: %d", err);
2512        }
2513        return err;
2514    }
2515    return OK;
2516}
2517
2518status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
2519    ATRACE_CALL();
2520    if (NULL == reply) {
2521        return android::BAD_VALUE;
2522    }
2523    int32_t methodId;
2524    status_t ret = request.readInt32(&methodId);
2525    if (ret != android::OK) {
2526        return ret;
2527    }
2528    switch(methodId) {
2529        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
2530        {
2531            int mode = request.readInt32();
2532            return setVideoScalingMode(mode);
2533        }
2534
2535        case INVOKE_ID_GET_TRACK_INFO:
2536        {
2537            return getTrackInfo(reply);
2538        }
2539        case INVOKE_ID_ADD_EXTERNAL_SOURCE:
2540        {
2541            Mutex::Autolock autoLock(mLock);
2542            if (mTextDriver == NULL) {
2543                mTextDriver = new TimedTextDriver(mListener);
2544            }
2545            // String values written in Parcel are UTF-16 values.
2546            String8 uri(request.readString16());
2547            String8 mimeType(request.readString16());
2548            size_t nTracks = countTracks();
2549            return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
2550        }
2551        case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
2552        {
2553            Mutex::Autolock autoLock(mLock);
2554            if (mTextDriver == NULL) {
2555                mTextDriver = new TimedTextDriver(mListener);
2556            }
2557            int fd         = request.readFileDescriptor();
2558            off64_t offset = request.readInt64();
2559            off64_t length  = request.readInt64();
2560            String8 mimeType(request.readString16());
2561            size_t nTracks = countTracks();
2562            return mTextDriver->addOutOfBandTextSource(
2563                    nTracks, fd, offset, length, mimeType);
2564        }
2565        case INVOKE_ID_SELECT_TRACK:
2566        {
2567            int trackIndex = request.readInt32();
2568            return selectTrack(trackIndex, true /* select */);
2569        }
2570        case INVOKE_ID_UNSELECT_TRACK:
2571        {
2572            int trackIndex = request.readInt32();
2573            return selectTrack(trackIndex, false /* select */);
2574        }
2575        default:
2576        {
2577            return ERROR_UNSUPPORTED;
2578        }
2579    }
2580    // It will not reach here.
2581    return OK;
2582}
2583
2584bool AwesomePlayer::isStreamingHTTP() const {
2585    return mCachedSource != NULL || mWVMExtractor != NULL;
2586}
2587
2588status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2589    Mutex::Autolock autoLock(mStatsLock);
2590
2591    FILE *out = fdopen(dup(fd), "w");
2592
2593    fprintf(out, " AwesomePlayer\n");
2594    if (mStats.mFd < 0) {
2595        fprintf(out, "  URI(suppressed)");
2596    } else {
2597        fprintf(out, "  fd(%d)", mStats.mFd);
2598    }
2599
2600    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2601
2602    if (mStats.mBitrate >= 0) {
2603        fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2604    }
2605
2606    fprintf(out, "\n");
2607
2608    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2609        const TrackStat &stat = mStats.mTracks.itemAt(i);
2610
2611        fprintf(out, "  Track %d\n", i + 1);
2612        fprintf(out, "   MIME(%s)", stat.mMIME.string());
2613
2614        if (!stat.mDecoderName.isEmpty()) {
2615            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2616        }
2617
2618        fprintf(out, "\n");
2619
2620        if ((ssize_t)i == mStats.mVideoTrackIndex) {
2621            fprintf(out,
2622                    "   videoDimensions(%d x %d), "
2623                    "numVideoFramesDecoded(%lld), "
2624                    "numVideoFramesDropped(%lld)\n",
2625                    mStats.mVideoWidth,
2626                    mStats.mVideoHeight,
2627                    mStats.mNumVideoFramesDecoded,
2628                    mStats.mNumVideoFramesDropped);
2629        }
2630    }
2631
2632    fclose(out);
2633    out = NULL;
2634
2635    return OK;
2636}
2637
2638void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2639    switch (mode) {
2640        case SET:
2641            mFlags |= value;
2642            break;
2643        case CLEAR:
2644            if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) {
2645                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
2646            }
2647            mFlags &= ~value;
2648            break;
2649        case ASSIGN:
2650            mFlags = value;
2651            break;
2652        default:
2653            TRESPASS();
2654    }
2655
2656    {
2657        Mutex::Autolock autoLock(mStatsLock);
2658        mStats.mFlags = mFlags;
2659    }
2660}
2661
2662}  // namespace android
2663