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