AwesomePlayer.cpp revision 8adb83ba4837b3c9de1a4221a5ca4c371a62e38c
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}
578
579void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
580    if (mListener != NULL) {
581        sp<MediaPlayerBase> listener = mListener.promote();
582
583        if (listener != NULL) {
584            listener->sendEvent(msg, ext1, ext2);
585        }
586    }
587}
588
589bool AwesomePlayer::getBitrate(int64_t *bitrate) {
590    off64_t size;
591    if (mDurationUs >= 0 && mCachedSource != NULL
592            && mCachedSource->getSize(&size) == OK) {
593        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
594        return true;
595    }
596
597    if (mBitrate >= 0) {
598        *bitrate = mBitrate;
599        return true;
600    }
601
602    *bitrate = 0;
603
604    return false;
605}
606
607// Returns true iff cached duration is available/applicable.
608bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
609    int64_t bitrate;
610
611    if (mRTSPController != NULL) {
612        *durationUs = mRTSPController->getQueueDurationUs(eos);
613        return true;
614    } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
615        status_t finalStatus;
616        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
617        *durationUs = cachedDataRemaining * 8000000ll / bitrate;
618        *eos = (finalStatus != OK);
619        return true;
620    } else if (mWVMExtractor != NULL) {
621        status_t finalStatus;
622        *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
623        *eos = (finalStatus != OK);
624        return true;
625    }
626
627    return false;
628}
629
630void AwesomePlayer::ensureCacheIsFetching_l() {
631    if (mCachedSource != NULL) {
632        mCachedSource->resumeFetchingIfNecessary();
633    }
634}
635
636void AwesomePlayer::onVideoLagUpdate() {
637    Mutex::Autolock autoLock(mLock);
638    if (!mVideoLagEventPending) {
639        return;
640    }
641    mVideoLagEventPending = false;
642
643    int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
644    int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
645
646    if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
647        LOGV("video late by %lld ms.", videoLateByUs / 1000ll);
648
649        notifyListener_l(
650                MEDIA_INFO,
651                MEDIA_INFO_VIDEO_TRACK_LAGGING,
652                videoLateByUs / 1000ll);
653    }
654
655    postVideoLagEvent_l();
656}
657
658void AwesomePlayer::onBufferingUpdate() {
659    Mutex::Autolock autoLock(mLock);
660    if (!mBufferingEventPending) {
661        return;
662    }
663    mBufferingEventPending = false;
664
665    if (mCachedSource != NULL) {
666        status_t finalStatus;
667        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
668        bool eos = (finalStatus != OK);
669
670        if (eos) {
671            if (finalStatus == ERROR_END_OF_STREAM) {
672                notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
673            }
674            if (mFlags & PREPARING) {
675                LOGV("cache has reached EOS, prepare is done.");
676                finishAsyncPrepare_l();
677            }
678        } else {
679            int64_t bitrate;
680            if (getBitrate(&bitrate)) {
681                size_t cachedSize = mCachedSource->cachedSize();
682                int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
683
684                int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
685                if (percentage > 100) {
686                    percentage = 100;
687                }
688
689                notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
690            } else {
691                // We don't know the bitrate of the stream, use absolute size
692                // limits to maintain the cache.
693
694                if ((mFlags & PLAYING) && !eos
695                        && (cachedDataRemaining < kLowWaterMarkBytes)) {
696                    LOGI("cache is running low (< %d) , pausing.",
697                         kLowWaterMarkBytes);
698                    modifyFlags(CACHE_UNDERRUN, SET);
699                    pause_l();
700                    ensureCacheIsFetching_l();
701                    sendCacheStats();
702                    notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
703                } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
704                    if (mFlags & CACHE_UNDERRUN) {
705                        LOGI("cache has filled up (> %d), resuming.",
706                             kHighWaterMarkBytes);
707                        modifyFlags(CACHE_UNDERRUN, CLEAR);
708                        play_l();
709                        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
710                    } else if (mFlags & PREPARING) {
711                        LOGV("cache has filled up (> %d), prepare is done",
712                             kHighWaterMarkBytes);
713                        finishAsyncPrepare_l();
714                    }
715                }
716            }
717        }
718    } else if (mWVMExtractor != NULL) {
719        status_t finalStatus;
720
721        int64_t cachedDurationUs
722            = mWVMExtractor->getCachedDurationUs(&finalStatus);
723
724        bool eos = (finalStatus != OK);
725
726        if (eos) {
727            if (finalStatus == ERROR_END_OF_STREAM) {
728                notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
729            }
730            if (mFlags & PREPARING) {
731                LOGV("cache has reached EOS, prepare is done.");
732                finishAsyncPrepare_l();
733            }
734        } else {
735            int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
736            if (percentage > 100) {
737                percentage = 100;
738            }
739
740            notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
741        }
742    }
743
744    int64_t cachedDurationUs;
745    bool eos;
746    if (getCachedDuration_l(&cachedDurationUs, &eos)) {
747        LOGV("cachedDurationUs = %.2f secs, eos=%d",
748             cachedDurationUs / 1E6, eos);
749
750        int64_t highWaterMarkUs =
751            (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
752
753        if ((mFlags & PLAYING) && !eos
754                && (cachedDurationUs < kLowWaterMarkUs)) {
755            LOGI("cache is running low (%.2f secs) , pausing.",
756                 cachedDurationUs / 1E6);
757            modifyFlags(CACHE_UNDERRUN, SET);
758            pause_l();
759            ensureCacheIsFetching_l();
760            sendCacheStats();
761            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
762        } else if (eos || cachedDurationUs > highWaterMarkUs) {
763            if (mFlags & CACHE_UNDERRUN) {
764                LOGI("cache has filled up (%.2f secs), resuming.",
765                     cachedDurationUs / 1E6);
766                modifyFlags(CACHE_UNDERRUN, CLEAR);
767                play_l();
768                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
769            } else if (mFlags & PREPARING) {
770                LOGV("cache has filled up (%.2f secs), prepare is done",
771                     cachedDurationUs / 1E6);
772                finishAsyncPrepare_l();
773            }
774        }
775    }
776
777    postBufferingEvent_l();
778}
779
780void AwesomePlayer::sendCacheStats() {
781    sp<MediaPlayerBase> listener = mListener.promote();
782    if (listener != NULL && mCachedSource != NULL) {
783        int32_t kbps = 0;
784        status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
785        if (err == OK) {
786            listener->sendEvent(
787                MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
788        }
789    }
790}
791
792void AwesomePlayer::onStreamDone() {
793    // Posted whenever any stream finishes playing.
794
795    Mutex::Autolock autoLock(mLock);
796    if (!mStreamDoneEventPending) {
797        return;
798    }
799    mStreamDoneEventPending = false;
800
801    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
802        LOGV("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 | AUTO_LOOPING)) {
822        seekTo_l(0);
823
824        if (mVideoSource != NULL) {
825            postVideoEvent_l();
826        }
827    } else {
828        LOGV("MEDIA_PLAYBACK_COMPLETE");
829        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
830
831        pause_l(true /* at eos */);
832
833        modifyFlags(AT_EOS, SET);
834    }
835}
836
837status_t AwesomePlayer::play() {
838    Mutex::Autolock autoLock(mLock);
839
840    modifyFlags(CACHE_UNDERRUN, CLEAR);
841
842    return play_l();
843}
844
845status_t AwesomePlayer::play_l() {
846    modifyFlags(SEEK_PREVIEW, CLEAR);
847
848    if (mFlags & PLAYING) {
849        return OK;
850    }
851
852    if (!(mFlags & PREPARED)) {
853        status_t err = prepare_l();
854
855        if (err != OK) {
856            return err;
857        }
858    }
859
860    modifyFlags(PLAYING, SET);
861    modifyFlags(FIRST_FRAME, SET);
862
863    if (mDecryptHandle != NULL) {
864        int64_t position;
865        getPosition(&position);
866        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
867                Playback::START, position / 1000);
868    }
869
870    if (mAudioSource != NULL) {
871        if (mAudioPlayer == NULL) {
872            if (mAudioSink != NULL) {
873                mAudioPlayer = new AudioPlayer(mAudioSink, this);
874                mAudioPlayer->setSource(mAudioSource);
875
876                mTimeSource = mAudioPlayer;
877
878                // If there was a seek request before we ever started,
879                // honor the request now.
880                // Make sure to do this before starting the audio player
881                // to avoid a race condition.
882                seekAudioIfNecessary_l();
883            }
884        }
885
886        CHECK(!(mFlags & AUDIO_RUNNING));
887
888        if (mVideoSource == NULL) {
889            // We don't want to post an error notification at this point,
890            // the error returned from MediaPlayer::start() will suffice.
891
892            status_t err = startAudioPlayer_l(
893                    false /* sendErrorNotification */);
894
895            if (err != OK) {
896                delete mAudioPlayer;
897                mAudioPlayer = NULL;
898
899                modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
900
901                if (mDecryptHandle != NULL) {
902                    mDrmManagerClient->setPlaybackStatus(
903                            mDecryptHandle, Playback::STOP, 0);
904                }
905
906                return err;
907            }
908        }
909    }
910
911    if (mTimeSource == NULL && mAudioPlayer == NULL) {
912        mTimeSource = &mSystemTimeSource;
913    }
914
915    if (mVideoSource != NULL) {
916        // Kick off video playback
917        postVideoEvent_l();
918
919        if (mAudioSource != NULL && mVideoSource != NULL) {
920            postVideoLagEvent_l();
921        }
922    }
923
924    if (mFlags & AT_EOS) {
925        // Legacy behaviour, if a stream finishes playing and then
926        // is started again, we play from the start...
927        seekTo_l(0);
928    }
929
930    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
931        | IMediaPlayerService::kBatteryDataTrackDecoder;
932    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
933        params |= IMediaPlayerService::kBatteryDataTrackAudio;
934    }
935    if (mVideoSource != NULL) {
936        params |= IMediaPlayerService::kBatteryDataTrackVideo;
937    }
938    addBatteryData(params);
939
940    return OK;
941}
942
943status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
944    CHECK(!(mFlags & AUDIO_RUNNING));
945
946    if (mAudioSource == NULL || mAudioPlayer == NULL) {
947        return OK;
948    }
949
950    if (!(mFlags & AUDIOPLAYER_STARTED)) {
951        modifyFlags(AUDIOPLAYER_STARTED, SET);
952
953        bool wasSeeking = mAudioPlayer->isSeeking();
954
955        // We've already started the MediaSource in order to enable
956        // the prefetcher to read its data.
957        status_t err = mAudioPlayer->start(
958                true /* sourceAlreadyStarted */);
959
960        if (err != OK) {
961            if (sendErrorNotification) {
962                notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
963            }
964
965            return err;
966        }
967
968        if (wasSeeking) {
969            CHECK(!mAudioPlayer->isSeeking());
970
971            // We will have finished the seek while starting the audio player.
972            postAudioSeekComplete_l();
973        }
974    } else {
975        mAudioPlayer->resume();
976    }
977
978    modifyFlags(AUDIO_RUNNING, SET);
979
980    mWatchForAudioEOS = true;
981
982    return OK;
983}
984
985void AwesomePlayer::notifyVideoSize_l() {
986    sp<MetaData> meta = mVideoSource->getFormat();
987
988    int32_t cropLeft, cropTop, cropRight, cropBottom;
989    if (!meta->findRect(
990                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
991        int32_t width, height;
992        CHECK(meta->findInt32(kKeyWidth, &width));
993        CHECK(meta->findInt32(kKeyHeight, &height));
994
995        cropLeft = cropTop = 0;
996        cropRight = width - 1;
997        cropBottom = height - 1;
998
999        LOGV("got dimensions only %d x %d", width, height);
1000    } else {
1001        LOGV("got crop rect %d, %d, %d, %d",
1002             cropLeft, cropTop, cropRight, cropBottom);
1003    }
1004
1005    int32_t displayWidth;
1006    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1007        LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1008        mDisplayWidth = displayWidth;
1009    }
1010    int32_t displayHeight;
1011    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1012        LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1013        mDisplayHeight = displayHeight;
1014    }
1015
1016    int32_t usableWidth = cropRight - cropLeft + 1;
1017    int32_t usableHeight = cropBottom - cropTop + 1;
1018    if (mDisplayWidth != 0) {
1019        usableWidth = mDisplayWidth;
1020    }
1021    if (mDisplayHeight != 0) {
1022        usableHeight = mDisplayHeight;
1023    }
1024
1025    {
1026        Mutex::Autolock autoLock(mStatsLock);
1027        mStats.mVideoWidth = usableWidth;
1028        mStats.mVideoHeight = usableHeight;
1029    }
1030
1031    int32_t rotationDegrees;
1032    if (!mVideoTrack->getFormat()->findInt32(
1033                kKeyRotation, &rotationDegrees)) {
1034        rotationDegrees = 0;
1035    }
1036
1037    if (rotationDegrees == 90 || rotationDegrees == 270) {
1038        notifyListener_l(
1039                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1040    } else {
1041        notifyListener_l(
1042                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1043    }
1044}
1045
1046void AwesomePlayer::initRenderer_l() {
1047    if (mNativeWindow == NULL) {
1048        return;
1049    }
1050
1051    sp<MetaData> meta = mVideoSource->getFormat();
1052
1053    int32_t format;
1054    const char *component;
1055    int32_t decodedWidth, decodedHeight;
1056    CHECK(meta->findInt32(kKeyColorFormat, &format));
1057    CHECK(meta->findCString(kKeyDecoderComponent, &component));
1058    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1059    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
1060
1061    int32_t rotationDegrees;
1062    if (!mVideoTrack->getFormat()->findInt32(
1063                kKeyRotation, &rotationDegrees)) {
1064        rotationDegrees = 0;
1065    }
1066
1067    mVideoRenderer.clear();
1068
1069    // Must ensure that mVideoRenderer's destructor is actually executed
1070    // before creating a new one.
1071    IPCThreadState::self()->flushCommands();
1072
1073    if (USE_SURFACE_ALLOC
1074            && !strncmp(component, "OMX.", 4)
1075            && strncmp(component, "OMX.google.", 11)) {
1076        // Hardware decoders avoid the CPU color conversion by decoding
1077        // directly to ANativeBuffers, so we must use a renderer that
1078        // just pushes those buffers to the ANativeWindow.
1079        mVideoRenderer =
1080            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
1081    } else {
1082        // Other decoders are instantiated locally and as a consequence
1083        // allocate their buffers in local address space.  This renderer
1084        // then performs a color conversion and copy to get the data
1085        // into the ANativeBuffer.
1086        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
1087    }
1088}
1089
1090status_t AwesomePlayer::pause() {
1091    Mutex::Autolock autoLock(mLock);
1092
1093    modifyFlags(CACHE_UNDERRUN, CLEAR);
1094
1095    return pause_l();
1096}
1097
1098status_t AwesomePlayer::pause_l(bool at_eos) {
1099    if (!(mFlags & PLAYING)) {
1100        return OK;
1101    }
1102
1103    cancelPlayerEvents(true /* keepBufferingGoing */);
1104
1105    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1106        if (at_eos) {
1107            // If we played the audio stream to completion we
1108            // want to make sure that all samples remaining in the audio
1109            // track's queue are played out.
1110            mAudioPlayer->pause(true /* playPendingSamples */);
1111        } else {
1112            mAudioPlayer->pause();
1113        }
1114
1115        modifyFlags(AUDIO_RUNNING, CLEAR);
1116    }
1117
1118    if (mFlags & TEXTPLAYER_STARTED) {
1119        mTextPlayer->pause();
1120        modifyFlags(TEXT_RUNNING, CLEAR);
1121    }
1122
1123    modifyFlags(PLAYING, CLEAR);
1124
1125    if (mDecryptHandle != NULL) {
1126        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1127                Playback::PAUSE, 0);
1128    }
1129
1130    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1131    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1132        params |= IMediaPlayerService::kBatteryDataTrackAudio;
1133    }
1134    if (mVideoSource != NULL) {
1135        params |= IMediaPlayerService::kBatteryDataTrackVideo;
1136    }
1137
1138    addBatteryData(params);
1139
1140    return OK;
1141}
1142
1143bool AwesomePlayer::isPlaying() const {
1144    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1145}
1146
1147void AwesomePlayer::setSurface(const sp<Surface> &surface) {
1148    Mutex::Autolock autoLock(mLock);
1149
1150    mSurface = surface;
1151    setNativeWindow_l(surface);
1152}
1153
1154void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1155    Mutex::Autolock autoLock(mLock);
1156
1157    mSurface.clear();
1158    if (surfaceTexture != NULL) {
1159        setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
1160    } else {
1161        setNativeWindow_l(NULL);
1162    }
1163}
1164
1165void AwesomePlayer::shutdownVideoDecoder_l() {
1166    if (mVideoBuffer) {
1167        mVideoBuffer->release();
1168        mVideoBuffer = NULL;
1169    }
1170
1171    mVideoSource->stop();
1172
1173    // The following hack is necessary to ensure that the OMX
1174    // component is completely released by the time we may try
1175    // to instantiate it again.
1176    wp<MediaSource> tmp = mVideoSource;
1177    mVideoSource.clear();
1178    while (tmp.promote() != NULL) {
1179        usleep(1000);
1180    }
1181    IPCThreadState::self()->flushCommands();
1182    LOGI("video decoder shutdown completed");
1183}
1184
1185void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1186    mNativeWindow = native;
1187
1188    if (mVideoSource == NULL) {
1189        return;
1190    }
1191
1192    LOGI("attempting to reconfigure to use new surface");
1193
1194    bool wasPlaying = (mFlags & PLAYING) != 0;
1195
1196    pause_l();
1197    mVideoRenderer.clear();
1198
1199    shutdownVideoDecoder_l();
1200
1201    CHECK_EQ(initVideoDecoder(), (status_t)OK);
1202
1203    if (mLastVideoTimeUs >= 0) {
1204        mSeeking = SEEK;
1205        mSeekNotificationSent = true;
1206        mSeekTimeUs = mLastVideoTimeUs;
1207        modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1208    }
1209
1210    if (wasPlaying) {
1211        play_l();
1212    }
1213}
1214
1215void AwesomePlayer::setAudioSink(
1216        const sp<MediaPlayerBase::AudioSink> &audioSink) {
1217    Mutex::Autolock autoLock(mLock);
1218
1219    mAudioSink = audioSink;
1220}
1221
1222status_t AwesomePlayer::setLooping(bool shouldLoop) {
1223    Mutex::Autolock autoLock(mLock);
1224
1225    modifyFlags(LOOPING, CLEAR);
1226
1227    if (shouldLoop) {
1228        modifyFlags(LOOPING, SET);
1229    }
1230
1231    return OK;
1232}
1233
1234status_t AwesomePlayer::getDuration(int64_t *durationUs) {
1235    Mutex::Autolock autoLock(mMiscStateLock);
1236
1237    if (mDurationUs < 0) {
1238        return UNKNOWN_ERROR;
1239    }
1240
1241    *durationUs = mDurationUs;
1242
1243    return OK;
1244}
1245
1246status_t AwesomePlayer::getPosition(int64_t *positionUs) {
1247    if (mRTSPController != NULL) {
1248        *positionUs = mRTSPController->getNormalPlayTimeUs();
1249    }
1250    else if (mSeeking != NO_SEEK) {
1251        *positionUs = mSeekTimeUs;
1252    } else if (mVideoSource != NULL
1253            && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1254        Mutex::Autolock autoLock(mMiscStateLock);
1255        *positionUs = mVideoTimeUs;
1256    } else if (mAudioPlayer != NULL) {
1257        *positionUs = mAudioPlayer->getMediaTimeUs();
1258    } else {
1259        *positionUs = 0;
1260    }
1261
1262    return OK;
1263}
1264
1265status_t AwesomePlayer::seekTo(int64_t timeUs) {
1266    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
1267        Mutex::Autolock autoLock(mLock);
1268        return seekTo_l(timeUs);
1269    }
1270
1271    return OK;
1272}
1273
1274status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
1275    if (mTextPlayer != NULL) {
1276        if (index >= 0) { // to turn on a text track
1277            status_t err = mTextPlayer->setTimedTextTrackIndex(index);
1278            if (err != OK) {
1279                return err;
1280            }
1281
1282            modifyFlags(TEXT_RUNNING, SET);
1283            modifyFlags(TEXTPLAYER_STARTED, SET);
1284            return OK;
1285        } else { // to turn off the text track display
1286            if (mFlags  & TEXT_RUNNING) {
1287                modifyFlags(TEXT_RUNNING, CLEAR);
1288            }
1289            if (mFlags  & TEXTPLAYER_STARTED) {
1290                modifyFlags(TEXTPLAYER_STARTED, CLEAR);
1291            }
1292
1293            return mTextPlayer->setTimedTextTrackIndex(index);
1294        }
1295    } else {
1296        return INVALID_OPERATION;
1297    }
1298}
1299
1300// static
1301void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1302    static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1303}
1304
1305void AwesomePlayer::onRTSPSeekDone() {
1306    notifyListener_l(MEDIA_SEEK_COMPLETE);
1307    mSeekNotificationSent = true;
1308}
1309
1310status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
1311    if (mRTSPController != NULL) {
1312        mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
1313        return OK;
1314    }
1315
1316    if (mFlags & CACHE_UNDERRUN) {
1317        modifyFlags(CACHE_UNDERRUN, CLEAR);
1318        play_l();
1319    }
1320
1321    if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1322        // Video playback completed before, there's no pending
1323        // video event right now. In order for this new seek
1324        // to be honored, we need to post one.
1325
1326        postVideoEvent_l();
1327    }
1328
1329    mSeeking = SEEK;
1330    mSeekNotificationSent = false;
1331    mSeekTimeUs = timeUs;
1332    modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1333
1334    seekAudioIfNecessary_l();
1335
1336    if (mFlags & TEXTPLAYER_STARTED) {
1337        mTextPlayer->seekTo(mSeekTimeUs);
1338    }
1339
1340    if (!(mFlags & PLAYING)) {
1341        LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1342             " immediately.");
1343
1344        notifyListener_l(MEDIA_SEEK_COMPLETE);
1345        mSeekNotificationSent = true;
1346
1347        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1348            modifyFlags(SEEK_PREVIEW, SET);
1349            postVideoEvent_l();
1350        }
1351    }
1352
1353    return OK;
1354}
1355
1356void AwesomePlayer::seekAudioIfNecessary_l() {
1357    if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1358        mAudioPlayer->seekTo(mSeekTimeUs);
1359
1360        mWatchForAudioSeekComplete = true;
1361        mWatchForAudioEOS = true;
1362
1363        if (mDecryptHandle != NULL) {
1364            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1365                    Playback::PAUSE, 0);
1366            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1367                    Playback::START, mSeekTimeUs / 1000);
1368        }
1369    }
1370}
1371
1372void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1373    CHECK(source != NULL);
1374
1375    mAudioTrack = source;
1376}
1377
1378void AwesomePlayer::addTextSource(sp<MediaSource> source) {
1379    Mutex::Autolock autoLock(mTimedTextLock);
1380    CHECK(source != NULL);
1381
1382    if (mTextPlayer == NULL) {
1383        mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
1384    }
1385
1386    mTextPlayer->addTextSource(source);
1387}
1388
1389status_t AwesomePlayer::initAudioDecoder() {
1390    sp<MetaData> meta = mAudioTrack->getFormat();
1391
1392    const char *mime;
1393    CHECK(meta->findCString(kKeyMIMEType, &mime));
1394
1395    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1396        mAudioSource = mAudioTrack;
1397    } else {
1398        mAudioSource = OMXCodec::Create(
1399                mClient.interface(), mAudioTrack->getFormat(),
1400                false, // createEncoder
1401                mAudioTrack);
1402    }
1403
1404    if (mAudioSource != NULL) {
1405        int64_t durationUs;
1406        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1407            Mutex::Autolock autoLock(mMiscStateLock);
1408            if (mDurationUs < 0 || durationUs > mDurationUs) {
1409                mDurationUs = durationUs;
1410            }
1411        }
1412
1413        status_t err = mAudioSource->start();
1414
1415        if (err != OK) {
1416            mAudioSource.clear();
1417            return err;
1418        }
1419    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1420        // For legacy reasons we're simply going to ignore the absence
1421        // of an audio decoder for QCELP instead of aborting playback
1422        // altogether.
1423        return OK;
1424    }
1425
1426    if (mAudioSource != NULL) {
1427        Mutex::Autolock autoLock(mStatsLock);
1428        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
1429
1430        const char *component;
1431        if (!mAudioSource->getFormat()
1432                ->findCString(kKeyDecoderComponent, &component)) {
1433            component = "none";
1434        }
1435
1436        stat->mDecoderName = component;
1437    }
1438
1439    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1440}
1441
1442void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1443    CHECK(source != NULL);
1444
1445    mVideoTrack = source;
1446}
1447
1448status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1449
1450    // Either the application or the DRM system can independently say
1451    // that there must be a hardware-protected path to an external video sink.
1452    // For now we always require a hardware-protected path to external video sink
1453    // if content is DRMed, but eventually this could be optional per DRM agent.
1454    // When the application wants protection, then
1455    //   (USE_SURFACE_ALLOC && (mSurface != 0) &&
1456    //   (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1457    // will be true, but that part is already handled by SurfaceFlinger.
1458
1459#ifdef DEBUG_HDCP
1460    // For debugging, we allow a system property to control the protected usage.
1461    // In case of uninitialized or unexpected property, we default to "DRM only".
1462    bool setProtectionBit = false;
1463    char value[PROPERTY_VALUE_MAX];
1464    if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1465        if (!strcmp(value, "never")) {
1466            // nop
1467        } else if (!strcmp(value, "always")) {
1468            setProtectionBit = true;
1469        } else if (!strcmp(value, "drm-only")) {
1470            if (mDecryptHandle != NULL) {
1471                setProtectionBit = true;
1472            }
1473        // property value is empty, or unexpected value
1474        } else {
1475            if (mDecryptHandle != NULL) {
1476                setProtectionBit = true;
1477            }
1478        }
1479    // can' read property value
1480    } else {
1481        if (mDecryptHandle != NULL) {
1482            setProtectionBit = true;
1483        }
1484    }
1485    // note that usage bit is already cleared, so no need to clear it in the "else" case
1486    if (setProtectionBit) {
1487        flags |= OMXCodec::kEnableGrallocUsageProtected;
1488    }
1489#else
1490    if (mDecryptHandle != NULL) {
1491        flags |= OMXCodec::kEnableGrallocUsageProtected;
1492    }
1493#endif
1494    LOGV("initVideoDecoder flags=0x%x", flags);
1495    mVideoSource = OMXCodec::Create(
1496            mClient.interface(), mVideoTrack->getFormat(),
1497            false, // createEncoder
1498            mVideoTrack,
1499            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
1500
1501    if (mVideoSource != NULL) {
1502        int64_t durationUs;
1503        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1504            Mutex::Autolock autoLock(mMiscStateLock);
1505            if (mDurationUs < 0 || durationUs > mDurationUs) {
1506                mDurationUs = durationUs;
1507            }
1508        }
1509
1510        status_t err = mVideoSource->start();
1511
1512        if (err != OK) {
1513            mVideoSource.clear();
1514            return err;
1515        }
1516    }
1517
1518    if (mVideoSource != NULL) {
1519        Mutex::Autolock autoLock(mStatsLock);
1520        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1521
1522        const char *component;
1523        CHECK(mVideoSource->getFormat()
1524                ->findCString(kKeyDecoderComponent, &component));
1525
1526        stat->mDecoderName = component;
1527    }
1528
1529    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1530}
1531
1532void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1533    if (mSeeking == SEEK_VIDEO_ONLY) {
1534        mSeeking = NO_SEEK;
1535        return;
1536    }
1537
1538    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1539        return;
1540    }
1541
1542    if (mAudioPlayer != NULL) {
1543        LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1544
1545        // If we don't have a video time, seek audio to the originally
1546        // requested seek time instead.
1547
1548        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1549        mWatchForAudioSeekComplete = true;
1550        mWatchForAudioEOS = true;
1551    } else if (!mSeekNotificationSent) {
1552        // If we're playing video only, report seek complete now,
1553        // otherwise audio player will notify us later.
1554        notifyListener_l(MEDIA_SEEK_COMPLETE);
1555        mSeekNotificationSent = true;
1556    }
1557
1558    modifyFlags(FIRST_FRAME, SET);
1559    mSeeking = NO_SEEK;
1560
1561    if (mDecryptHandle != NULL) {
1562        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1563                Playback::PAUSE, 0);
1564        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1565                Playback::START, videoTimeUs / 1000);
1566    }
1567}
1568
1569void AwesomePlayer::onVideoEvent() {
1570    Mutex::Autolock autoLock(mLock);
1571    if (!mVideoEventPending) {
1572        // The event has been cancelled in reset_l() but had already
1573        // been scheduled for execution at that time.
1574        return;
1575    }
1576    mVideoEventPending = false;
1577
1578    if (mSeeking != NO_SEEK) {
1579        if (mVideoBuffer) {
1580            mVideoBuffer->release();
1581            mVideoBuffer = NULL;
1582        }
1583
1584        if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
1585                && !(mFlags & SEEK_PREVIEW)) {
1586            // We're going to seek the video source first, followed by
1587            // the audio source.
1588            // In order to avoid jumps in the DataSource offset caused by
1589            // the audio codec prefetching data from the old locations
1590            // while the video codec is already reading data from the new
1591            // locations, we'll "pause" the audio source, causing it to
1592            // stop reading input data until a subsequent seek.
1593
1594            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1595                mAudioPlayer->pause();
1596
1597                modifyFlags(AUDIO_RUNNING, CLEAR);
1598            }
1599            mAudioSource->pause();
1600        }
1601    }
1602
1603    if (!mVideoBuffer) {
1604        MediaSource::ReadOptions options;
1605        if (mSeeking != NO_SEEK) {
1606            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1607
1608            options.setSeekTo(
1609                    mSeekTimeUs,
1610                    mSeeking == SEEK_VIDEO_ONLY
1611                        ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1612                        : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1613        }
1614        for (;;) {
1615            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1616            options.clearSeekTo();
1617
1618            if (err != OK) {
1619                CHECK(mVideoBuffer == NULL);
1620
1621                if (err == INFO_FORMAT_CHANGED) {
1622                    LOGV("VideoSource signalled format change.");
1623
1624                    notifyVideoSize_l();
1625
1626                    if (mVideoRenderer != NULL) {
1627                        mVideoRendererIsPreview = false;
1628                        initRenderer_l();
1629                    }
1630                    continue;
1631                }
1632
1633                // So video playback is complete, but we may still have
1634                // a seek request pending that needs to be applied
1635                // to the audio track.
1636                if (mSeeking != NO_SEEK) {
1637                    LOGV("video stream ended while seeking!");
1638                }
1639                finishSeekIfNecessary(-1);
1640
1641                if (mAudioPlayer != NULL
1642                        && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1643                    startAudioPlayer_l();
1644                }
1645
1646                modifyFlags(VIDEO_AT_EOS, SET);
1647                postStreamDoneEvent_l(err);
1648                return;
1649            }
1650
1651            if (mVideoBuffer->range_length() == 0) {
1652                // Some decoders, notably the PV AVC software decoder
1653                // return spurious empty buffers that we just want to ignore.
1654
1655                mVideoBuffer->release();
1656                mVideoBuffer = NULL;
1657                continue;
1658            }
1659
1660            break;
1661        }
1662
1663        {
1664            Mutex::Autolock autoLock(mStatsLock);
1665            ++mStats.mNumVideoFramesDecoded;
1666        }
1667    }
1668
1669    int64_t timeUs;
1670    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1671
1672    mLastVideoTimeUs = timeUs;
1673
1674    if (mSeeking == SEEK_VIDEO_ONLY) {
1675        if (mSeekTimeUs > timeUs) {
1676            LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1677                 mSeekTimeUs, timeUs);
1678        }
1679    }
1680
1681    {
1682        Mutex::Autolock autoLock(mMiscStateLock);
1683        mVideoTimeUs = timeUs;
1684    }
1685
1686    SeekType wasSeeking = mSeeking;
1687    finishSeekIfNecessary(timeUs);
1688
1689    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1690        status_t err = startAudioPlayer_l();
1691        if (err != OK) {
1692            LOGE("Starting the audio player failed w/ err %d", err);
1693            return;
1694        }
1695    }
1696
1697    if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1698        mTextPlayer->resume();
1699        modifyFlags(TEXT_RUNNING, SET);
1700    }
1701
1702    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1703
1704    if (mFlags & FIRST_FRAME) {
1705        modifyFlags(FIRST_FRAME, CLEAR);
1706        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1707    }
1708
1709    int64_t realTimeUs, mediaTimeUs;
1710    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1711        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1712        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1713    }
1714
1715    if (wasSeeking == SEEK_VIDEO_ONLY) {
1716        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1717
1718        int64_t latenessUs = nowUs - timeUs;
1719
1720        if (latenessUs > 0) {
1721            LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1722        }
1723    }
1724
1725    if (wasSeeking == NO_SEEK) {
1726        // Let's display the first frame after seeking right away.
1727
1728        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1729
1730        int64_t latenessUs = nowUs - timeUs;
1731
1732        if (latenessUs > 500000ll
1733                && mRTSPController == NULL
1734                && mAudioPlayer != NULL
1735                && mAudioPlayer->getMediaTimeMapping(
1736                    &realTimeUs, &mediaTimeUs)) {
1737            LOGI("we're much too late (%.2f secs), video skipping ahead",
1738                 latenessUs / 1E6);
1739
1740            mVideoBuffer->release();
1741            mVideoBuffer = NULL;
1742
1743            mSeeking = SEEK_VIDEO_ONLY;
1744            mSeekTimeUs = mediaTimeUs;
1745
1746            postVideoEvent_l();
1747            return;
1748        }
1749
1750        if (latenessUs > 40000) {
1751            // We're more than 40ms late.
1752            LOGV("we're late by %lld us (%.2f secs), dropping frame",
1753                 latenessUs, latenessUs / 1E6);
1754            mVideoBuffer->release();
1755            mVideoBuffer = NULL;
1756
1757            {
1758                Mutex::Autolock autoLock(mStatsLock);
1759                ++mStats.mNumVideoFramesDropped;
1760            }
1761
1762            postVideoEvent_l();
1763            return;
1764        }
1765
1766        if (latenessUs < -10000) {
1767            // We're more than 10ms early.
1768
1769            postVideoEvent_l(10000);
1770            return;
1771        }
1772    }
1773
1774    if ((mNativeWindow != NULL)
1775            && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
1776        mVideoRendererIsPreview = false;
1777
1778        initRenderer_l();
1779    }
1780
1781    if (mVideoRenderer != NULL) {
1782        mVideoRenderer->render(mVideoBuffer);
1783    }
1784
1785    mVideoBuffer->release();
1786    mVideoBuffer = NULL;
1787
1788    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
1789        modifyFlags(SEEK_PREVIEW, CLEAR);
1790        return;
1791    }
1792
1793    postVideoEvent_l();
1794}
1795
1796void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1797    if (mVideoEventPending) {
1798        return;
1799    }
1800
1801    mVideoEventPending = true;
1802    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1803}
1804
1805void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1806    if (mStreamDoneEventPending) {
1807        return;
1808    }
1809    mStreamDoneEventPending = true;
1810
1811    mStreamDoneStatus = status;
1812    mQueue.postEvent(mStreamDoneEvent);
1813}
1814
1815void AwesomePlayer::postBufferingEvent_l() {
1816    if (mBufferingEventPending) {
1817        return;
1818    }
1819    mBufferingEventPending = true;
1820    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1821}
1822
1823void AwesomePlayer::postVideoLagEvent_l() {
1824    if (mVideoLagEventPending) {
1825        return;
1826    }
1827    mVideoLagEventPending = true;
1828    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1829}
1830
1831void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
1832    if (mAudioStatusEventPending) {
1833        return;
1834    }
1835    mAudioStatusEventPending = true;
1836    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
1837}
1838
1839void AwesomePlayer::onCheckAudioStatus() {
1840    Mutex::Autolock autoLock(mLock);
1841    if (!mAudioStatusEventPending) {
1842        // Event was dispatched and while we were blocking on the mutex,
1843        // has already been cancelled.
1844        return;
1845    }
1846
1847    mAudioStatusEventPending = false;
1848
1849    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1850        mWatchForAudioSeekComplete = false;
1851
1852        if (!mSeekNotificationSent) {
1853            notifyListener_l(MEDIA_SEEK_COMPLETE);
1854            mSeekNotificationSent = true;
1855        }
1856
1857        mSeeking = NO_SEEK;
1858    }
1859
1860    status_t finalStatus;
1861    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1862        mWatchForAudioEOS = false;
1863        modifyFlags(AUDIO_AT_EOS, SET);
1864        modifyFlags(FIRST_FRAME, SET);
1865        postStreamDoneEvent_l(finalStatus);
1866    }
1867}
1868
1869status_t AwesomePlayer::prepare() {
1870    Mutex::Autolock autoLock(mLock);
1871    return prepare_l();
1872}
1873
1874status_t AwesomePlayer::prepare_l() {
1875    if (mFlags & PREPARED) {
1876        return OK;
1877    }
1878
1879    if (mFlags & PREPARING) {
1880        return UNKNOWN_ERROR;
1881    }
1882
1883    mIsAsyncPrepare = false;
1884    status_t err = prepareAsync_l();
1885
1886    if (err != OK) {
1887        return err;
1888    }
1889
1890    while (mFlags & PREPARING) {
1891        mPreparedCondition.wait(mLock);
1892    }
1893
1894    return mPrepareResult;
1895}
1896
1897status_t AwesomePlayer::prepareAsync() {
1898    Mutex::Autolock autoLock(mLock);
1899
1900    if (mFlags & PREPARING) {
1901        return UNKNOWN_ERROR;  // async prepare already pending
1902    }
1903
1904    mIsAsyncPrepare = true;
1905    return prepareAsync_l();
1906}
1907
1908status_t AwesomePlayer::prepareAsync_l() {
1909    if (mFlags & PREPARING) {
1910        return UNKNOWN_ERROR;  // async prepare already pending
1911    }
1912
1913    if (!mQueueStarted) {
1914        mQueue.start();
1915        mQueueStarted = true;
1916    }
1917
1918    modifyFlags(PREPARING, SET);
1919    mAsyncPrepareEvent = new AwesomeEvent(
1920            this, &AwesomePlayer::onPrepareAsyncEvent);
1921
1922    mQueue.postEvent(mAsyncPrepareEvent);
1923
1924    return OK;
1925}
1926
1927status_t AwesomePlayer::finishSetDataSource_l() {
1928    sp<DataSource> dataSource;
1929
1930    bool isWidevineStreaming = false;
1931    if (!strncasecmp("widevine://", mUri.string(), 11)) {
1932        isWidevineStreaming = true;
1933
1934        String8 newURI = String8("http://");
1935        newURI.append(mUri.string() + 11);
1936
1937        mUri = newURI;
1938    }
1939
1940    if (!strncasecmp("http://", mUri.string(), 7)
1941            || !strncasecmp("https://", mUri.string(), 8)
1942            || isWidevineStreaming) {
1943        mConnectingDataSource = HTTPBase::Create(
1944                (mFlags & INCOGNITO)
1945                    ? HTTPBase::kFlagIncognito
1946                    : 0);
1947
1948        if (mUIDValid) {
1949            mConnectingDataSource->setUID(mUID);
1950        }
1951
1952        mLock.unlock();
1953        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
1954        mLock.lock();
1955
1956        if (err != OK) {
1957            mConnectingDataSource.clear();
1958
1959            LOGI("mConnectingDataSource->connect() returned %d", err);
1960            return err;
1961        }
1962
1963        if (!isWidevineStreaming) {
1964            // The widevine extractor does its own caching.
1965
1966#if 0
1967            mCachedSource = new NuCachedSource2(
1968                    new ThrottledSource(
1969                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1970#else
1971            mCachedSource = new NuCachedSource2(mConnectingDataSource);
1972#endif
1973
1974            dataSource = mCachedSource;
1975        } else {
1976            dataSource = mConnectingDataSource;
1977        }
1978
1979        mConnectingDataSource.clear();
1980
1981
1982        String8 contentType = dataSource->getMIMEType();
1983
1984        if (strncasecmp(contentType.string(), "audio/", 6)) {
1985            // We're not doing this for streams that appear to be audio-only
1986            // streams to ensure that even low bandwidth streams start
1987            // playing back fairly instantly.
1988
1989            // We're going to prefill the cache before trying to instantiate
1990            // the extractor below, as the latter is an operation that otherwise
1991            // could block on the datasource for a significant amount of time.
1992            // During that time we'd be unable to abort the preparation phase
1993            // without this prefill.
1994            if (mCachedSource != NULL) {
1995                // We're going to prefill the cache before trying to instantiate
1996                // the extractor below, as the latter is an operation that otherwise
1997                // could block on the datasource for a significant amount of time.
1998                // During that time we'd be unable to abort the preparation phase
1999                // without this prefill.
2000
2001                mLock.unlock();
2002
2003                for (;;) {
2004                    status_t finalStatus;
2005                    size_t cachedDataRemaining =
2006                        mCachedSource->approxDataRemaining(&finalStatus);
2007
2008                    if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
2009                            || (mFlags & PREPARE_CANCELLED)) {
2010                        break;
2011                    }
2012
2013                    usleep(200000);
2014                }
2015
2016                mLock.lock();
2017            }
2018
2019            if (mFlags & PREPARE_CANCELLED) {
2020                LOGI("Prepare cancelled while waiting for initial cache fill.");
2021                return UNKNOWN_ERROR;
2022            }
2023        }
2024    } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
2025        if (mLooper == NULL) {
2026            mLooper = new ALooper;
2027            mLooper->setName("rtsp");
2028            mLooper->start();
2029        }
2030        mRTSPController = new ARTSPController(mLooper);
2031        mConnectingRTSPController = mRTSPController;
2032
2033        if (mUIDValid) {
2034            mConnectingRTSPController->setUID(mUID);
2035        }
2036
2037        mLock.unlock();
2038        status_t err = mRTSPController->connect(mUri.string());
2039        mLock.lock();
2040
2041        mConnectingRTSPController.clear();
2042
2043        LOGI("ARTSPController::connect returned %d", err);
2044
2045        if (err != OK) {
2046            mRTSPController.clear();
2047            return err;
2048        }
2049
2050        sp<MediaExtractor> extractor = mRTSPController.get();
2051        return setDataSource_l(extractor);
2052    } else {
2053        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2054    }
2055
2056    if (dataSource == NULL) {
2057        return UNKNOWN_ERROR;
2058    }
2059
2060    sp<MediaExtractor> extractor;
2061
2062    if (isWidevineStreaming) {
2063        String8 mimeType;
2064        float confidence;
2065        sp<AMessage> dummy;
2066        bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
2067
2068        if (!success
2069                || strcasecmp(
2070                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2071            return ERROR_UNSUPPORTED;
2072        }
2073
2074        mWVMExtractor = new WVMExtractor(dataSource);
2075        mWVMExtractor->setAdaptiveStreamingMode(true);
2076        extractor = mWVMExtractor;
2077    } else {
2078        extractor = MediaExtractor::Create(dataSource);
2079
2080        if (extractor == NULL) {
2081            return UNKNOWN_ERROR;
2082        }
2083    }
2084
2085    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
2086
2087    if (mDecryptHandle != NULL) {
2088        CHECK(mDrmManagerClient);
2089        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
2090            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
2091        }
2092    }
2093
2094    status_t err = setDataSource_l(extractor);
2095
2096    if (err != OK) {
2097        mWVMExtractor.clear();
2098
2099        return err;
2100    }
2101
2102    return OK;
2103}
2104
2105void AwesomePlayer::abortPrepare(status_t err) {
2106    CHECK(err != OK);
2107
2108    if (mIsAsyncPrepare) {
2109        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2110    }
2111
2112    mPrepareResult = err;
2113    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2114    mAsyncPrepareEvent = NULL;
2115    mPreparedCondition.broadcast();
2116}
2117
2118// static
2119bool AwesomePlayer::ContinuePreparation(void *cookie) {
2120    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2121
2122    return (me->mFlags & PREPARE_CANCELLED) == 0;
2123}
2124
2125void AwesomePlayer::onPrepareAsyncEvent() {
2126    Mutex::Autolock autoLock(mLock);
2127
2128    if (mFlags & PREPARE_CANCELLED) {
2129        LOGI("prepare was cancelled before doing anything");
2130        abortPrepare(UNKNOWN_ERROR);
2131        return;
2132    }
2133
2134    if (mUri.size() > 0) {
2135        status_t err = finishSetDataSource_l();
2136
2137        if (err != OK) {
2138            abortPrepare(err);
2139            return;
2140        }
2141    }
2142
2143    if (mVideoTrack != NULL && mVideoSource == NULL) {
2144        status_t err = initVideoDecoder();
2145
2146        if (err != OK) {
2147            abortPrepare(err);
2148            return;
2149        }
2150    }
2151
2152    if (mAudioTrack != NULL && mAudioSource == NULL) {
2153        status_t err = initAudioDecoder();
2154
2155        if (err != OK) {
2156            abortPrepare(err);
2157            return;
2158        }
2159    }
2160
2161    modifyFlags(PREPARING_CONNECTED, SET);
2162
2163    if (isStreamingHTTP() || mRTSPController != NULL) {
2164        postBufferingEvent_l();
2165    } else {
2166        finishAsyncPrepare_l();
2167    }
2168}
2169
2170void AwesomePlayer::finishAsyncPrepare_l() {
2171    if (mIsAsyncPrepare) {
2172        if (mVideoSource == NULL) {
2173            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2174        } else {
2175            notifyVideoSize_l();
2176        }
2177
2178        notifyListener_l(MEDIA_PREPARED);
2179    }
2180
2181    mPrepareResult = OK;
2182    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2183    modifyFlags(PREPARED, SET);
2184    mAsyncPrepareEvent = NULL;
2185    mPreparedCondition.broadcast();
2186}
2187
2188uint32_t AwesomePlayer::flags() const {
2189    return mExtractorFlags;
2190}
2191
2192void AwesomePlayer::postAudioEOS(int64_t delayUs) {
2193    Mutex::Autolock autoLock(mLock);
2194    postCheckAudioStatusEvent_l(delayUs);
2195}
2196
2197void AwesomePlayer::postAudioSeekComplete() {
2198    Mutex::Autolock autoLock(mLock);
2199    postAudioSeekComplete_l();
2200}
2201
2202void AwesomePlayer::postAudioSeekComplete_l() {
2203    postCheckAudioStatusEvent_l(0 /* delayUs */);
2204}
2205
2206status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
2207    switch (key) {
2208        case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX:
2209        {
2210            Mutex::Autolock autoLock(mTimedTextLock);
2211            return setTimedTextTrackIndex(request.readInt32());
2212        }
2213        case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE:
2214        {
2215            Mutex::Autolock autoLock(mTimedTextLock);
2216            if (mTextPlayer == NULL) {
2217                mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
2218            }
2219
2220            return mTextPlayer->setParameter(key, request);
2221        }
2222        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2223        {
2224            return setCacheStatCollectFreq(request);
2225        }
2226        default:
2227        {
2228            return ERROR_UNSUPPORTED;
2229        }
2230    }
2231}
2232
2233status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2234    if (mCachedSource != NULL) {
2235        int32_t freqMs = request.readInt32();
2236        LOGD("Request to keep cache stats in the past %d ms",
2237            freqMs);
2238        return mCachedSource->setCacheStatCollectFreq(freqMs);
2239    }
2240    return ERROR_UNSUPPORTED;
2241}
2242
2243status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
2244    switch (key) {
2245    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2246        {
2247            int32_t channelCount;
2248            if (mAudioTrack == 0 ||
2249                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2250                channelCount = 0;
2251            }
2252            reply->writeInt32(channelCount);
2253        }
2254        return OK;
2255    default:
2256        {
2257            return ERROR_UNSUPPORTED;
2258        }
2259    }
2260}
2261
2262bool AwesomePlayer::isStreamingHTTP() const {
2263    return mCachedSource != NULL || mWVMExtractor != NULL;
2264}
2265
2266status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2267    Mutex::Autolock autoLock(mStatsLock);
2268
2269    FILE *out = fdopen(dup(fd), "w");
2270
2271    fprintf(out, " AwesomePlayer\n");
2272    if (mStats.mFd < 0) {
2273        fprintf(out, "  URI(%s)", mStats.mURI.string());
2274    } else {
2275        fprintf(out, "  fd(%d)", mStats.mFd);
2276    }
2277
2278    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2279
2280    if (mStats.mBitrate >= 0) {
2281        fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2282    }
2283
2284    fprintf(out, "\n");
2285
2286    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2287        const TrackStat &stat = mStats.mTracks.itemAt(i);
2288
2289        fprintf(out, "  Track %d\n", i + 1);
2290        fprintf(out, "   MIME(%s)", stat.mMIME.string());
2291
2292        if (!stat.mDecoderName.isEmpty()) {
2293            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2294        }
2295
2296        fprintf(out, "\n");
2297
2298        if ((ssize_t)i == mStats.mVideoTrackIndex) {
2299            fprintf(out,
2300                    "   videoDimensions(%d x %d), "
2301                    "numVideoFramesDecoded(%lld), "
2302                    "numVideoFramesDropped(%lld)\n",
2303                    mStats.mVideoWidth,
2304                    mStats.mVideoHeight,
2305                    mStats.mNumVideoFramesDecoded,
2306                    mStats.mNumVideoFramesDropped);
2307        }
2308    }
2309
2310    fclose(out);
2311    out = NULL;
2312
2313    return OK;
2314}
2315
2316void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2317    switch (mode) {
2318        case SET:
2319            mFlags |= value;
2320            break;
2321        case CLEAR:
2322            mFlags &= ~value;
2323            break;
2324        case ASSIGN:
2325            mFlags = value;
2326            break;
2327        default:
2328            TRESPASS();
2329    }
2330
2331    {
2332        Mutex::Autolock autoLock(mStatsLock);
2333        mStats.mFlags = mFlags;
2334    }
2335}
2336
2337}  // namespace android
2338