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