AwesomePlayer.cpp revision c374dae535b83d9b499dd9fe8f9dabdb8b0ac9fd
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/ISurfaceTexture.h>
52#include <gui/SurfaceTextureClient.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    if (!(mFlags & INCOGNITO)) {
285        ALOGI("setDataSource_l('%s')", mUri.string());
286    } else {
287        ALOGI("setDataSource_l(URL suppressed)");
288    }
289
290    // The actual work will be done during preparation in the call to
291    // ::finishSetDataSource_l to avoid blocking the calling thread in
292    // setDataSource for any significant time.
293
294    {
295        Mutex::Autolock autoLock(mStatsLock);
296        mStats.mFd = -1;
297        mStats.mURI = mUri;
298    }
299
300    return OK;
301}
302
303status_t AwesomePlayer::setDataSource(
304        int fd, int64_t offset, int64_t length) {
305    Mutex::Autolock autoLock(mLock);
306
307    reset_l();
308
309    sp<DataSource> dataSource = new FileSource(fd, offset, length);
310
311    status_t err = dataSource->initCheck();
312
313    if (err != OK) {
314        return err;
315    }
316
317    mFileSource = dataSource;
318
319    {
320        Mutex::Autolock autoLock(mStatsLock);
321        mStats.mFd = fd;
322        mStats.mURI = String8();
323    }
324
325    return setDataSource_l(dataSource);
326}
327
328status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
329    return INVALID_OPERATION;
330}
331
332status_t AwesomePlayer::setDataSource_l(
333        const sp<DataSource> &dataSource) {
334    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
335
336    if (extractor == NULL) {
337        return UNKNOWN_ERROR;
338    }
339
340    if (extractor->getDrmFlag()) {
341        checkDrmStatus(dataSource);
342    }
343
344    return setDataSource_l(extractor);
345}
346
347void AwesomePlayer::checkDrmStatus(const sp<DataSource>& dataSource) {
348    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
349    if (mDecryptHandle != NULL) {
350        CHECK(mDrmManagerClient);
351        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
352            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
353        }
354    }
355}
356
357status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
358    // Attempt to approximate overall stream bitrate by summing all
359    // tracks' individual bitrates, if not all of them advertise bitrate,
360    // we have to fail.
361
362    int64_t totalBitRate = 0;
363
364    mExtractor = extractor;
365    for (size_t i = 0; i < extractor->countTracks(); ++i) {
366        sp<MetaData> meta = extractor->getTrackMetaData(i);
367
368        int32_t bitrate;
369        if (!meta->findInt32(kKeyBitRate, &bitrate)) {
370            const char *mime;
371            CHECK(meta->findCString(kKeyMIMEType, &mime));
372            ALOGV("track of type '%s' does not publish bitrate", mime);
373
374            totalBitRate = -1;
375            break;
376        }
377
378        totalBitRate += bitrate;
379    }
380
381    mBitrate = totalBitRate;
382
383    ALOGV("mBitrate = %lld bits/sec", mBitrate);
384
385    {
386        Mutex::Autolock autoLock(mStatsLock);
387        mStats.mBitrate = mBitrate;
388        mStats.mTracks.clear();
389        mStats.mAudioTrackIndex = -1;
390        mStats.mVideoTrackIndex = -1;
391    }
392
393    bool haveAudio = false;
394    bool haveVideo = false;
395    for (size_t i = 0; i < extractor->countTracks(); ++i) {
396        sp<MetaData> meta = extractor->getTrackMetaData(i);
397
398        const char *_mime;
399        CHECK(meta->findCString(kKeyMIMEType, &_mime));
400
401        String8 mime = String8(_mime);
402
403        if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
404            setVideoSource(extractor->getTrack(i));
405            haveVideo = true;
406
407            // Set the presentation/display size
408            int32_t displayWidth, displayHeight;
409            bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
410            if (success) {
411                success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
412            }
413            if (success) {
414                mDisplayWidth = displayWidth;
415                mDisplayHeight = displayHeight;
416            }
417
418            {
419                Mutex::Autolock autoLock(mStatsLock);
420                mStats.mVideoTrackIndex = mStats.mTracks.size();
421                mStats.mTracks.push();
422                TrackStat *stat =
423                    &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
424                stat->mMIME = mime.string();
425            }
426        } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
427            setAudioSource(extractor->getTrack(i));
428            haveAudio = true;
429            mActiveAudioTrackIndex = i;
430
431            {
432                Mutex::Autolock autoLock(mStatsLock);
433                mStats.mAudioTrackIndex = mStats.mTracks.size();
434                mStats.mTracks.push();
435                TrackStat *stat =
436                    &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
437                stat->mMIME = mime.string();
438            }
439
440            if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) {
441                // Only do this for vorbis audio, none of the other audio
442                // formats even support this ringtone specific hack and
443                // retrieving the metadata on some extractors may turn out
444                // to be very expensive.
445                sp<MetaData> fileMeta = extractor->getMetaData();
446                int32_t loop;
447                if (fileMeta != NULL
448                        && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
449                    modifyFlags(AUTO_LOOPING, SET);
450                }
451            }
452        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
453            addTextSource_l(i, extractor->getTrack(i));
454        }
455    }
456
457    if (!haveAudio && !haveVideo) {
458        return UNKNOWN_ERROR;
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            if (mWVMExtractor == NULL) {
759                ALOGI("cache is running low (%.2f secs) , pausing.",
760                      cachedDurationUs / 1E6);
761                pause_l();
762                ensureCacheIsFetching_l();
763                sendCacheStats();
764            }
765            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
766        } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
767            if (mFlags & CACHE_UNDERRUN) {
768                modifyFlags(CACHE_UNDERRUN, CLEAR);
769                if (mWVMExtractor == NULL) {
770                    ALOGI("cache has filled up (%.2f secs), resuming.",
771                          cachedDurationUs / 1E6);
772                    play_l();
773                }
774            } else if (mFlags & PREPARING) {
775                ALOGV("cache has filled up (%.2f secs), prepare is done",
776                     cachedDurationUs / 1E6);
777                finishAsyncPrepare_l();
778            }
779        }
780    }
781
782    postBufferingEvent_l();
783}
784
785void AwesomePlayer::sendCacheStats() {
786    sp<MediaPlayerBase> listener = mListener.promote();
787    if (listener != NULL && mCachedSource != NULL) {
788        int32_t kbps = 0;
789        status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
790        if (err == OK) {
791            listener->sendEvent(
792                MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
793        }
794    }
795}
796
797void AwesomePlayer::onStreamDone() {
798    // Posted whenever any stream finishes playing.
799    ATRACE_CALL();
800
801    Mutex::Autolock autoLock(mLock);
802    if (!mStreamDoneEventPending) {
803        return;
804    }
805    mStreamDoneEventPending = false;
806
807    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
808        ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
809
810        notifyListener_l(
811                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
812
813        pause_l(true /* at eos */);
814
815        modifyFlags(AT_EOS, SET);
816        return;
817    }
818
819    const bool allDone =
820        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
821            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
822
823    if (!allDone) {
824        return;
825    }
826
827    if ((mFlags & LOOPING)
828            || ((mFlags & AUTO_LOOPING)
829                && (mAudioSink == NULL || mAudioSink->realtime()))) {
830        // Don't AUTO_LOOP if we're being recorded, since that cannot be
831        // turned off and recording would go on indefinitely.
832
833        seekTo_l(0);
834
835        if (mVideoSource != NULL) {
836            postVideoEvent_l();
837        }
838    } else {
839        ALOGV("MEDIA_PLAYBACK_COMPLETE");
840        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
841
842        pause_l(true /* at eos */);
843
844        modifyFlags(AT_EOS, SET);
845    }
846}
847
848status_t AwesomePlayer::play() {
849    ATRACE_CALL();
850
851    Mutex::Autolock autoLock(mLock);
852
853    modifyFlags(CACHE_UNDERRUN, CLEAR);
854
855    return play_l();
856}
857
858status_t AwesomePlayer::play_l() {
859    modifyFlags(SEEK_PREVIEW, CLEAR);
860
861    if (mFlags & PLAYING) {
862        return OK;
863    }
864
865    if (!(mFlags & PREPARED)) {
866        status_t err = prepare_l();
867
868        if (err != OK) {
869            return err;
870        }
871    }
872
873    modifyFlags(PLAYING, SET);
874    modifyFlags(FIRST_FRAME, SET);
875
876    if (mDecryptHandle != NULL) {
877        int64_t position;
878        getPosition(&position);
879        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
880                Playback::START, position / 1000);
881    }
882
883    if (mAudioSource != NULL) {
884        if (mAudioPlayer == NULL) {
885            if (mAudioSink != NULL) {
886                bool allowDeepBuffering;
887                int64_t cachedDurationUs;
888                bool eos;
889                if (mVideoSource == NULL
890                        && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||
891                        (getCachedDuration_l(&cachedDurationUs, &eos) &&
892                        cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) {
893                    allowDeepBuffering = true;
894                } else {
895                    allowDeepBuffering = false;
896                }
897
898                mAudioPlayer = new AudioPlayer(mAudioSink, allowDeepBuffering, this);
899                mAudioPlayer->setSource(mAudioSource);
900
901                mTimeSource = mAudioPlayer;
902
903                // If there was a seek request before we ever started,
904                // honor the request now.
905                // Make sure to do this before starting the audio player
906                // to avoid a race condition.
907                seekAudioIfNecessary_l();
908            }
909        }
910
911        CHECK(!(mFlags & AUDIO_RUNNING));
912
913        if (mVideoSource == NULL) {
914            // We don't want to post an error notification at this point,
915            // the error returned from MediaPlayer::start() will suffice.
916
917            status_t err = startAudioPlayer_l(
918                    false /* sendErrorNotification */);
919
920            if (err != OK) {
921                delete mAudioPlayer;
922                mAudioPlayer = NULL;
923
924                modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
925
926                if (mDecryptHandle != NULL) {
927                    mDrmManagerClient->setPlaybackStatus(
928                            mDecryptHandle, Playback::STOP, 0);
929                }
930
931                return err;
932            }
933        }
934    }
935
936    if (mTimeSource == NULL && mAudioPlayer == NULL) {
937        mTimeSource = &mSystemTimeSource;
938    }
939
940    if (mVideoSource != NULL) {
941        // Kick off video playback
942        postVideoEvent_l();
943
944        if (mAudioSource != NULL && mVideoSource != NULL) {
945            postVideoLagEvent_l();
946        }
947    }
948
949    if (mFlags & AT_EOS) {
950        // Legacy behaviour, if a stream finishes playing and then
951        // is started again, we play from the start...
952        seekTo_l(0);
953    }
954
955    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
956        | IMediaPlayerService::kBatteryDataTrackDecoder;
957    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
958        params |= IMediaPlayerService::kBatteryDataTrackAudio;
959    }
960    if (mVideoSource != NULL) {
961        params |= IMediaPlayerService::kBatteryDataTrackVideo;
962    }
963    addBatteryData(params);
964
965    return OK;
966}
967
968status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
969    CHECK(!(mFlags & AUDIO_RUNNING));
970
971    if (mAudioSource == NULL || mAudioPlayer == NULL) {
972        return OK;
973    }
974
975    if (!(mFlags & AUDIOPLAYER_STARTED)) {
976        bool wasSeeking = mAudioPlayer->isSeeking();
977
978        // We've already started the MediaSource in order to enable
979        // the prefetcher to read its data.
980        status_t err = mAudioPlayer->start(
981                true /* sourceAlreadyStarted */);
982
983        if (err != OK) {
984            if (sendErrorNotification) {
985                notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
986            }
987
988            return err;
989        }
990
991        modifyFlags(AUDIOPLAYER_STARTED, SET);
992
993        if (wasSeeking) {
994            CHECK(!mAudioPlayer->isSeeking());
995
996            // We will have finished the seek while starting the audio player.
997            postAudioSeekComplete();
998        }
999    } else {
1000        mAudioPlayer->resume();
1001    }
1002
1003    modifyFlags(AUDIO_RUNNING, SET);
1004
1005    mWatchForAudioEOS = true;
1006
1007    return OK;
1008}
1009
1010void AwesomePlayer::notifyVideoSize_l() {
1011    ATRACE_CALL();
1012    sp<MetaData> meta = mVideoSource->getFormat();
1013
1014    int32_t cropLeft, cropTop, cropRight, cropBottom;
1015    if (!meta->findRect(
1016                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1017        int32_t width, height;
1018        CHECK(meta->findInt32(kKeyWidth, &width));
1019        CHECK(meta->findInt32(kKeyHeight, &height));
1020
1021        cropLeft = cropTop = 0;
1022        cropRight = width - 1;
1023        cropBottom = height - 1;
1024
1025        ALOGV("got dimensions only %d x %d", width, height);
1026    } else {
1027        ALOGV("got crop rect %d, %d, %d, %d",
1028             cropLeft, cropTop, cropRight, cropBottom);
1029    }
1030
1031    int32_t displayWidth;
1032    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1033        ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1034        mDisplayWidth = displayWidth;
1035    }
1036    int32_t displayHeight;
1037    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1038        ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1039        mDisplayHeight = displayHeight;
1040    }
1041
1042    int32_t usableWidth = cropRight - cropLeft + 1;
1043    int32_t usableHeight = cropBottom - cropTop + 1;
1044    if (mDisplayWidth != 0) {
1045        usableWidth = mDisplayWidth;
1046    }
1047    if (mDisplayHeight != 0) {
1048        usableHeight = mDisplayHeight;
1049    }
1050
1051    {
1052        Mutex::Autolock autoLock(mStatsLock);
1053        mStats.mVideoWidth = usableWidth;
1054        mStats.mVideoHeight = usableHeight;
1055    }
1056
1057    int32_t rotationDegrees;
1058    if (!mVideoTrack->getFormat()->findInt32(
1059                kKeyRotation, &rotationDegrees)) {
1060        rotationDegrees = 0;
1061    }
1062
1063    if (rotationDegrees == 90 || rotationDegrees == 270) {
1064        notifyListener_l(
1065                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1066    } else {
1067        notifyListener_l(
1068                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1069    }
1070}
1071
1072void AwesomePlayer::initRenderer_l() {
1073    ATRACE_CALL();
1074
1075    if (mNativeWindow == NULL) {
1076        return;
1077    }
1078
1079    sp<MetaData> meta = mVideoSource->getFormat();
1080
1081    int32_t format;
1082    const char *component;
1083    int32_t decodedWidth, decodedHeight;
1084    CHECK(meta->findInt32(kKeyColorFormat, &format));
1085    CHECK(meta->findCString(kKeyDecoderComponent, &component));
1086    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1087    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
1088
1089    int32_t rotationDegrees;
1090    if (!mVideoTrack->getFormat()->findInt32(
1091                kKeyRotation, &rotationDegrees)) {
1092        rotationDegrees = 0;
1093    }
1094
1095    mVideoRenderer.clear();
1096
1097    // Must ensure that mVideoRenderer's destructor is actually executed
1098    // before creating a new one.
1099    IPCThreadState::self()->flushCommands();
1100
1101    // Even if set scaling mode fails, we will continue anyway
1102    setVideoScalingMode_l(mVideoScalingMode);
1103    if (USE_SURFACE_ALLOC
1104            && !strncmp(component, "OMX.", 4)
1105            && strncmp(component, "OMX.google.", 11)
1106            && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) {
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<ISurfaceTexture> &surfaceTexture) {
1181    Mutex::Autolock autoLock(mLock);
1182
1183    status_t err;
1184    if (surfaceTexture != NULL) {
1185        err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
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            mVideoSource.clear();
1507            return err;
1508        }
1509    }
1510
1511    if (mVideoSource != NULL) {
1512        const char *componentName;
1513        CHECK(mVideoSource->getFormat()
1514                ->findCString(kKeyDecoderComponent, &componentName));
1515
1516        {
1517            Mutex::Autolock autoLock(mStatsLock);
1518            TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1519
1520            stat->mDecoderName = componentName;
1521        }
1522
1523        static const char *kPrefix = "OMX.Nvidia.";
1524        static const char *kSuffix = ".decode";
1525        static const size_t kSuffixLength = strlen(kSuffix);
1526
1527        size_t componentNameLength = strlen(componentName);
1528
1529        if (!strncmp(componentName, kPrefix, strlen(kPrefix))
1530                && componentNameLength >= kSuffixLength
1531                && !strcmp(&componentName[
1532                    componentNameLength - kSuffixLength], kSuffix)) {
1533            modifyFlags(SLOW_DECODER_HACK, SET);
1534        }
1535    }
1536
1537    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1538}
1539
1540void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1541    ATRACE_CALL();
1542
1543    if (mSeeking == SEEK_VIDEO_ONLY) {
1544        mSeeking = NO_SEEK;
1545        return;
1546    }
1547
1548    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1549        return;
1550    }
1551
1552    if (mAudioPlayer != NULL) {
1553        ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1554
1555        // If we don't have a video time, seek audio to the originally
1556        // requested seek time instead.
1557
1558        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1559        mWatchForAudioSeekComplete = true;
1560        mWatchForAudioEOS = true;
1561    } else if (!mSeekNotificationSent) {
1562        // If we're playing video only, report seek complete now,
1563        // otherwise audio player will notify us later.
1564        notifyListener_l(MEDIA_SEEK_COMPLETE);
1565        mSeekNotificationSent = true;
1566    }
1567
1568    modifyFlags(FIRST_FRAME, SET);
1569    mSeeking = NO_SEEK;
1570
1571    if (mDecryptHandle != NULL) {
1572        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1573                Playback::PAUSE, 0);
1574        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1575                Playback::START, videoTimeUs / 1000);
1576    }
1577}
1578
1579void AwesomePlayer::onVideoEvent() {
1580    ATRACE_CALL();
1581    Mutex::Autolock autoLock(mLock);
1582    if (!mVideoEventPending) {
1583        // The event has been cancelled in reset_l() but had already
1584        // been scheduled for execution at that time.
1585        return;
1586    }
1587    mVideoEventPending = false;
1588
1589    if (mSeeking != NO_SEEK) {
1590        if (mVideoBuffer) {
1591            mVideoBuffer->release();
1592            mVideoBuffer = NULL;
1593        }
1594
1595        if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
1596                && !(mFlags & SEEK_PREVIEW)) {
1597            // We're going to seek the video source first, followed by
1598            // the audio source.
1599            // In order to avoid jumps in the DataSource offset caused by
1600            // the audio codec prefetching data from the old locations
1601            // while the video codec is already reading data from the new
1602            // locations, we'll "pause" the audio source, causing it to
1603            // stop reading input data until a subsequent seek.
1604
1605            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1606                mAudioPlayer->pause();
1607
1608                modifyFlags(AUDIO_RUNNING, CLEAR);
1609            }
1610            mAudioSource->pause();
1611        }
1612    }
1613
1614    if (!mVideoBuffer) {
1615        MediaSource::ReadOptions options;
1616        if (mSeeking != NO_SEEK) {
1617            ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1618
1619            options.setSeekTo(
1620                    mSeekTimeUs,
1621                    mSeeking == SEEK_VIDEO_ONLY
1622                        ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1623                        : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1624        }
1625        for (;;) {
1626            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1627            options.clearSeekTo();
1628
1629            if (err != OK) {
1630                CHECK(mVideoBuffer == NULL);
1631
1632                if (err == INFO_FORMAT_CHANGED) {
1633                    ALOGV("VideoSource signalled format change.");
1634
1635                    notifyVideoSize_l();
1636
1637                    if (mVideoRenderer != NULL) {
1638                        mVideoRendererIsPreview = false;
1639                        initRenderer_l();
1640                    }
1641                    continue;
1642                }
1643
1644                // So video playback is complete, but we may still have
1645                // a seek request pending that needs to be applied
1646                // to the audio track.
1647                if (mSeeking != NO_SEEK) {
1648                    ALOGV("video stream ended while seeking!");
1649                }
1650                finishSeekIfNecessary(-1);
1651
1652                if (mAudioPlayer != NULL
1653                        && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1654                    startAudioPlayer_l();
1655                }
1656
1657                modifyFlags(VIDEO_AT_EOS, SET);
1658                postStreamDoneEvent_l(err);
1659                return;
1660            }
1661
1662            if (mVideoBuffer->range_length() == 0) {
1663                // Some decoders, notably the PV AVC software decoder
1664                // return spurious empty buffers that we just want to ignore.
1665
1666                mVideoBuffer->release();
1667                mVideoBuffer = NULL;
1668                continue;
1669            }
1670
1671            break;
1672        }
1673
1674        {
1675            Mutex::Autolock autoLock(mStatsLock);
1676            ++mStats.mNumVideoFramesDecoded;
1677        }
1678    }
1679
1680    int64_t timeUs;
1681    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1682
1683    mLastVideoTimeUs = timeUs;
1684
1685    if (mSeeking == SEEK_VIDEO_ONLY) {
1686        if (mSeekTimeUs > timeUs) {
1687            ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1688                 mSeekTimeUs, timeUs);
1689        }
1690    }
1691
1692    {
1693        Mutex::Autolock autoLock(mMiscStateLock);
1694        mVideoTimeUs = timeUs;
1695    }
1696
1697    SeekType wasSeeking = mSeeking;
1698    finishSeekIfNecessary(timeUs);
1699
1700    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1701        status_t err = startAudioPlayer_l();
1702        if (err != OK) {
1703            ALOGE("Starting the audio player failed w/ err %d", err);
1704            return;
1705        }
1706    }
1707
1708    if ((mFlags & TEXTPLAYER_INITIALIZED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1709        mTextDriver->start();
1710        modifyFlags(TEXT_RUNNING, SET);
1711    }
1712
1713    TimeSource *ts =
1714        ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
1715            ? &mSystemTimeSource : mTimeSource;
1716
1717    if (mFlags & FIRST_FRAME) {
1718        modifyFlags(FIRST_FRAME, CLEAR);
1719        mSinceLastDropped = 0;
1720        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1721    }
1722
1723    int64_t realTimeUs, mediaTimeUs;
1724    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1725        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1726        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1727    }
1728
1729    if (wasSeeking == SEEK_VIDEO_ONLY) {
1730        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1731
1732        int64_t latenessUs = nowUs - timeUs;
1733
1734        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1735
1736        if (latenessUs > 0) {
1737            ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1738        }
1739    }
1740
1741    if (wasSeeking == NO_SEEK) {
1742        // Let's display the first frame after seeking right away.
1743
1744        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1745
1746        int64_t latenessUs = nowUs - timeUs;
1747
1748        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1749
1750        if (latenessUs > 500000ll
1751                && mAudioPlayer != NULL
1752                && mAudioPlayer->getMediaTimeMapping(
1753                    &realTimeUs, &mediaTimeUs)) {
1754            ALOGI("we're much too late (%.2f secs), video skipping ahead",
1755                 latenessUs / 1E6);
1756
1757            mVideoBuffer->release();
1758            mVideoBuffer = NULL;
1759
1760            mSeeking = SEEK_VIDEO_ONLY;
1761            mSeekTimeUs = mediaTimeUs;
1762
1763            postVideoEvent_l();
1764            return;
1765        }
1766
1767        if (latenessUs > 40000) {
1768            // We're more than 40ms late.
1769            ALOGV("we're late by %lld us (%.2f secs)",
1770                 latenessUs, latenessUs / 1E6);
1771
1772            if (!(mFlags & SLOW_DECODER_HACK)
1773                    || mSinceLastDropped > FRAME_DROP_FREQ)
1774            {
1775                ALOGV("we're late by %lld us (%.2f secs) dropping "
1776                     "one after %d frames",
1777                     latenessUs, latenessUs / 1E6, mSinceLastDropped);
1778
1779                mSinceLastDropped = 0;
1780                mVideoBuffer->release();
1781                mVideoBuffer = NULL;
1782
1783                {
1784                    Mutex::Autolock autoLock(mStatsLock);
1785                    ++mStats.mNumVideoFramesDropped;
1786                }
1787
1788                postVideoEvent_l();
1789                return;
1790            }
1791        }
1792
1793        if (latenessUs < -10000) {
1794            // We're more than 10ms early.
1795            postVideoEvent_l(10000);
1796            return;
1797        }
1798    }
1799
1800    if ((mNativeWindow != NULL)
1801            && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
1802        mVideoRendererIsPreview = false;
1803
1804        initRenderer_l();
1805    }
1806
1807    if (mVideoRenderer != NULL) {
1808        mSinceLastDropped++;
1809        mVideoRenderer->render(mVideoBuffer);
1810        if (!mVideoRenderingStarted) {
1811            mVideoRenderingStarted = true;
1812            notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
1813        }
1814
1815    }
1816
1817    mVideoBuffer->release();
1818    mVideoBuffer = NULL;
1819
1820    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
1821        modifyFlags(SEEK_PREVIEW, CLEAR);
1822        return;
1823    }
1824
1825    postVideoEvent_l();
1826}
1827
1828void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1829    ATRACE_CALL();
1830
1831    if (mVideoEventPending) {
1832        return;
1833    }
1834
1835    mVideoEventPending = true;
1836    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1837}
1838
1839void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1840    if (mStreamDoneEventPending) {
1841        return;
1842    }
1843    mStreamDoneEventPending = true;
1844
1845    mStreamDoneStatus = status;
1846    mQueue.postEvent(mStreamDoneEvent);
1847}
1848
1849void AwesomePlayer::postBufferingEvent_l() {
1850    if (mBufferingEventPending) {
1851        return;
1852    }
1853    mBufferingEventPending = true;
1854    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1855}
1856
1857void AwesomePlayer::postVideoLagEvent_l() {
1858    if (mVideoLagEventPending) {
1859        return;
1860    }
1861    mVideoLagEventPending = true;
1862    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1863}
1864
1865void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
1866    Mutex::Autolock autoLock(mAudioLock);
1867    if (mAudioStatusEventPending) {
1868        return;
1869    }
1870    mAudioStatusEventPending = true;
1871    // Do not honor delay when looping in order to limit audio gap
1872    if (mFlags & (LOOPING | AUTO_LOOPING)) {
1873        delayUs = 0;
1874    }
1875    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
1876}
1877
1878void AwesomePlayer::onCheckAudioStatus() {
1879    {
1880        Mutex::Autolock autoLock(mAudioLock);
1881        if (!mAudioStatusEventPending) {
1882            // Event was dispatched and while we were blocking on the mutex,
1883            // has already been cancelled.
1884            return;
1885        }
1886
1887        mAudioStatusEventPending = false;
1888    }
1889
1890    Mutex::Autolock autoLock(mLock);
1891
1892    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1893        mWatchForAudioSeekComplete = false;
1894
1895        if (!mSeekNotificationSent) {
1896            notifyListener_l(MEDIA_SEEK_COMPLETE);
1897            mSeekNotificationSent = true;
1898        }
1899
1900        mSeeking = NO_SEEK;
1901    }
1902
1903    status_t finalStatus;
1904    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1905        mWatchForAudioEOS = false;
1906        modifyFlags(AUDIO_AT_EOS, SET);
1907        modifyFlags(FIRST_FRAME, SET);
1908        postStreamDoneEvent_l(finalStatus);
1909    }
1910}
1911
1912status_t AwesomePlayer::prepare() {
1913    ATRACE_CALL();
1914    Mutex::Autolock autoLock(mLock);
1915    return prepare_l();
1916}
1917
1918status_t AwesomePlayer::prepare_l() {
1919    if (mFlags & PREPARED) {
1920        return OK;
1921    }
1922
1923    if (mFlags & PREPARING) {
1924        return UNKNOWN_ERROR;
1925    }
1926
1927    mIsAsyncPrepare = false;
1928    status_t err = prepareAsync_l();
1929
1930    if (err != OK) {
1931        return err;
1932    }
1933
1934    while (mFlags & PREPARING) {
1935        mPreparedCondition.wait(mLock);
1936    }
1937
1938    return mPrepareResult;
1939}
1940
1941status_t AwesomePlayer::prepareAsync() {
1942    ATRACE_CALL();
1943    Mutex::Autolock autoLock(mLock);
1944
1945    if (mFlags & PREPARING) {
1946        return UNKNOWN_ERROR;  // async prepare already pending
1947    }
1948
1949    mIsAsyncPrepare = true;
1950    return prepareAsync_l();
1951}
1952
1953status_t AwesomePlayer::prepareAsync_l() {
1954    if (mFlags & PREPARING) {
1955        return UNKNOWN_ERROR;  // async prepare already pending
1956    }
1957
1958    if (!mQueueStarted) {
1959        mQueue.start();
1960        mQueueStarted = true;
1961    }
1962
1963    modifyFlags(PREPARING, SET);
1964    mAsyncPrepareEvent = new AwesomeEvent(
1965            this, &AwesomePlayer::onPrepareAsyncEvent);
1966
1967    mQueue.postEvent(mAsyncPrepareEvent);
1968
1969    return OK;
1970}
1971
1972status_t AwesomePlayer::finishSetDataSource_l() {
1973    ATRACE_CALL();
1974    sp<DataSource> dataSource;
1975
1976    bool isWidevineStreaming = false;
1977    if (!strncasecmp("widevine://", mUri.string(), 11)) {
1978        isWidevineStreaming = true;
1979
1980        String8 newURI = String8("http://");
1981        newURI.append(mUri.string() + 11);
1982
1983        mUri = newURI;
1984    }
1985
1986    AString sniffedMIME;
1987
1988    if (!strncasecmp("http://", mUri.string(), 7)
1989            || !strncasecmp("https://", mUri.string(), 8)
1990            || isWidevineStreaming) {
1991        mConnectingDataSource = HTTPBase::Create(
1992                (mFlags & INCOGNITO)
1993                    ? HTTPBase::kFlagIncognito
1994                    : 0);
1995
1996        if (mUIDValid) {
1997            mConnectingDataSource->setUID(mUID);
1998        }
1999
2000        String8 cacheConfig;
2001        bool disconnectAtHighwatermark;
2002        NuCachedSource2::RemoveCacheSpecificHeaders(
2003                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
2004
2005        mLock.unlock();
2006        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
2007        mLock.lock();
2008
2009        if (err != OK) {
2010            mConnectingDataSource.clear();
2011
2012            ALOGI("mConnectingDataSource->connect() returned %d", err);
2013            return err;
2014        }
2015
2016        if (!isWidevineStreaming) {
2017            // The widevine extractor does its own caching.
2018
2019#if 0
2020            mCachedSource = new NuCachedSource2(
2021                    new ThrottledSource(
2022                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
2023#else
2024            mCachedSource = new NuCachedSource2(
2025                    mConnectingDataSource,
2026                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
2027                    disconnectAtHighwatermark);
2028#endif
2029
2030            dataSource = mCachedSource;
2031        } else {
2032            dataSource = mConnectingDataSource;
2033        }
2034
2035        mConnectingDataSource.clear();
2036
2037        String8 contentType = dataSource->getMIMEType();
2038
2039        if (strncasecmp(contentType.string(), "audio/", 6)) {
2040            // We're not doing this for streams that appear to be audio-only
2041            // streams to ensure that even low bandwidth streams start
2042            // playing back fairly instantly.
2043
2044            // We're going to prefill the cache before trying to instantiate
2045            // the extractor below, as the latter is an operation that otherwise
2046            // could block on the datasource for a significant amount of time.
2047            // During that time we'd be unable to abort the preparation phase
2048            // without this prefill.
2049            if (mCachedSource != NULL) {
2050                // We're going to prefill the cache before trying to instantiate
2051                // the extractor below, as the latter is an operation that otherwise
2052                // could block on the datasource for a significant amount of time.
2053                // During that time we'd be unable to abort the preparation phase
2054                // without this prefill.
2055
2056                mLock.unlock();
2057
2058                // Initially make sure we have at least 192 KB for the sniff
2059                // to complete without blocking.
2060                static const size_t kMinBytesForSniffing = 192 * 1024;
2061
2062                off64_t metaDataSize = -1ll;
2063                for (;;) {
2064                    status_t finalStatus;
2065                    size_t cachedDataRemaining =
2066                        mCachedSource->approxDataRemaining(&finalStatus);
2067
2068                    if (finalStatus != OK
2069                            || (metaDataSize >= 0
2070                                && cachedDataRemaining >= metaDataSize)
2071                            || (mFlags & PREPARE_CANCELLED)) {
2072                        break;
2073                    }
2074
2075                    ALOGV("now cached %d bytes of data", cachedDataRemaining);
2076
2077                    if (metaDataSize < 0
2078                            && cachedDataRemaining >= kMinBytesForSniffing) {
2079                        String8 tmp;
2080                        float confidence;
2081                        sp<AMessage> meta;
2082                        if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2083                            mLock.lock();
2084                            return UNKNOWN_ERROR;
2085                        }
2086
2087                        // We successfully identified the file's extractor to
2088                        // be, remember this mime type so we don't have to
2089                        // sniff it again when we call MediaExtractor::Create()
2090                        // below.
2091                        sniffedMIME = tmp.string();
2092
2093                        if (meta == NULL
2094                                || !meta->findInt64(
2095                                    "meta-data-size", &metaDataSize)) {
2096                            metaDataSize = kHighWaterMarkBytes;
2097                        }
2098
2099                        CHECK_GE(metaDataSize, 0ll);
2100                        ALOGV("metaDataSize = %lld bytes", metaDataSize);
2101                    }
2102
2103                    usleep(200000);
2104                }
2105
2106                mLock.lock();
2107            }
2108
2109            if (mFlags & PREPARE_CANCELLED) {
2110                ALOGI("Prepare cancelled while waiting for initial cache fill.");
2111                return UNKNOWN_ERROR;
2112            }
2113        }
2114    } else {
2115        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2116    }
2117
2118    if (dataSource == NULL) {
2119        return UNKNOWN_ERROR;
2120    }
2121
2122    sp<MediaExtractor> extractor;
2123
2124    if (isWidevineStreaming) {
2125        String8 mimeType;
2126        float confidence;
2127        sp<AMessage> dummy;
2128        bool success;
2129
2130        // SniffWVM is potentially blocking since it may require network access.
2131        // Do not call it with mLock held.
2132        mLock.unlock();
2133        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
2134        mLock.lock();
2135
2136        if (!success
2137                || strcasecmp(
2138                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2139            return ERROR_UNSUPPORTED;
2140        }
2141
2142        mWVMExtractor = new WVMExtractor(dataSource);
2143        mWVMExtractor->setAdaptiveStreamingMode(true);
2144        if (mUIDValid)
2145            mWVMExtractor->setUID(mUID);
2146        extractor = mWVMExtractor;
2147    } else {
2148        extractor = MediaExtractor::Create(
2149                dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
2150
2151        if (extractor == NULL) {
2152            return UNKNOWN_ERROR;
2153        }
2154    }
2155
2156    if (extractor->getDrmFlag()) {
2157        checkDrmStatus(dataSource);
2158    }
2159
2160    status_t err = setDataSource_l(extractor);
2161
2162    if (err != OK) {
2163        mWVMExtractor.clear();
2164
2165        return err;
2166    }
2167
2168    return OK;
2169}
2170
2171void AwesomePlayer::abortPrepare(status_t err) {
2172    CHECK(err != OK);
2173
2174    if (mIsAsyncPrepare) {
2175        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2176    }
2177
2178    mPrepareResult = err;
2179    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2180    mAsyncPrepareEvent = NULL;
2181    mPreparedCondition.broadcast();
2182}
2183
2184// static
2185bool AwesomePlayer::ContinuePreparation(void *cookie) {
2186    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2187
2188    return (me->mFlags & PREPARE_CANCELLED) == 0;
2189}
2190
2191void AwesomePlayer::onPrepareAsyncEvent() {
2192    Mutex::Autolock autoLock(mLock);
2193
2194    if (mFlags & PREPARE_CANCELLED) {
2195        ALOGI("prepare was cancelled before doing anything");
2196        abortPrepare(UNKNOWN_ERROR);
2197        return;
2198    }
2199
2200    if (mUri.size() > 0) {
2201        status_t err = finishSetDataSource_l();
2202
2203        if (err != OK) {
2204            abortPrepare(err);
2205            return;
2206        }
2207    }
2208
2209    if (mVideoTrack != NULL && mVideoSource == NULL) {
2210        status_t err = initVideoDecoder();
2211
2212        if (err != OK) {
2213            abortPrepare(err);
2214            return;
2215        }
2216    }
2217
2218    if (mAudioTrack != NULL && mAudioSource == NULL) {
2219        status_t err = initAudioDecoder();
2220
2221        if (err != OK) {
2222            abortPrepare(err);
2223            return;
2224        }
2225    }
2226
2227    modifyFlags(PREPARING_CONNECTED, SET);
2228
2229    if (isStreamingHTTP()) {
2230        postBufferingEvent_l();
2231    } else {
2232        finishAsyncPrepare_l();
2233    }
2234}
2235
2236void AwesomePlayer::finishAsyncPrepare_l() {
2237    if (mIsAsyncPrepare) {
2238        if (mVideoSource == NULL) {
2239            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2240        } else {
2241            notifyVideoSize_l();
2242        }
2243
2244        notifyListener_l(MEDIA_PREPARED);
2245    }
2246
2247    mPrepareResult = OK;
2248    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2249    modifyFlags(PREPARED, SET);
2250    mAsyncPrepareEvent = NULL;
2251    mPreparedCondition.broadcast();
2252}
2253
2254uint32_t AwesomePlayer::flags() const {
2255    return mExtractorFlags;
2256}
2257
2258void AwesomePlayer::postAudioEOS(int64_t delayUs) {
2259    postCheckAudioStatusEvent(delayUs);
2260}
2261
2262void AwesomePlayer::postAudioSeekComplete() {
2263    postCheckAudioStatusEvent(0);
2264}
2265
2266status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
2267    switch (key) {
2268        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2269        {
2270            return setCacheStatCollectFreq(request);
2271        }
2272        case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
2273        {
2274            if (mAudioPlayer != NULL) {
2275                return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
2276            } else {
2277                return NO_INIT;
2278            }
2279        }
2280        default:
2281        {
2282            return ERROR_UNSUPPORTED;
2283        }
2284    }
2285}
2286
2287status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2288    if (mCachedSource != NULL) {
2289        int32_t freqMs = request.readInt32();
2290        ALOGD("Request to keep cache stats in the past %d ms",
2291            freqMs);
2292        return mCachedSource->setCacheStatCollectFreq(freqMs);
2293    }
2294    return ERROR_UNSUPPORTED;
2295}
2296
2297status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
2298    switch (key) {
2299    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2300        {
2301            int32_t channelCount;
2302            if (mAudioTrack == 0 ||
2303                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2304                channelCount = 0;
2305            }
2306            reply->writeInt32(channelCount);
2307        }
2308        return OK;
2309    default:
2310        {
2311            return ERROR_UNSUPPORTED;
2312        }
2313    }
2314}
2315
2316status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
2317    Mutex::Autolock autoLock(mLock);
2318    size_t trackCount = mExtractor->countTracks();
2319    if (mTextDriver != NULL) {
2320        trackCount += mTextDriver->countExternalTracks();
2321    }
2322
2323    reply->writeInt32(trackCount);
2324    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
2325        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2326
2327        const char *_mime;
2328        CHECK(meta->findCString(kKeyMIMEType, &_mime));
2329
2330        String8 mime = String8(_mime);
2331
2332        reply->writeInt32(2); // 2 fields
2333
2334        if (!strncasecmp(mime.string(), "video/", 6)) {
2335            reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
2336        } else if (!strncasecmp(mime.string(), "audio/", 6)) {
2337            reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
2338        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
2339            reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
2340        } else {
2341            reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
2342        }
2343
2344        const char *lang;
2345        if (!meta->findCString(kKeyMediaLanguage, &lang)) {
2346            lang = "und";
2347        }
2348        reply->writeString16(String16(lang));
2349    }
2350
2351    if (mTextDriver != NULL) {
2352        mTextDriver->getExternalTrackInfo(reply);
2353    }
2354    return OK;
2355}
2356
2357status_t AwesomePlayer::selectAudioTrack_l(
2358        const sp<MediaSource>& source, size_t trackIndex) {
2359
2360    ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags);
2361
2362    {
2363        Mutex::Autolock autoLock(mStatsLock);
2364        if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
2365            ALOGI("Track %d is active. Does nothing.", trackIndex);
2366            return OK;
2367        }
2368        //mStats.mFlags = mFlags;
2369    }
2370
2371    if (mSeeking != NO_SEEK) {
2372        ALOGE("Selecting a track while seeking is not supported");
2373        return ERROR_UNSUPPORTED;
2374    }
2375
2376    if ((mFlags & PREPARED) == 0) {
2377        ALOGE("Data source has not finished preparation");
2378        return ERROR_UNSUPPORTED;
2379    }
2380
2381    CHECK(source != NULL);
2382    bool wasPlaying = (mFlags & PLAYING) != 0;
2383
2384    pause_l();
2385
2386    int64_t curTimeUs;
2387    CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
2388
2389    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
2390            && mAudioSource != NULL) {
2391        // If we had an audio player, it would have effectively
2392        // taken possession of the audio source and stopped it when
2393        // _it_ is stopped. Otherwise this is still our responsibility.
2394        mAudioSource->stop();
2395    }
2396    mAudioSource.clear();
2397
2398    mTimeSource = NULL;
2399
2400    delete mAudioPlayer;
2401    mAudioPlayer = NULL;
2402
2403    modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
2404
2405    setAudioSource(source);
2406
2407    modifyFlags(AUDIO_AT_EOS, CLEAR);
2408    modifyFlags(AT_EOS, CLEAR);
2409
2410    status_t err;
2411    if ((err = initAudioDecoder()) != OK) {
2412        ALOGE("Failed to init audio decoder: 0x%x", err);
2413        return err;
2414    }
2415
2416    mSeekNotificationSent = true;
2417    seekTo_l(curTimeUs);
2418
2419    if (wasPlaying) {
2420        play_l();
2421    }
2422
2423    mActiveAudioTrackIndex = trackIndex;
2424
2425    return OK;
2426}
2427
2428status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
2429    ATRACE_CALL();
2430    ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
2431    Mutex::Autolock autoLock(mLock);
2432    size_t trackCount = mExtractor->countTracks();
2433    if (mTextDriver != NULL) {
2434        trackCount += mTextDriver->countExternalTracks();
2435    }
2436    if (trackIndex >= trackCount) {
2437        ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount);
2438        return ERROR_OUT_OF_RANGE;
2439    }
2440
2441    bool isAudioTrack = false;
2442    if (trackIndex < mExtractor->countTracks()) {
2443        sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
2444        const char *mime;
2445        CHECK(meta->findCString(kKeyMIMEType, &mime));
2446        isAudioTrack = !strncasecmp(mime, "audio/", 6);
2447
2448        if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) {
2449            ALOGE("Track %d is not either audio or timed text", trackIndex);
2450            return ERROR_UNSUPPORTED;
2451        }
2452    }
2453
2454    if (isAudioTrack) {
2455        if (!select) {
2456            ALOGE("Deselect an audio track (%d) is not supported", trackIndex);
2457            return ERROR_UNSUPPORTED;
2458        }
2459        return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
2460    }
2461
2462    // Timed text track handling
2463    if (mTextDriver == NULL) {
2464        return INVALID_OPERATION;
2465    }
2466
2467    status_t err = OK;
2468    if (select) {
2469        err = mTextDriver->selectTrack(trackIndex);
2470        if (err == OK) {
2471            modifyFlags(TEXTPLAYER_INITIALIZED, SET);
2472            if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
2473                mTextDriver->start();
2474                modifyFlags(TEXT_RUNNING, SET);
2475            }
2476        }
2477    } else {
2478        err = mTextDriver->unselectTrack(trackIndex);
2479        if (err == OK) {
2480            modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
2481            modifyFlags(TEXT_RUNNING, CLEAR);
2482        }
2483    }
2484    return err;
2485}
2486
2487size_t AwesomePlayer::countTracks() const {
2488    return mExtractor->countTracks() + mTextDriver->countExternalTracks();
2489}
2490
2491status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
2492    Mutex::Autolock lock(mLock);
2493    return setVideoScalingMode_l(mode);
2494}
2495
2496status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
2497    mVideoScalingMode = mode;
2498    if (mNativeWindow != NULL) {
2499        status_t err = native_window_set_scaling_mode(
2500                mNativeWindow.get(), mVideoScalingMode);
2501        if (err != OK) {
2502            ALOGW("Failed to set scaling mode: %d", err);
2503        }
2504    }
2505    return OK;
2506}
2507
2508status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
2509    ATRACE_CALL();
2510    if (NULL == reply) {
2511        return android::BAD_VALUE;
2512    }
2513    int32_t methodId;
2514    status_t ret = request.readInt32(&methodId);
2515    if (ret != android::OK) {
2516        return ret;
2517    }
2518    switch(methodId) {
2519        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
2520        {
2521            int mode = request.readInt32();
2522            return setVideoScalingMode(mode);
2523        }
2524
2525        case INVOKE_ID_GET_TRACK_INFO:
2526        {
2527            return getTrackInfo(reply);
2528        }
2529        case INVOKE_ID_ADD_EXTERNAL_SOURCE:
2530        {
2531            Mutex::Autolock autoLock(mLock);
2532            if (mTextDriver == NULL) {
2533                mTextDriver = new TimedTextDriver(mListener);
2534            }
2535            // String values written in Parcel are UTF-16 values.
2536            String8 uri(request.readString16());
2537            String8 mimeType(request.readString16());
2538            size_t nTracks = countTracks();
2539            return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
2540        }
2541        case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
2542        {
2543            Mutex::Autolock autoLock(mLock);
2544            if (mTextDriver == NULL) {
2545                mTextDriver = new TimedTextDriver(mListener);
2546            }
2547            int fd         = request.readFileDescriptor();
2548            off64_t offset = request.readInt64();
2549            off64_t length  = request.readInt64();
2550            String8 mimeType(request.readString16());
2551            size_t nTracks = countTracks();
2552            return mTextDriver->addOutOfBandTextSource(
2553                    nTracks, fd, offset, length, mimeType);
2554        }
2555        case INVOKE_ID_SELECT_TRACK:
2556        {
2557            int trackIndex = request.readInt32();
2558            return selectTrack(trackIndex, true /* select */);
2559        }
2560        case INVOKE_ID_UNSELECT_TRACK:
2561        {
2562            int trackIndex = request.readInt32();
2563            return selectTrack(trackIndex, false /* select */);
2564        }
2565        default:
2566        {
2567            return ERROR_UNSUPPORTED;
2568        }
2569    }
2570    // It will not reach here.
2571    return OK;
2572}
2573
2574bool AwesomePlayer::isStreamingHTTP() const {
2575    return mCachedSource != NULL || mWVMExtractor != NULL;
2576}
2577
2578status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2579    Mutex::Autolock autoLock(mStatsLock);
2580
2581    FILE *out = fdopen(dup(fd), "w");
2582
2583    fprintf(out, " AwesomePlayer\n");
2584    if (mStats.mFd < 0) {
2585        fprintf(out, "  URI(%s)", mStats.mURI.string());
2586    } else {
2587        fprintf(out, "  fd(%d)", mStats.mFd);
2588    }
2589
2590    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2591
2592    if (mStats.mBitrate >= 0) {
2593        fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2594    }
2595
2596    fprintf(out, "\n");
2597
2598    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2599        const TrackStat &stat = mStats.mTracks.itemAt(i);
2600
2601        fprintf(out, "  Track %d\n", i + 1);
2602        fprintf(out, "   MIME(%s)", stat.mMIME.string());
2603
2604        if (!stat.mDecoderName.isEmpty()) {
2605            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2606        }
2607
2608        fprintf(out, "\n");
2609
2610        if ((ssize_t)i == mStats.mVideoTrackIndex) {
2611            fprintf(out,
2612                    "   videoDimensions(%d x %d), "
2613                    "numVideoFramesDecoded(%lld), "
2614                    "numVideoFramesDropped(%lld)\n",
2615                    mStats.mVideoWidth,
2616                    mStats.mVideoHeight,
2617                    mStats.mNumVideoFramesDecoded,
2618                    mStats.mNumVideoFramesDropped);
2619        }
2620    }
2621
2622    fclose(out);
2623    out = NULL;
2624
2625    return OK;
2626}
2627
2628void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2629    switch (mode) {
2630        case SET:
2631            mFlags |= value;
2632            break;
2633        case CLEAR:
2634            if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) {
2635                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
2636            }
2637            mFlags &= ~value;
2638            break;
2639        case ASSIGN:
2640            mFlags = value;
2641            break;
2642        default:
2643            TRESPASS();
2644    }
2645
2646    {
2647        Mutex::Autolock autoLock(mStatsLock);
2648        mStats.mFlags = mFlags;
2649    }
2650}
2651
2652}  // namespace android
2653