AwesomePlayer.cpp revision cdef698dae0c6dd89755f6494cc3d4b163f410ef
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#include <utils/Log.h>
22
23#include <dlfcn.h>
24
25#include "include/ARTSPController.h"
26#include "include/AwesomePlayer.h"
27#include "include/DRMExtractor.h"
28#include "include/SoftwareRenderer.h"
29#include "include/NuCachedSource2.h"
30#include "include/ThrottledSource.h"
31#include "include/MPEG2TSExtractor.h"
32#include "include/WVMExtractor.h"
33
34#include "timedtext/TimedTextPlayer.h"
35
36#include <binder/IPCThreadState.h>
37#include <binder/IServiceManager.h>
38#include <media/IMediaPlayerService.h>
39#include <media/stagefright/foundation/hexdump.h>
40#include <media/stagefright/foundation/ADebug.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 <surfaceflinger/Surface.h>
52#include <gui/ISurfaceTexture.h>
53#include <gui/SurfaceTextureClient.h>
54#include <surfaceflinger/ISurfaceComposer.h>
55
56#include <media/stagefright/foundation/ALooper.h>
57#include <media/stagefright/foundation/AMessage.h>
58
59#include <cutils/properties.h>
60
61#define USE_SURFACE_ALLOC 1
62
63namespace android {
64
65static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
66static int64_t kHighWaterMarkUs = 5000000ll;  // 5secs
67static int64_t kHighWaterMarkRTSPUs = 4000000ll;  // 4secs
68static const size_t kLowWaterMarkBytes = 40000;
69static const size_t kHighWaterMarkBytes = 200000;
70
71struct AwesomeEvent : public TimedEventQueue::Event {
72    AwesomeEvent(
73            AwesomePlayer *player,
74            void (AwesomePlayer::*method)())
75        : mPlayer(player),
76          mMethod(method) {
77    }
78
79protected:
80    virtual ~AwesomeEvent() {}
81
82    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
83        (mPlayer->*mMethod)();
84    }
85
86private:
87    AwesomePlayer *mPlayer;
88    void (AwesomePlayer::*mMethod)();
89
90    AwesomeEvent(const AwesomeEvent &);
91    AwesomeEvent &operator=(const AwesomeEvent &);
92};
93
94struct AwesomeLocalRenderer : public AwesomeRenderer {
95    AwesomeLocalRenderer(
96            const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
97        : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
98    }
99
100    virtual void render(MediaBuffer *buffer) {
101        render((const uint8_t *)buffer->data() + buffer->range_offset(),
102               buffer->range_length());
103    }
104
105    void render(const void *data, size_t size) {
106        mTarget->render(data, size, NULL);
107    }
108
109protected:
110    virtual ~AwesomeLocalRenderer() {
111        delete mTarget;
112        mTarget = NULL;
113    }
114
115private:
116    SoftwareRenderer *mTarget;
117
118    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
119    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
120};
121
122struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
123    AwesomeNativeWindowRenderer(
124            const sp<ANativeWindow> &nativeWindow,
125            int32_t rotationDegrees)
126        : mNativeWindow(nativeWindow) {
127        applyRotation(rotationDegrees);
128    }
129
130    virtual void render(MediaBuffer *buffer) {
131        int64_t timeUs;
132        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
133        native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);
134        status_t err = mNativeWindow->queueBuffer(
135                mNativeWindow.get(), buffer->graphicBuffer().get());
136        if (err != 0) {
137            LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
138                    -err);
139            return;
140        }
141
142        sp<MetaData> metaData = buffer->meta_data();
143        metaData->setInt32(kKeyRendered, 1);
144    }
145
146protected:
147    virtual ~AwesomeNativeWindowRenderer() {}
148
149private:
150    sp<ANativeWindow> mNativeWindow;
151
152    void applyRotation(int32_t rotationDegrees) {
153        uint32_t transform;
154        switch (rotationDegrees) {
155            case 0: transform = 0; break;
156            case 90: transform = HAL_TRANSFORM_ROT_90; break;
157            case 180: transform = HAL_TRANSFORM_ROT_180; break;
158            case 270: transform = HAL_TRANSFORM_ROT_270; break;
159            default: transform = 0; break;
160        }
161
162        if (transform) {
163            CHECK_EQ(0, native_window_set_buffers_transform(
164                        mNativeWindow.get(), transform));
165        }
166    }
167
168    AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
169    AwesomeNativeWindowRenderer &operator=(
170            const AwesomeNativeWindowRenderer &);
171};
172
173// To collect the decoder usage
174void addBatteryData(uint32_t params) {
175    sp<IBinder> binder =
176        defaultServiceManager()->getService(String16("media.player"));
177    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
178    CHECK(service.get() != NULL);
179
180    service->addBatteryData(params);
181}
182
183////////////////////////////////////////////////////////////////////////////////
184AwesomePlayer::AwesomePlayer()
185    : mQueueStarted(false),
186      mUIDValid(false),
187      mTimeSource(NULL),
188      mVideoRendererIsPreview(false),
189      mAudioPlayer(NULL),
190      mDisplayWidth(0),
191      mDisplayHeight(0),
192      mFlags(0),
193      mExtractorFlags(0),
194      mVideoBuffer(NULL),
195      mDecryptHandle(NULL),
196      mLastVideoTimeUs(-1),
197      mTextPlayer(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 keepBufferingGoing) {
230    mQueue.cancelEvent(mVideoEvent->eventID());
231    mVideoEventPending = false;
232    mQueue.cancelEvent(mStreamDoneEvent->eventID());
233    mStreamDoneEventPending = false;
234    mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
235    mAudioStatusEventPending = false;
236    mQueue.cancelEvent(mVideoLagEvent->eventID());
237    mVideoLagEventPending = false;
238
239    if (!keepBufferingGoing) {
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    LOGI("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        LOGI("setDataSource_l('%s')", mUri.string());
285    } else {
286        LOGI("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    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
340    if (mDecryptHandle != NULL) {
341        CHECK(mDrmManagerClient);
342        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
343            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
344        }
345    }
346
347    return setDataSource_l(extractor);
348}
349
350status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
351    // Attempt to approximate overall stream bitrate by summing all
352    // tracks' individual bitrates, if not all of them advertise bitrate,
353    // we have to fail.
354
355    int64_t totalBitRate = 0;
356
357    for (size_t i = 0; i < extractor->countTracks(); ++i) {
358        sp<MetaData> meta = extractor->getTrackMetaData(i);
359
360        int32_t bitrate;
361        if (!meta->findInt32(kKeyBitRate, &bitrate)) {
362            const char *mime;
363            CHECK(meta->findCString(kKeyMIMEType, &mime));
364            LOGW("track of type '%s' does not publish bitrate", mime);
365
366            totalBitRate = -1;
367            break;
368        }
369
370        totalBitRate += bitrate;
371    }
372
373    mBitrate = totalBitRate;
374
375    LOGV("mBitrate = %lld bits/sec", mBitrate);
376
377    {
378        Mutex::Autolock autoLock(mStatsLock);
379        mStats.mBitrate = mBitrate;
380        mStats.mTracks.clear();
381        mStats.mAudioTrackIndex = -1;
382        mStats.mVideoTrackIndex = -1;
383    }
384
385    bool haveAudio = false;
386    bool haveVideo = false;
387    for (size_t i = 0; i < extractor->countTracks(); ++i) {
388        sp<MetaData> meta = extractor->getTrackMetaData(i);
389
390        const char *mime;
391        CHECK(meta->findCString(kKeyMIMEType, &mime));
392
393        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
394            setVideoSource(extractor->getTrack(i));
395            haveVideo = true;
396
397            // Set the presentation/display size
398            int32_t displayWidth, displayHeight;
399            bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
400            if (success) {
401                success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
402            }
403            if (success) {
404                mDisplayWidth = displayWidth;
405                mDisplayHeight = displayHeight;
406            }
407
408            {
409                Mutex::Autolock autoLock(mStatsLock);
410                mStats.mVideoTrackIndex = mStats.mTracks.size();
411                mStats.mTracks.push();
412                TrackStat *stat =
413                    &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
414                stat->mMIME = mime;
415            }
416        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
417            setAudioSource(extractor->getTrack(i));
418            haveAudio = true;
419
420            {
421                Mutex::Autolock autoLock(mStatsLock);
422                mStats.mAudioTrackIndex = mStats.mTracks.size();
423                mStats.mTracks.push();
424                TrackStat *stat =
425                    &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
426                stat->mMIME = mime;
427            }
428
429            if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
430                // Only do this for vorbis audio, none of the other audio
431                // formats even support this ringtone specific hack and
432                // retrieving the metadata on some extractors may turn out
433                // to be very expensive.
434                sp<MetaData> fileMeta = extractor->getMetaData();
435                int32_t loop;
436                if (fileMeta != NULL
437                        && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
438                    modifyFlags(AUTO_LOOPING, SET);
439                }
440            }
441        } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
442            addTextSource(extractor->getTrack(i));
443        }
444    }
445
446    if (!haveAudio && !haveVideo) {
447        return UNKNOWN_ERROR;
448    }
449
450    mExtractorFlags = extractor->flags();
451
452    return OK;
453}
454
455void AwesomePlayer::reset() {
456    Mutex::Autolock autoLock(mLock);
457    reset_l();
458}
459
460void AwesomePlayer::reset_l() {
461    mDisplayWidth = 0;
462    mDisplayHeight = 0;
463
464    if (mDecryptHandle != NULL) {
465            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
466                    Playback::STOP, 0);
467            mDecryptHandle = NULL;
468            mDrmManagerClient = NULL;
469    }
470
471    if (mFlags & PLAYING) {
472        uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
473        if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
474            params |= IMediaPlayerService::kBatteryDataTrackAudio;
475        }
476        if (mVideoSource != NULL) {
477            params |= IMediaPlayerService::kBatteryDataTrackVideo;
478        }
479        addBatteryData(params);
480    }
481
482    if (mFlags & PREPARING) {
483        modifyFlags(PREPARE_CANCELLED, SET);
484        if (mConnectingDataSource != NULL) {
485            LOGI("interrupting the connection process");
486            mConnectingDataSource->disconnect();
487        } else if (mConnectingRTSPController != NULL) {
488            LOGI("interrupting the connection process");
489            mConnectingRTSPController->disconnect();
490        }
491
492        if (mFlags & PREPARING_CONNECTED) {
493            // We are basically done preparing, we're just buffering
494            // enough data to start playback, we can safely interrupt that.
495            finishAsyncPrepare_l();
496        }
497    }
498
499    while (mFlags & PREPARING) {
500        mPreparedCondition.wait(mLock);
501    }
502
503    cancelPlayerEvents();
504
505    mWVMExtractor.clear();
506    mCachedSource.clear();
507    mAudioTrack.clear();
508    mVideoTrack.clear();
509
510    // Shutdown audio first, so that the respone to the reset request
511    // appears to happen instantaneously as far as the user is concerned
512    // If we did this later, audio would continue playing while we
513    // shutdown the video-related resources and the player appear to
514    // not be as responsive to a reset request.
515    if (mAudioPlayer == NULL && mAudioSource != NULL) {
516        // If we had an audio player, it would have effectively
517        // taken possession of the audio source and stopped it when
518        // _it_ is stopped. Otherwise this is still our responsibility.
519        mAudioSource->stop();
520    }
521    mAudioSource.clear();
522
523    mTimeSource = NULL;
524
525    delete mAudioPlayer;
526    mAudioPlayer = NULL;
527
528    if (mTextPlayer != NULL) {
529        delete mTextPlayer;
530        mTextPlayer = NULL;
531    }
532
533    mVideoRenderer.clear();
534
535    if (mRTSPController != NULL) {
536        mRTSPController->disconnect();
537        mRTSPController.clear();
538    }
539
540    if (mVideoSource != NULL) {
541        shutdownVideoDecoder_l();
542    }
543
544    mDurationUs = -1;
545    modifyFlags(0, ASSIGN);
546    mExtractorFlags = 0;
547    mTimeSourceDeltaUs = 0;
548    mVideoTimeUs = 0;
549
550    mSeeking = NO_SEEK;
551    mSeekNotificationSent = false;
552    mSeekTimeUs = 0;
553
554    mUri.setTo("");
555    mUriHeaders.clear();
556
557    mFileSource.clear();
558
559    mBitrate = -1;
560    mLastVideoTimeUs = -1;
561
562    {
563        Mutex::Autolock autoLock(mStatsLock);
564        mStats.mFd = -1;
565        mStats.mURI = String8();
566        mStats.mBitrate = -1;
567        mStats.mAudioTrackIndex = -1;
568        mStats.mVideoTrackIndex = -1;
569        mStats.mNumVideoFramesDecoded = 0;
570        mStats.mNumVideoFramesDropped = 0;
571        mStats.mVideoWidth = -1;
572        mStats.mVideoHeight = -1;
573        mStats.mFlags = 0;
574        mStats.mTracks.clear();
575    }
576
577    mWatchForAudioSeekComplete = false;
578    mWatchForAudioEOS = false;
579}
580
581void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
582    if (mListener != NULL) {
583        sp<MediaPlayerBase> listener = mListener.promote();
584
585        if (listener != NULL) {
586            listener->sendEvent(msg, ext1, ext2);
587        }
588    }
589}
590
591bool AwesomePlayer::getBitrate(int64_t *bitrate) {
592    off64_t size;
593    if (mDurationUs >= 0 && mCachedSource != NULL
594            && mCachedSource->getSize(&size) == OK) {
595        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
596        return true;
597    }
598
599    if (mBitrate >= 0) {
600        *bitrate = mBitrate;
601        return true;
602    }
603
604    *bitrate = 0;
605
606    return false;
607}
608
609// Returns true iff cached duration is available/applicable.
610bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
611    int64_t bitrate;
612
613    if (mRTSPController != NULL) {
614        *durationUs = mRTSPController->getQueueDurationUs(eos);
615        return true;
616    } else 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        LOGV("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                LOGV("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                    LOGI("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                        LOGI("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                        LOGV("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                LOGV("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        LOGV("cachedDurationUs = %.2f secs, eos=%d",
750             cachedDurationUs / 1E6, eos);
751
752        int64_t highWaterMarkUs =
753            (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
754
755        if ((mFlags & PLAYING) && !eos
756                && (cachedDurationUs < kLowWaterMarkUs)) {
757            LOGI("cache is running low (%.2f secs) , pausing.",
758                 cachedDurationUs / 1E6);
759            modifyFlags(CACHE_UNDERRUN, SET);
760            pause_l();
761            ensureCacheIsFetching_l();
762            sendCacheStats();
763            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
764        } else if (eos || cachedDurationUs > highWaterMarkUs) {
765            if (mFlags & CACHE_UNDERRUN) {
766                LOGI("cache has filled up (%.2f secs), resuming.",
767                     cachedDurationUs / 1E6);
768                modifyFlags(CACHE_UNDERRUN, CLEAR);
769                play_l();
770                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
771            } else if (mFlags & PREPARING) {
772                LOGV("cache has filled up (%.2f secs), prepare is done",
773                     cachedDurationUs / 1E6);
774                finishAsyncPrepare_l();
775            }
776        }
777    }
778
779    postBufferingEvent_l();
780}
781
782void AwesomePlayer::sendCacheStats() {
783    sp<MediaPlayerBase> listener = mListener.promote();
784    if (listener != NULL && mCachedSource != NULL) {
785        int32_t kbps = 0;
786        status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
787        if (err == OK) {
788            listener->sendEvent(
789                MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
790        }
791    }
792}
793
794void AwesomePlayer::onStreamDone() {
795    // Posted whenever any stream finishes playing.
796
797    Mutex::Autolock autoLock(mLock);
798    if (!mStreamDoneEventPending) {
799        return;
800    }
801    mStreamDoneEventPending = false;
802
803    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
804        LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
805
806        notifyListener_l(
807                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
808
809        pause_l(true /* at eos */);
810
811        modifyFlags(AT_EOS, SET);
812        return;
813    }
814
815    const bool allDone =
816        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
817            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
818
819    if (!allDone) {
820        return;
821    }
822
823    if ((mFlags & LOOPING)
824            || ((mFlags & AUTO_LOOPING)
825                && (mAudioSink == NULL || mAudioSink->realtime()))) {
826        // Don't AUTO_LOOP if we're being recorded, since that cannot be
827        // turned off and recording would go on indefinitely.
828
829        seekTo_l(0);
830
831        if (mVideoSource != NULL) {
832            postVideoEvent_l();
833        }
834    } else {
835        LOGV("MEDIA_PLAYBACK_COMPLETE");
836        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
837
838        pause_l(true /* at eos */);
839
840        modifyFlags(AT_EOS, SET);
841    }
842}
843
844status_t AwesomePlayer::play() {
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                mAudioPlayer = new AudioPlayer(mAudioSink, this);
881                mAudioPlayer->setSource(mAudioSource);
882
883                mTimeSource = mAudioPlayer;
884
885                // If there was a seek request before we ever started,
886                // honor the request now.
887                // Make sure to do this before starting the audio player
888                // to avoid a race condition.
889                seekAudioIfNecessary_l();
890            }
891        }
892
893        CHECK(!(mFlags & AUDIO_RUNNING));
894
895        if (mVideoSource == NULL) {
896            // We don't want to post an error notification at this point,
897            // the error returned from MediaPlayer::start() will suffice.
898
899            status_t err = startAudioPlayer_l(
900                    false /* sendErrorNotification */);
901
902            if (err != OK) {
903                delete mAudioPlayer;
904                mAudioPlayer = NULL;
905
906                modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
907
908                if (mDecryptHandle != NULL) {
909                    mDrmManagerClient->setPlaybackStatus(
910                            mDecryptHandle, Playback::STOP, 0);
911                }
912
913                return err;
914            }
915        }
916    }
917
918    if (mTimeSource == NULL && mAudioPlayer == NULL) {
919        mTimeSource = &mSystemTimeSource;
920    }
921
922    if (mVideoSource != NULL) {
923        // Kick off video playback
924        postVideoEvent_l();
925
926        if (mAudioSource != NULL && mVideoSource != NULL) {
927            postVideoLagEvent_l();
928        }
929    }
930
931    if (mFlags & AT_EOS) {
932        // Legacy behaviour, if a stream finishes playing and then
933        // is started again, we play from the start...
934        seekTo_l(0);
935    }
936
937    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
938        | IMediaPlayerService::kBatteryDataTrackDecoder;
939    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
940        params |= IMediaPlayerService::kBatteryDataTrackAudio;
941    }
942    if (mVideoSource != NULL) {
943        params |= IMediaPlayerService::kBatteryDataTrackVideo;
944    }
945    addBatteryData(params);
946
947    return OK;
948}
949
950status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
951    CHECK(!(mFlags & AUDIO_RUNNING));
952
953    if (mAudioSource == NULL || mAudioPlayer == NULL) {
954        return OK;
955    }
956
957    if (!(mFlags & AUDIOPLAYER_STARTED)) {
958        modifyFlags(AUDIOPLAYER_STARTED, SET);
959
960        bool wasSeeking = mAudioPlayer->isSeeking();
961
962        // We've already started the MediaSource in order to enable
963        // the prefetcher to read its data.
964        status_t err = mAudioPlayer->start(
965                true /* sourceAlreadyStarted */);
966
967        if (err != OK) {
968            if (sendErrorNotification) {
969                notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
970            }
971
972            return err;
973        }
974
975        if (wasSeeking) {
976            CHECK(!mAudioPlayer->isSeeking());
977
978            // We will have finished the seek while starting the audio player.
979            postAudioSeekComplete_l();
980        }
981    } else {
982        mAudioPlayer->resume();
983    }
984
985    modifyFlags(AUDIO_RUNNING, SET);
986
987    mWatchForAudioEOS = true;
988
989    return OK;
990}
991
992void AwesomePlayer::notifyVideoSize_l() {
993    sp<MetaData> meta = mVideoSource->getFormat();
994
995    int32_t cropLeft, cropTop, cropRight, cropBottom;
996    if (!meta->findRect(
997                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
998        int32_t width, height;
999        CHECK(meta->findInt32(kKeyWidth, &width));
1000        CHECK(meta->findInt32(kKeyHeight, &height));
1001
1002        cropLeft = cropTop = 0;
1003        cropRight = width - 1;
1004        cropBottom = height - 1;
1005
1006        LOGV("got dimensions only %d x %d", width, height);
1007    } else {
1008        LOGV("got crop rect %d, %d, %d, %d",
1009             cropLeft, cropTop, cropRight, cropBottom);
1010    }
1011
1012    int32_t displayWidth;
1013    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1014        LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1015        mDisplayWidth = displayWidth;
1016    }
1017    int32_t displayHeight;
1018    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1019        LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1020        mDisplayHeight = displayHeight;
1021    }
1022
1023    int32_t usableWidth = cropRight - cropLeft + 1;
1024    int32_t usableHeight = cropBottom - cropTop + 1;
1025    if (mDisplayWidth != 0) {
1026        usableWidth = mDisplayWidth;
1027    }
1028    if (mDisplayHeight != 0) {
1029        usableHeight = mDisplayHeight;
1030    }
1031
1032    {
1033        Mutex::Autolock autoLock(mStatsLock);
1034        mStats.mVideoWidth = usableWidth;
1035        mStats.mVideoHeight = usableHeight;
1036    }
1037
1038    int32_t rotationDegrees;
1039    if (!mVideoTrack->getFormat()->findInt32(
1040                kKeyRotation, &rotationDegrees)) {
1041        rotationDegrees = 0;
1042    }
1043
1044    if (rotationDegrees == 90 || rotationDegrees == 270) {
1045        notifyListener_l(
1046                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1047    } else {
1048        notifyListener_l(
1049                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1050    }
1051}
1052
1053void AwesomePlayer::initRenderer_l() {
1054    if (mNativeWindow == NULL) {
1055        return;
1056    }
1057
1058    sp<MetaData> meta = mVideoSource->getFormat();
1059
1060    int32_t format;
1061    const char *component;
1062    int32_t decodedWidth, decodedHeight;
1063    CHECK(meta->findInt32(kKeyColorFormat, &format));
1064    CHECK(meta->findCString(kKeyDecoderComponent, &component));
1065    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1066    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
1067
1068    int32_t rotationDegrees;
1069    if (!mVideoTrack->getFormat()->findInt32(
1070                kKeyRotation, &rotationDegrees)) {
1071        rotationDegrees = 0;
1072    }
1073
1074    mVideoRenderer.clear();
1075
1076    // Must ensure that mVideoRenderer's destructor is actually executed
1077    // before creating a new one.
1078    IPCThreadState::self()->flushCommands();
1079
1080    if (USE_SURFACE_ALLOC
1081            && !strncmp(component, "OMX.", 4)
1082            && strncmp(component, "OMX.google.", 11)) {
1083        // Hardware decoders avoid the CPU color conversion by decoding
1084        // directly to ANativeBuffers, so we must use a renderer that
1085        // just pushes those buffers to the ANativeWindow.
1086        mVideoRenderer =
1087            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
1088    } else {
1089        // Other decoders are instantiated locally and as a consequence
1090        // allocate their buffers in local address space.  This renderer
1091        // then performs a color conversion and copy to get the data
1092        // into the ANativeBuffer.
1093        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
1094    }
1095}
1096
1097status_t AwesomePlayer::pause() {
1098    Mutex::Autolock autoLock(mLock);
1099
1100    modifyFlags(CACHE_UNDERRUN, CLEAR);
1101
1102    return pause_l();
1103}
1104
1105status_t AwesomePlayer::pause_l(bool at_eos) {
1106    if (!(mFlags & PLAYING)) {
1107        return OK;
1108    }
1109
1110    cancelPlayerEvents(true /* keepBufferingGoing */);
1111
1112    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1113        if (at_eos) {
1114            // If we played the audio stream to completion we
1115            // want to make sure that all samples remaining in the audio
1116            // track's queue are played out.
1117            mAudioPlayer->pause(true /* playPendingSamples */);
1118        } else {
1119            mAudioPlayer->pause();
1120        }
1121
1122        modifyFlags(AUDIO_RUNNING, CLEAR);
1123    }
1124
1125    if (mFlags & TEXTPLAYER_STARTED) {
1126        mTextPlayer->pause();
1127        modifyFlags(TEXT_RUNNING, CLEAR);
1128    }
1129
1130    modifyFlags(PLAYING, CLEAR);
1131
1132    if (mDecryptHandle != NULL) {
1133        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1134                Playback::PAUSE, 0);
1135    }
1136
1137    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1138    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1139        params |= IMediaPlayerService::kBatteryDataTrackAudio;
1140    }
1141    if (mVideoSource != NULL) {
1142        params |= IMediaPlayerService::kBatteryDataTrackVideo;
1143    }
1144
1145    addBatteryData(params);
1146
1147    return OK;
1148}
1149
1150bool AwesomePlayer::isPlaying() const {
1151    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1152}
1153
1154void AwesomePlayer::setSurface(const sp<Surface> &surface) {
1155    Mutex::Autolock autoLock(mLock);
1156
1157    mSurface = surface;
1158    setNativeWindow_l(surface);
1159}
1160
1161void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1162    Mutex::Autolock autoLock(mLock);
1163
1164    mSurface.clear();
1165    if (surfaceTexture != NULL) {
1166        setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
1167    } else {
1168        setNativeWindow_l(NULL);
1169    }
1170}
1171
1172void AwesomePlayer::shutdownVideoDecoder_l() {
1173    if (mVideoBuffer) {
1174        mVideoBuffer->release();
1175        mVideoBuffer = NULL;
1176    }
1177
1178    mVideoSource->stop();
1179
1180    // The following hack is necessary to ensure that the OMX
1181    // component is completely released by the time we may try
1182    // to instantiate it again.
1183    wp<MediaSource> tmp = mVideoSource;
1184    mVideoSource.clear();
1185    while (tmp.promote() != NULL) {
1186        usleep(1000);
1187    }
1188    IPCThreadState::self()->flushCommands();
1189    LOGI("video decoder shutdown completed");
1190}
1191
1192void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1193    mNativeWindow = native;
1194
1195    if (mVideoSource == NULL) {
1196        return;
1197    }
1198
1199    LOGI("attempting to reconfigure to use new surface");
1200
1201    bool wasPlaying = (mFlags & PLAYING) != 0;
1202
1203    pause_l();
1204    mVideoRenderer.clear();
1205
1206    shutdownVideoDecoder_l();
1207
1208    CHECK_EQ(initVideoDecoder(), (status_t)OK);
1209
1210    if (mLastVideoTimeUs >= 0) {
1211        mSeeking = SEEK;
1212        mSeekNotificationSent = true;
1213        mSeekTimeUs = mLastVideoTimeUs;
1214        modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1215    }
1216
1217    if (wasPlaying) {
1218        play_l();
1219    }
1220}
1221
1222void AwesomePlayer::setAudioSink(
1223        const sp<MediaPlayerBase::AudioSink> &audioSink) {
1224    Mutex::Autolock autoLock(mLock);
1225
1226    mAudioSink = audioSink;
1227}
1228
1229status_t AwesomePlayer::setLooping(bool shouldLoop) {
1230    Mutex::Autolock autoLock(mLock);
1231
1232    modifyFlags(LOOPING, CLEAR);
1233
1234    if (shouldLoop) {
1235        modifyFlags(LOOPING, SET);
1236    }
1237
1238    return OK;
1239}
1240
1241status_t AwesomePlayer::getDuration(int64_t *durationUs) {
1242    Mutex::Autolock autoLock(mMiscStateLock);
1243
1244    if (mDurationUs < 0) {
1245        return UNKNOWN_ERROR;
1246    }
1247
1248    *durationUs = mDurationUs;
1249
1250    return OK;
1251}
1252
1253status_t AwesomePlayer::getPosition(int64_t *positionUs) {
1254    if (mRTSPController != NULL) {
1255        *positionUs = mRTSPController->getNormalPlayTimeUs();
1256    }
1257    else if (mSeeking != NO_SEEK) {
1258        *positionUs = mSeekTimeUs;
1259    } else if (mVideoSource != NULL
1260            && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1261        Mutex::Autolock autoLock(mMiscStateLock);
1262        *positionUs = mVideoTimeUs;
1263    } else if (mAudioPlayer != NULL) {
1264        *positionUs = mAudioPlayer->getMediaTimeUs();
1265    } else {
1266        *positionUs = 0;
1267    }
1268
1269    return OK;
1270}
1271
1272status_t AwesomePlayer::seekTo(int64_t timeUs) {
1273    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
1274        Mutex::Autolock autoLock(mLock);
1275        return seekTo_l(timeUs);
1276    }
1277
1278    return OK;
1279}
1280
1281status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
1282    if (mTextPlayer != NULL) {
1283        if (index >= 0) { // to turn on a text track
1284            status_t err = mTextPlayer->setTimedTextTrackIndex(index);
1285            if (err != OK) {
1286                return err;
1287            }
1288
1289            modifyFlags(TEXT_RUNNING, SET);
1290            modifyFlags(TEXTPLAYER_STARTED, SET);
1291            return OK;
1292        } else { // to turn off the text track display
1293            if (mFlags  & TEXT_RUNNING) {
1294                modifyFlags(TEXT_RUNNING, CLEAR);
1295            }
1296            if (mFlags  & TEXTPLAYER_STARTED) {
1297                modifyFlags(TEXTPLAYER_STARTED, CLEAR);
1298            }
1299
1300            return mTextPlayer->setTimedTextTrackIndex(index);
1301        }
1302    } else {
1303        return INVALID_OPERATION;
1304    }
1305}
1306
1307// static
1308void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1309    static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1310}
1311
1312void AwesomePlayer::onRTSPSeekDone() {
1313    notifyListener_l(MEDIA_SEEK_COMPLETE);
1314    mSeekNotificationSent = true;
1315}
1316
1317status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
1318    if (mRTSPController != NULL) {
1319        mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
1320        return OK;
1321    }
1322
1323    if (mFlags & CACHE_UNDERRUN) {
1324        modifyFlags(CACHE_UNDERRUN, CLEAR);
1325        play_l();
1326    }
1327
1328    if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1329        // Video playback completed before, there's no pending
1330        // video event right now. In order for this new seek
1331        // to be honored, we need to post one.
1332
1333        postVideoEvent_l();
1334    }
1335
1336    mSeeking = SEEK;
1337    mSeekNotificationSent = false;
1338    mSeekTimeUs = timeUs;
1339    modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1340
1341    seekAudioIfNecessary_l();
1342
1343    if (mFlags & TEXTPLAYER_STARTED) {
1344        mTextPlayer->seekTo(mSeekTimeUs);
1345    }
1346
1347    if (!(mFlags & PLAYING)) {
1348        LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1349             " immediately.");
1350
1351        notifyListener_l(MEDIA_SEEK_COMPLETE);
1352        mSeekNotificationSent = true;
1353
1354        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1355            modifyFlags(SEEK_PREVIEW, SET);
1356            postVideoEvent_l();
1357        }
1358    }
1359
1360    return OK;
1361}
1362
1363void AwesomePlayer::seekAudioIfNecessary_l() {
1364    if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1365        mAudioPlayer->seekTo(mSeekTimeUs);
1366
1367        mWatchForAudioSeekComplete = true;
1368        mWatchForAudioEOS = true;
1369
1370        if (mDecryptHandle != NULL) {
1371            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1372                    Playback::PAUSE, 0);
1373            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1374                    Playback::START, mSeekTimeUs / 1000);
1375        }
1376    }
1377}
1378
1379void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1380    CHECK(source != NULL);
1381
1382    mAudioTrack = source;
1383}
1384
1385void AwesomePlayer::addTextSource(sp<MediaSource> source) {
1386    Mutex::Autolock autoLock(mTimedTextLock);
1387    CHECK(source != NULL);
1388
1389    if (mTextPlayer == NULL) {
1390        mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
1391    }
1392
1393    mTextPlayer->addTextSource(source);
1394}
1395
1396status_t AwesomePlayer::initAudioDecoder() {
1397    sp<MetaData> meta = mAudioTrack->getFormat();
1398
1399    const char *mime;
1400    CHECK(meta->findCString(kKeyMIMEType, &mime));
1401
1402    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1403        mAudioSource = mAudioTrack;
1404    } else {
1405        mAudioSource = OMXCodec::Create(
1406                mClient.interface(), mAudioTrack->getFormat(),
1407                false, // createEncoder
1408                mAudioTrack);
1409    }
1410
1411    if (mAudioSource != NULL) {
1412        int64_t durationUs;
1413        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1414            Mutex::Autolock autoLock(mMiscStateLock);
1415            if (mDurationUs < 0 || durationUs > mDurationUs) {
1416                mDurationUs = durationUs;
1417            }
1418        }
1419
1420        status_t err = mAudioSource->start();
1421
1422        if (err != OK) {
1423            mAudioSource.clear();
1424            return err;
1425        }
1426    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1427        // For legacy reasons we're simply going to ignore the absence
1428        // of an audio decoder for QCELP instead of aborting playback
1429        // altogether.
1430        return OK;
1431    }
1432
1433    if (mAudioSource != NULL) {
1434        Mutex::Autolock autoLock(mStatsLock);
1435        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
1436
1437        const char *component;
1438        if (!mAudioSource->getFormat()
1439                ->findCString(kKeyDecoderComponent, &component)) {
1440            component = "none";
1441        }
1442
1443        stat->mDecoderName = component;
1444    }
1445
1446    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1447}
1448
1449void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1450    CHECK(source != NULL);
1451
1452    mVideoTrack = source;
1453}
1454
1455status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1456
1457    // Either the application or the DRM system can independently say
1458    // that there must be a hardware-protected path to an external video sink.
1459    // For now we always require a hardware-protected path to external video sink
1460    // if content is DRMed, but eventually this could be optional per DRM agent.
1461    // When the application wants protection, then
1462    //   (USE_SURFACE_ALLOC && (mSurface != 0) &&
1463    //   (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1464    // will be true, but that part is already handled by SurfaceFlinger.
1465
1466#ifdef DEBUG_HDCP
1467    // For debugging, we allow a system property to control the protected usage.
1468    // In case of uninitialized or unexpected property, we default to "DRM only".
1469    bool setProtectionBit = false;
1470    char value[PROPERTY_VALUE_MAX];
1471    if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1472        if (!strcmp(value, "never")) {
1473            // nop
1474        } else if (!strcmp(value, "always")) {
1475            setProtectionBit = true;
1476        } else if (!strcmp(value, "drm-only")) {
1477            if (mDecryptHandle != NULL) {
1478                setProtectionBit = true;
1479            }
1480        // property value is empty, or unexpected value
1481        } else {
1482            if (mDecryptHandle != NULL) {
1483                setProtectionBit = true;
1484            }
1485        }
1486    // can' read property value
1487    } else {
1488        if (mDecryptHandle != NULL) {
1489            setProtectionBit = true;
1490        }
1491    }
1492    // note that usage bit is already cleared, so no need to clear it in the "else" case
1493    if (setProtectionBit) {
1494        flags |= OMXCodec::kEnableGrallocUsageProtected;
1495    }
1496#else
1497    if (mDecryptHandle != NULL) {
1498        flags |= OMXCodec::kEnableGrallocUsageProtected;
1499    }
1500#endif
1501    LOGV("initVideoDecoder flags=0x%x", flags);
1502    mVideoSource = OMXCodec::Create(
1503            mClient.interface(), mVideoTrack->getFormat(),
1504            false, // createEncoder
1505            mVideoTrack,
1506            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
1507
1508    if (mVideoSource != NULL) {
1509        int64_t durationUs;
1510        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1511            Mutex::Autolock autoLock(mMiscStateLock);
1512            if (mDurationUs < 0 || durationUs > mDurationUs) {
1513                mDurationUs = durationUs;
1514            }
1515        }
1516
1517        status_t err = mVideoSource->start();
1518
1519        if (err != OK) {
1520            mVideoSource.clear();
1521            return err;
1522        }
1523    }
1524
1525    if (mVideoSource != NULL) {
1526        Mutex::Autolock autoLock(mStatsLock);
1527        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1528
1529        const char *component;
1530        CHECK(mVideoSource->getFormat()
1531                ->findCString(kKeyDecoderComponent, &component));
1532
1533        stat->mDecoderName = component;
1534    }
1535
1536    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1537}
1538
1539void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1540    if (mSeeking == SEEK_VIDEO_ONLY) {
1541        mSeeking = NO_SEEK;
1542        return;
1543    }
1544
1545    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1546        return;
1547    }
1548
1549    if (mAudioPlayer != NULL) {
1550        LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1551
1552        // If we don't have a video time, seek audio to the originally
1553        // requested seek time instead.
1554
1555        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1556        mWatchForAudioSeekComplete = true;
1557        mWatchForAudioEOS = true;
1558    } else if (!mSeekNotificationSent) {
1559        // If we're playing video only, report seek complete now,
1560        // otherwise audio player will notify us later.
1561        notifyListener_l(MEDIA_SEEK_COMPLETE);
1562        mSeekNotificationSent = true;
1563    }
1564
1565    modifyFlags(FIRST_FRAME, SET);
1566    mSeeking = NO_SEEK;
1567
1568    if (mDecryptHandle != NULL) {
1569        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1570                Playback::PAUSE, 0);
1571        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1572                Playback::START, videoTimeUs / 1000);
1573    }
1574}
1575
1576void AwesomePlayer::onVideoEvent() {
1577    Mutex::Autolock autoLock(mLock);
1578    if (!mVideoEventPending) {
1579        // The event has been cancelled in reset_l() but had already
1580        // been scheduled for execution at that time.
1581        return;
1582    }
1583    mVideoEventPending = false;
1584
1585    if (mSeeking != NO_SEEK) {
1586        if (mVideoBuffer) {
1587            mVideoBuffer->release();
1588            mVideoBuffer = NULL;
1589        }
1590
1591        if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
1592                && !(mFlags & SEEK_PREVIEW)) {
1593            // We're going to seek the video source first, followed by
1594            // the audio source.
1595            // In order to avoid jumps in the DataSource offset caused by
1596            // the audio codec prefetching data from the old locations
1597            // while the video codec is already reading data from the new
1598            // locations, we'll "pause" the audio source, causing it to
1599            // stop reading input data until a subsequent seek.
1600
1601            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1602                mAudioPlayer->pause();
1603
1604                modifyFlags(AUDIO_RUNNING, CLEAR);
1605            }
1606            mAudioSource->pause();
1607        }
1608    }
1609
1610    if (!mVideoBuffer) {
1611        MediaSource::ReadOptions options;
1612        if (mSeeking != NO_SEEK) {
1613            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1614
1615            options.setSeekTo(
1616                    mSeekTimeUs,
1617                    mSeeking == SEEK_VIDEO_ONLY
1618                        ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1619                        : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1620        }
1621        for (;;) {
1622            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1623            options.clearSeekTo();
1624
1625            if (err != OK) {
1626                CHECK(mVideoBuffer == NULL);
1627
1628                if (err == INFO_FORMAT_CHANGED) {
1629                    LOGV("VideoSource signalled format change.");
1630
1631                    notifyVideoSize_l();
1632
1633                    if (mVideoRenderer != NULL) {
1634                        mVideoRendererIsPreview = false;
1635                        initRenderer_l();
1636                    }
1637                    continue;
1638                }
1639
1640                // So video playback is complete, but we may still have
1641                // a seek request pending that needs to be applied
1642                // to the audio track.
1643                if (mSeeking != NO_SEEK) {
1644                    LOGV("video stream ended while seeking!");
1645                }
1646                finishSeekIfNecessary(-1);
1647
1648                if (mAudioPlayer != NULL
1649                        && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1650                    startAudioPlayer_l();
1651                }
1652
1653                modifyFlags(VIDEO_AT_EOS, SET);
1654                postStreamDoneEvent_l(err);
1655                return;
1656            }
1657
1658            if (mVideoBuffer->range_length() == 0) {
1659                // Some decoders, notably the PV AVC software decoder
1660                // return spurious empty buffers that we just want to ignore.
1661
1662                mVideoBuffer->release();
1663                mVideoBuffer = NULL;
1664                continue;
1665            }
1666
1667            break;
1668        }
1669
1670        {
1671            Mutex::Autolock autoLock(mStatsLock);
1672            ++mStats.mNumVideoFramesDecoded;
1673        }
1674    }
1675
1676    int64_t timeUs;
1677    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1678
1679    mLastVideoTimeUs = timeUs;
1680
1681    if (mSeeking == SEEK_VIDEO_ONLY) {
1682        if (mSeekTimeUs > timeUs) {
1683            LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1684                 mSeekTimeUs, timeUs);
1685        }
1686    }
1687
1688    {
1689        Mutex::Autolock autoLock(mMiscStateLock);
1690        mVideoTimeUs = timeUs;
1691    }
1692
1693    SeekType wasSeeking = mSeeking;
1694    finishSeekIfNecessary(timeUs);
1695
1696    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1697        status_t err = startAudioPlayer_l();
1698        if (err != OK) {
1699            LOGE("Starting the audio player failed w/ err %d", err);
1700            return;
1701        }
1702    }
1703
1704    if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1705        mTextPlayer->resume();
1706        modifyFlags(TEXT_RUNNING, SET);
1707    }
1708
1709    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1710
1711    if (mFlags & FIRST_FRAME) {
1712        modifyFlags(FIRST_FRAME, CLEAR);
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        if (latenessUs > 0) {
1728            LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1729        }
1730    }
1731
1732    if (wasSeeking == NO_SEEK) {
1733        // Let's display the first frame after seeking right away.
1734
1735        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1736
1737        int64_t latenessUs = nowUs - timeUs;
1738
1739        if (latenessUs > 500000ll
1740                && mRTSPController == NULL
1741                && mAudioPlayer != NULL
1742                && mAudioPlayer->getMediaTimeMapping(
1743                    &realTimeUs, &mediaTimeUs)) {
1744            LOGI("we're much too late (%.2f secs), video skipping ahead",
1745                 latenessUs / 1E6);
1746
1747            mVideoBuffer->release();
1748            mVideoBuffer = NULL;
1749
1750            mSeeking = SEEK_VIDEO_ONLY;
1751            mSeekTimeUs = mediaTimeUs;
1752
1753            postVideoEvent_l();
1754            return;
1755        }
1756
1757        if (latenessUs > 40000) {
1758            // We're more than 40ms late.
1759            LOGV("we're late by %lld us (%.2f secs), dropping frame",
1760                 latenessUs, latenessUs / 1E6);
1761            mVideoBuffer->release();
1762            mVideoBuffer = NULL;
1763
1764            {
1765                Mutex::Autolock autoLock(mStatsLock);
1766                ++mStats.mNumVideoFramesDropped;
1767            }
1768
1769            postVideoEvent_l();
1770            return;
1771        }
1772
1773        if (latenessUs < -10000) {
1774            // We're more than 10ms early.
1775
1776            postVideoEvent_l(10000);
1777            return;
1778        }
1779    }
1780
1781    if ((mNativeWindow != NULL)
1782            && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
1783        mVideoRendererIsPreview = false;
1784
1785        initRenderer_l();
1786    }
1787
1788    if (mVideoRenderer != NULL) {
1789        mVideoRenderer->render(mVideoBuffer);
1790    }
1791
1792    mVideoBuffer->release();
1793    mVideoBuffer = NULL;
1794
1795    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
1796        modifyFlags(SEEK_PREVIEW, CLEAR);
1797        return;
1798    }
1799
1800    postVideoEvent_l();
1801}
1802
1803void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1804    if (mVideoEventPending) {
1805        return;
1806    }
1807
1808    mVideoEventPending = true;
1809    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1810}
1811
1812void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1813    if (mStreamDoneEventPending) {
1814        return;
1815    }
1816    mStreamDoneEventPending = true;
1817
1818    mStreamDoneStatus = status;
1819    mQueue.postEvent(mStreamDoneEvent);
1820}
1821
1822void AwesomePlayer::postBufferingEvent_l() {
1823    if (mBufferingEventPending) {
1824        return;
1825    }
1826    mBufferingEventPending = true;
1827    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1828}
1829
1830void AwesomePlayer::postVideoLagEvent_l() {
1831    if (mVideoLagEventPending) {
1832        return;
1833    }
1834    mVideoLagEventPending = true;
1835    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1836}
1837
1838void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
1839    if (mAudioStatusEventPending) {
1840        return;
1841    }
1842    mAudioStatusEventPending = true;
1843    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
1844}
1845
1846void AwesomePlayer::onCheckAudioStatus() {
1847    Mutex::Autolock autoLock(mLock);
1848    if (!mAudioStatusEventPending) {
1849        // Event was dispatched and while we were blocking on the mutex,
1850        // has already been cancelled.
1851        return;
1852    }
1853
1854    mAudioStatusEventPending = false;
1855
1856    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1857        mWatchForAudioSeekComplete = false;
1858
1859        if (!mSeekNotificationSent) {
1860            notifyListener_l(MEDIA_SEEK_COMPLETE);
1861            mSeekNotificationSent = true;
1862        }
1863
1864        mSeeking = NO_SEEK;
1865    }
1866
1867    status_t finalStatus;
1868    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1869        mWatchForAudioEOS = false;
1870        modifyFlags(AUDIO_AT_EOS, SET);
1871        modifyFlags(FIRST_FRAME, SET);
1872        postStreamDoneEvent_l(finalStatus);
1873    }
1874}
1875
1876status_t AwesomePlayer::prepare() {
1877    Mutex::Autolock autoLock(mLock);
1878    return prepare_l();
1879}
1880
1881status_t AwesomePlayer::prepare_l() {
1882    if (mFlags & PREPARED) {
1883        return OK;
1884    }
1885
1886    if (mFlags & PREPARING) {
1887        return UNKNOWN_ERROR;
1888    }
1889
1890    mIsAsyncPrepare = false;
1891    status_t err = prepareAsync_l();
1892
1893    if (err != OK) {
1894        return err;
1895    }
1896
1897    while (mFlags & PREPARING) {
1898        mPreparedCondition.wait(mLock);
1899    }
1900
1901    return mPrepareResult;
1902}
1903
1904status_t AwesomePlayer::prepareAsync() {
1905    Mutex::Autolock autoLock(mLock);
1906
1907    if (mFlags & PREPARING) {
1908        return UNKNOWN_ERROR;  // async prepare already pending
1909    }
1910
1911    mIsAsyncPrepare = true;
1912    return prepareAsync_l();
1913}
1914
1915status_t AwesomePlayer::prepareAsync_l() {
1916    if (mFlags & PREPARING) {
1917        return UNKNOWN_ERROR;  // async prepare already pending
1918    }
1919
1920    if (!mQueueStarted) {
1921        mQueue.start();
1922        mQueueStarted = true;
1923    }
1924
1925    modifyFlags(PREPARING, SET);
1926    mAsyncPrepareEvent = new AwesomeEvent(
1927            this, &AwesomePlayer::onPrepareAsyncEvent);
1928
1929    mQueue.postEvent(mAsyncPrepareEvent);
1930
1931    return OK;
1932}
1933
1934status_t AwesomePlayer::finishSetDataSource_l() {
1935    sp<DataSource> dataSource;
1936
1937    bool isWidevineStreaming = false;
1938    if (!strncasecmp("widevine://", mUri.string(), 11)) {
1939        isWidevineStreaming = true;
1940
1941        String8 newURI = String8("http://");
1942        newURI.append(mUri.string() + 11);
1943
1944        mUri = newURI;
1945    }
1946
1947    if (!strncasecmp("http://", mUri.string(), 7)
1948            || !strncasecmp("https://", mUri.string(), 8)
1949            || isWidevineStreaming) {
1950        mConnectingDataSource = HTTPBase::Create(
1951                (mFlags & INCOGNITO)
1952                    ? HTTPBase::kFlagIncognito
1953                    : 0);
1954
1955        if (mUIDValid) {
1956            mConnectingDataSource->setUID(mUID);
1957        }
1958
1959        mLock.unlock();
1960        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
1961        mLock.lock();
1962
1963        if (err != OK) {
1964            mConnectingDataSource.clear();
1965
1966            LOGI("mConnectingDataSource->connect() returned %d", err);
1967            return err;
1968        }
1969
1970        if (!isWidevineStreaming) {
1971            // The widevine extractor does its own caching.
1972
1973#if 0
1974            mCachedSource = new NuCachedSource2(
1975                    new ThrottledSource(
1976                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1977#else
1978            mCachedSource = new NuCachedSource2(mConnectingDataSource);
1979#endif
1980
1981            dataSource = mCachedSource;
1982        } else {
1983            dataSource = mConnectingDataSource;
1984        }
1985
1986        mConnectingDataSource.clear();
1987
1988
1989        String8 contentType = dataSource->getMIMEType();
1990
1991        if (strncasecmp(contentType.string(), "audio/", 6)) {
1992            // We're not doing this for streams that appear to be audio-only
1993            // streams to ensure that even low bandwidth streams start
1994            // playing back fairly instantly.
1995
1996            // We're going to prefill the cache before trying to instantiate
1997            // the extractor below, as the latter is an operation that otherwise
1998            // could block on the datasource for a significant amount of time.
1999            // During that time we'd be unable to abort the preparation phase
2000            // without this prefill.
2001            if (mCachedSource != NULL) {
2002                // We're going to prefill the cache before trying to instantiate
2003                // the extractor below, as the latter is an operation that otherwise
2004                // could block on the datasource for a significant amount of time.
2005                // During that time we'd be unable to abort the preparation phase
2006                // without this prefill.
2007
2008                mLock.unlock();
2009
2010                for (;;) {
2011                    status_t finalStatus;
2012                    size_t cachedDataRemaining =
2013                        mCachedSource->approxDataRemaining(&finalStatus);
2014
2015                    if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
2016                            || (mFlags & PREPARE_CANCELLED)) {
2017                        break;
2018                    }
2019
2020                    usleep(200000);
2021                }
2022
2023                mLock.lock();
2024            }
2025
2026            if (mFlags & PREPARE_CANCELLED) {
2027                LOGI("Prepare cancelled while waiting for initial cache fill.");
2028                return UNKNOWN_ERROR;
2029            }
2030        }
2031    } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
2032        if (mLooper == NULL) {
2033            mLooper = new ALooper;
2034            mLooper->setName("rtsp");
2035            mLooper->start();
2036        }
2037        mRTSPController = new ARTSPController(mLooper);
2038        mConnectingRTSPController = mRTSPController;
2039
2040        if (mUIDValid) {
2041            mConnectingRTSPController->setUID(mUID);
2042        }
2043
2044        mLock.unlock();
2045        status_t err = mRTSPController->connect(mUri.string());
2046        mLock.lock();
2047
2048        mConnectingRTSPController.clear();
2049
2050        LOGI("ARTSPController::connect returned %d", err);
2051
2052        if (err != OK) {
2053            mRTSPController.clear();
2054            return err;
2055        }
2056
2057        sp<MediaExtractor> extractor = mRTSPController.get();
2058        return setDataSource_l(extractor);
2059    } else {
2060        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2061    }
2062
2063    if (dataSource == NULL) {
2064        return UNKNOWN_ERROR;
2065    }
2066
2067    sp<MediaExtractor> extractor;
2068
2069    if (isWidevineStreaming) {
2070        String8 mimeType;
2071        float confidence;
2072        sp<AMessage> dummy;
2073        bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
2074
2075        if (!success
2076                || strcasecmp(
2077                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2078            return ERROR_UNSUPPORTED;
2079        }
2080
2081        mWVMExtractor = new WVMExtractor(dataSource);
2082        mWVMExtractor->setAdaptiveStreamingMode(true);
2083        extractor = mWVMExtractor;
2084    } else {
2085        extractor = MediaExtractor::Create(dataSource);
2086
2087        if (extractor == NULL) {
2088            return UNKNOWN_ERROR;
2089        }
2090    }
2091
2092    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
2093
2094    if (mDecryptHandle != NULL) {
2095        CHECK(mDrmManagerClient);
2096        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
2097            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
2098        }
2099    }
2100
2101    status_t err = setDataSource_l(extractor);
2102
2103    if (err != OK) {
2104        mWVMExtractor.clear();
2105
2106        return err;
2107    }
2108
2109    return OK;
2110}
2111
2112void AwesomePlayer::abortPrepare(status_t err) {
2113    CHECK(err != OK);
2114
2115    if (mIsAsyncPrepare) {
2116        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2117    }
2118
2119    mPrepareResult = err;
2120    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2121    mAsyncPrepareEvent = NULL;
2122    mPreparedCondition.broadcast();
2123}
2124
2125// static
2126bool AwesomePlayer::ContinuePreparation(void *cookie) {
2127    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2128
2129    return (me->mFlags & PREPARE_CANCELLED) == 0;
2130}
2131
2132void AwesomePlayer::onPrepareAsyncEvent() {
2133    Mutex::Autolock autoLock(mLock);
2134
2135    if (mFlags & PREPARE_CANCELLED) {
2136        LOGI("prepare was cancelled before doing anything");
2137        abortPrepare(UNKNOWN_ERROR);
2138        return;
2139    }
2140
2141    if (mUri.size() > 0) {
2142        status_t err = finishSetDataSource_l();
2143
2144        if (err != OK) {
2145            abortPrepare(err);
2146            return;
2147        }
2148    }
2149
2150    if (mVideoTrack != NULL && mVideoSource == NULL) {
2151        status_t err = initVideoDecoder();
2152
2153        if (err != OK) {
2154            abortPrepare(err);
2155            return;
2156        }
2157    }
2158
2159    if (mAudioTrack != NULL && mAudioSource == NULL) {
2160        status_t err = initAudioDecoder();
2161
2162        if (err != OK) {
2163            abortPrepare(err);
2164            return;
2165        }
2166    }
2167
2168    modifyFlags(PREPARING_CONNECTED, SET);
2169
2170    if (isStreamingHTTP() || mRTSPController != NULL) {
2171        postBufferingEvent_l();
2172    } else {
2173        finishAsyncPrepare_l();
2174    }
2175}
2176
2177void AwesomePlayer::finishAsyncPrepare_l() {
2178    if (mIsAsyncPrepare) {
2179        if (mVideoSource == NULL) {
2180            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2181        } else {
2182            notifyVideoSize_l();
2183        }
2184
2185        notifyListener_l(MEDIA_PREPARED);
2186    }
2187
2188    mPrepareResult = OK;
2189    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2190    modifyFlags(PREPARED, SET);
2191    mAsyncPrepareEvent = NULL;
2192    mPreparedCondition.broadcast();
2193}
2194
2195uint32_t AwesomePlayer::flags() const {
2196    return mExtractorFlags;
2197}
2198
2199void AwesomePlayer::postAudioEOS(int64_t delayUs) {
2200    Mutex::Autolock autoLock(mLock);
2201    postCheckAudioStatusEvent_l(delayUs);
2202}
2203
2204void AwesomePlayer::postAudioSeekComplete() {
2205    Mutex::Autolock autoLock(mLock);
2206    postAudioSeekComplete_l();
2207}
2208
2209void AwesomePlayer::postAudioSeekComplete_l() {
2210    postCheckAudioStatusEvent_l(0 /* delayUs */);
2211}
2212
2213status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
2214    switch (key) {
2215        case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX:
2216        {
2217            Mutex::Autolock autoLock(mTimedTextLock);
2218            return setTimedTextTrackIndex(request.readInt32());
2219        }
2220        case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE:
2221        {
2222            Mutex::Autolock autoLock(mTimedTextLock);
2223            if (mTextPlayer == NULL) {
2224                mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
2225            }
2226
2227            return mTextPlayer->setParameter(key, request);
2228        }
2229        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2230        {
2231            return setCacheStatCollectFreq(request);
2232        }
2233        default:
2234        {
2235            return ERROR_UNSUPPORTED;
2236        }
2237    }
2238}
2239
2240status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2241    if (mCachedSource != NULL) {
2242        int32_t freqMs = request.readInt32();
2243        LOGD("Request to keep cache stats in the past %d ms",
2244            freqMs);
2245        return mCachedSource->setCacheStatCollectFreq(freqMs);
2246    }
2247    return ERROR_UNSUPPORTED;
2248}
2249
2250status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
2251    switch (key) {
2252    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2253        {
2254            int32_t channelCount;
2255            if (mAudioTrack == 0 ||
2256                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2257                channelCount = 0;
2258            }
2259            reply->writeInt32(channelCount);
2260        }
2261        return OK;
2262    default:
2263        {
2264            return ERROR_UNSUPPORTED;
2265        }
2266    }
2267}
2268
2269bool AwesomePlayer::isStreamingHTTP() const {
2270    return mCachedSource != NULL || mWVMExtractor != NULL;
2271}
2272
2273status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2274    Mutex::Autolock autoLock(mStatsLock);
2275
2276    FILE *out = fdopen(dup(fd), "w");
2277
2278    fprintf(out, " AwesomePlayer\n");
2279    if (mStats.mFd < 0) {
2280        fprintf(out, "  URI(%s)", mStats.mURI.string());
2281    } else {
2282        fprintf(out, "  fd(%d)", mStats.mFd);
2283    }
2284
2285    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2286
2287    if (mStats.mBitrate >= 0) {
2288        fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2289    }
2290
2291    fprintf(out, "\n");
2292
2293    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2294        const TrackStat &stat = mStats.mTracks.itemAt(i);
2295
2296        fprintf(out, "  Track %d\n", i + 1);
2297        fprintf(out, "   MIME(%s)", stat.mMIME.string());
2298
2299        if (!stat.mDecoderName.isEmpty()) {
2300            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2301        }
2302
2303        fprintf(out, "\n");
2304
2305        if ((ssize_t)i == mStats.mVideoTrackIndex) {
2306            fprintf(out,
2307                    "   videoDimensions(%d x %d), "
2308                    "numVideoFramesDecoded(%lld), "
2309                    "numVideoFramesDropped(%lld)\n",
2310                    mStats.mVideoWidth,
2311                    mStats.mVideoHeight,
2312                    mStats.mNumVideoFramesDecoded,
2313                    mStats.mNumVideoFramesDropped);
2314        }
2315    }
2316
2317    fclose(out);
2318    out = NULL;
2319
2320    return OK;
2321}
2322
2323void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2324    switch (mode) {
2325        case SET:
2326            mFlags |= value;
2327            break;
2328        case CLEAR:
2329            mFlags &= ~value;
2330            break;
2331        case ASSIGN:
2332            mFlags = value;
2333            break;
2334        default:
2335            TRESPASS();
2336    }
2337
2338    {
2339        Mutex::Autolock autoLock(mStatsLock);
2340        mStats.mFlags = mFlags;
2341    }
2342}
2343
2344}  // namespace android
2345