AwesomePlayer.cpp revision 1173118eace0e9e347cb007f0da817cee87579ed
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//#define LOG_NDEBUG 0
18#define LOG_TAG "AwesomePlayer"
19#include <utils/Log.h>
20
21#include <dlfcn.h>
22
23#include "include/ARTSPController.h"
24#include "include/AwesomePlayer.h"
25#include "include/SoftwareRenderer.h"
26#include "include/NuCachedSource2.h"
27#include "include/ThrottledSource.h"
28#include "include/MPEG2TSExtractor.h"
29
30#include <binder/IPCThreadState.h>
31#include <binder/IServiceManager.h>
32#include <media/IMediaPlayerService.h>
33#include <media/stagefright/foundation/hexdump.h>
34#include <media/stagefright/foundation/ADebug.h>
35#include <media/stagefright/AudioPlayer.h>
36#include <media/stagefright/DataSource.h>
37#include <media/stagefright/FileSource.h>
38#include <media/stagefright/MediaBuffer.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/MediaExtractor.h>
41#include <media/stagefright/MediaSource.h>
42#include <media/stagefright/MetaData.h>
43#include <media/stagefright/OMXCodec.h>
44
45#include <surfaceflinger/Surface.h>
46#include <gui/ISurfaceTexture.h>
47#include <gui/SurfaceTextureClient.h>
48
49#include <media/stagefright/foundation/ALooper.h>
50#include <media/stagefright/foundation/AMessage.h>
51
52#define USE_SURFACE_ALLOC 1
53#define FRAME_DROP_FREQ 7
54
55namespace android {
56
57static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
58static int64_t kHighWaterMarkUs = 10000000ll;  // 10secs
59static int64_t kHighWaterMarkRTSPUs = 4000000ll;  // 4secs
60static const size_t kLowWaterMarkBytes = 40000;
61static const size_t kHighWaterMarkBytes = 200000;
62
63struct AwesomeEvent : public TimedEventQueue::Event {
64    AwesomeEvent(
65            AwesomePlayer *player,
66            void (AwesomePlayer::*method)())
67        : mPlayer(player),
68          mMethod(method) {
69    }
70
71protected:
72    virtual ~AwesomeEvent() {}
73
74    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
75        (mPlayer->*mMethod)();
76    }
77
78private:
79    AwesomePlayer *mPlayer;
80    void (AwesomePlayer::*mMethod)();
81
82    AwesomeEvent(const AwesomeEvent &);
83    AwesomeEvent &operator=(const AwesomeEvent &);
84};
85
86struct AwesomeLocalRenderer : public AwesomeRenderer {
87    AwesomeLocalRenderer(
88            const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
89        : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
90    }
91
92    virtual void render(MediaBuffer *buffer) {
93        render((const uint8_t *)buffer->data() + buffer->range_offset(),
94               buffer->range_length());
95    }
96
97    void render(const void *data, size_t size) {
98        mTarget->render(data, size, NULL);
99    }
100
101protected:
102    virtual ~AwesomeLocalRenderer() {
103        delete mTarget;
104        mTarget = NULL;
105    }
106
107private:
108    SoftwareRenderer *mTarget;
109
110    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
111    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
112};
113
114struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
115    AwesomeNativeWindowRenderer(
116            const sp<ANativeWindow> &nativeWindow,
117            int32_t rotationDegrees)
118        : mNativeWindow(nativeWindow) {
119        applyRotation(rotationDegrees);
120    }
121
122    virtual void render(MediaBuffer *buffer) {
123        status_t err = mNativeWindow->queueBuffer(
124                mNativeWindow.get(), buffer->graphicBuffer().get());
125        if (err != 0) {
126            LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
127                    -err);
128            return;
129        }
130
131        sp<MetaData> metaData = buffer->meta_data();
132        metaData->setInt32(kKeyRendered, 1);
133    }
134
135protected:
136    virtual ~AwesomeNativeWindowRenderer() {}
137
138private:
139    sp<ANativeWindow> mNativeWindow;
140
141    void applyRotation(int32_t rotationDegrees) {
142        uint32_t transform;
143        switch (rotationDegrees) {
144            case 0: transform = 0; break;
145            case 90: transform = HAL_TRANSFORM_ROT_90; break;
146            case 180: transform = HAL_TRANSFORM_ROT_180; break;
147            case 270: transform = HAL_TRANSFORM_ROT_270; break;
148            default: transform = 0; break;
149        }
150
151        if (transform) {
152            CHECK_EQ(0, native_window_set_buffers_transform(
153                        mNativeWindow.get(), transform));
154        }
155    }
156
157    AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
158    AwesomeNativeWindowRenderer &operator=(
159            const AwesomeNativeWindowRenderer &);
160};
161
162// To collect the decoder usage
163void addBatteryData(uint32_t params) {
164    sp<IBinder> binder =
165        defaultServiceManager()->getService(String16("media.player"));
166    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
167    CHECK(service.get() != NULL);
168
169    service->addBatteryData(params);
170}
171
172////////////////////////////////////////////////////////////////////////////////
173AwesomePlayer::AwesomePlayer()
174    : mQueueStarted(false),
175      mTimeSource(NULL),
176      mVideoRendererIsPreview(false),
177      mAudioPlayer(NULL),
178      mDisplayWidth(0),
179      mDisplayHeight(0),
180      mFlags(0),
181      mExtractorFlags(0),
182      mVideoBuffer(NULL),
183      mDecryptHandle(NULL) {
184    CHECK_EQ(mClient.connect(), (status_t)OK);
185
186    DataSource::RegisterDefaultSniffers();
187
188    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
189    mVideoEventPending = false;
190    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
191    mStreamDoneEventPending = false;
192    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
193    mBufferingEventPending = false;
194    mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
195    mVideoEventPending = false;
196
197    mCheckAudioStatusEvent = new AwesomeEvent(
198            this, &AwesomePlayer::onCheckAudioStatus);
199
200    mAudioStatusEventPending = false;
201
202    reset();
203}
204
205AwesomePlayer::~AwesomePlayer() {
206    if (mQueueStarted) {
207        mQueue.stop();
208    }
209
210    reset();
211
212    mClient.disconnect();
213}
214
215void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
216    mQueue.cancelEvent(mVideoEvent->eventID());
217    mVideoEventPending = false;
218    mQueue.cancelEvent(mStreamDoneEvent->eventID());
219    mStreamDoneEventPending = false;
220    mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
221    mAudioStatusEventPending = false;
222    mQueue.cancelEvent(mVideoLagEvent->eventID());
223    mVideoLagEventPending = false;
224
225    if (!keepBufferingGoing) {
226        mQueue.cancelEvent(mBufferingEvent->eventID());
227        mBufferingEventPending = false;
228    }
229}
230
231void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
232    Mutex::Autolock autoLock(mLock);
233    mListener = listener;
234}
235
236status_t AwesomePlayer::setDataSource(
237        const char *uri, const KeyedVector<String8, String8> *headers) {
238    Mutex::Autolock autoLock(mLock);
239    return setDataSource_l(uri, headers);
240}
241
242status_t AwesomePlayer::setDataSource_l(
243        const char *uri, const KeyedVector<String8, String8> *headers) {
244    reset_l();
245
246    mUri = uri;
247
248    if (headers) {
249        mUriHeaders = *headers;
250    }
251
252    // The actual work will be done during preparation in the call to
253    // ::finishSetDataSource_l to avoid blocking the calling thread in
254    // setDataSource for any significant time.
255
256    return OK;
257}
258
259status_t AwesomePlayer::setDataSource(
260        int fd, int64_t offset, int64_t length) {
261    Mutex::Autolock autoLock(mLock);
262
263    reset_l();
264
265    sp<DataSource> dataSource = new FileSource(fd, offset, length);
266
267    status_t err = dataSource->initCheck();
268
269    if (err != OK) {
270        return err;
271    }
272
273    mFileSource = dataSource;
274
275    return setDataSource_l(dataSource);
276}
277
278status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
279    return INVALID_OPERATION;
280}
281
282status_t AwesomePlayer::setDataSource_l(
283        const sp<DataSource> &dataSource) {
284    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
285
286    if (extractor == NULL) {
287        return UNKNOWN_ERROR;
288    }
289
290    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
291    if (mDecryptHandle != NULL) {
292        CHECK(mDrmManagerClient);
293        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
294            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
295        }
296    }
297
298    return setDataSource_l(extractor);
299}
300
301status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
302    // Attempt to approximate overall stream bitrate by summing all
303    // tracks' individual bitrates, if not all of them advertise bitrate,
304    // we have to fail.
305
306    int64_t totalBitRate = 0;
307
308    for (size_t i = 0; i < extractor->countTracks(); ++i) {
309        sp<MetaData> meta = extractor->getTrackMetaData(i);
310
311        int32_t bitrate;
312        if (!meta->findInt32(kKeyBitRate, &bitrate)) {
313            totalBitRate = -1;
314            break;
315        }
316
317        totalBitRate += bitrate;
318    }
319
320    mBitrate = totalBitRate;
321
322    LOGV("mBitrate = %lld bits/sec", mBitrate);
323
324    bool haveAudio = false;
325    bool haveVideo = false;
326    for (size_t i = 0; i < extractor->countTracks(); ++i) {
327        sp<MetaData> meta = extractor->getTrackMetaData(i);
328
329        const char *mime;
330        CHECK(meta->findCString(kKeyMIMEType, &mime));
331
332        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
333            setVideoSource(extractor->getTrack(i));
334            haveVideo = true;
335
336            // Set the presentation/display size
337            int32_t displayWidth, displayHeight;
338            bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
339            if (success) {
340                success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
341            }
342            if (success) {
343                mDisplayWidth = displayWidth;
344                mDisplayHeight = displayHeight;
345            }
346
347        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
348            setAudioSource(extractor->getTrack(i));
349            haveAudio = true;
350
351            if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
352                // Only do this for vorbis audio, none of the other audio
353                // formats even support this ringtone specific hack and
354                // retrieving the metadata on some extractors may turn out
355                // to be very expensive.
356                sp<MetaData> fileMeta = extractor->getMetaData();
357                int32_t loop;
358                if (fileMeta != NULL
359                        && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
360                    mFlags |= AUTO_LOOPING;
361                }
362            }
363        }
364
365        if (haveAudio && haveVideo) {
366            break;
367        }
368    }
369
370    if (!haveAudio && !haveVideo) {
371        return UNKNOWN_ERROR;
372    }
373
374    mExtractorFlags = extractor->flags();
375
376    return OK;
377}
378
379void AwesomePlayer::reset() {
380    Mutex::Autolock autoLock(mLock);
381    reset_l();
382}
383
384void AwesomePlayer::reset_l() {
385    mDisplayWidth = 0;
386    mDisplayHeight = 0;
387
388    if (mDecryptHandle != NULL) {
389            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
390                    Playback::STOP, 0);
391            mDecryptHandle = NULL;
392            mDrmManagerClient = NULL;
393    }
394
395    if (mFlags & PLAYING) {
396        uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
397        if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
398            params |= IMediaPlayerService::kBatteryDataTrackAudio;
399        }
400        if (mVideoSource != NULL) {
401            params |= IMediaPlayerService::kBatteryDataTrackVideo;
402        }
403        addBatteryData(params);
404    }
405
406    if (mFlags & PREPARING) {
407        mFlags |= PREPARE_CANCELLED;
408        if (mConnectingDataSource != NULL) {
409            LOGI("interrupting the connection process");
410            mConnectingDataSource->disconnect();
411        } else if (mConnectingRTSPController != NULL) {
412            LOGI("interrupting the connection process");
413            mConnectingRTSPController->disconnect();
414        }
415
416        if (mFlags & PREPARING_CONNECTED) {
417            // We are basically done preparing, we're just buffering
418            // enough data to start playback, we can safely interrupt that.
419            finishAsyncPrepare_l();
420        }
421    }
422
423    while (mFlags & PREPARING) {
424        mPreparedCondition.wait(mLock);
425    }
426
427    cancelPlayerEvents();
428
429    mCachedSource.clear();
430    mAudioTrack.clear();
431    mVideoTrack.clear();
432
433    // Shutdown audio first, so that the respone to the reset request
434    // appears to happen instantaneously as far as the user is concerned
435    // If we did this later, audio would continue playing while we
436    // shutdown the video-related resources and the player appear to
437    // not be as responsive to a reset request.
438    if (mAudioPlayer == NULL && mAudioSource != NULL) {
439        // If we had an audio player, it would have effectively
440        // taken possession of the audio source and stopped it when
441        // _it_ is stopped. Otherwise this is still our responsibility.
442        mAudioSource->stop();
443    }
444    mAudioSource.clear();
445
446    mTimeSource = NULL;
447
448    delete mAudioPlayer;
449    mAudioPlayer = NULL;
450
451    mVideoRenderer.clear();
452
453    if (mVideoBuffer) {
454        mVideoBuffer->release();
455        mVideoBuffer = NULL;
456    }
457
458    if (mRTSPController != NULL) {
459        mRTSPController->disconnect();
460        mRTSPController.clear();
461    }
462
463    if (mVideoSource != NULL) {
464        mVideoSource->stop();
465
466        // The following hack is necessary to ensure that the OMX
467        // component is completely released by the time we may try
468        // to instantiate it again.
469        wp<MediaSource> tmp = mVideoSource;
470        mVideoSource.clear();
471        while (tmp.promote() != NULL) {
472            usleep(1000);
473        }
474        IPCThreadState::self()->flushCommands();
475    }
476
477    mDurationUs = -1;
478    mFlags = 0;
479    mExtractorFlags = 0;
480    mTimeSourceDeltaUs = 0;
481    mVideoTimeUs = 0;
482
483    mSeeking = false;
484    mSeekNotificationSent = false;
485    mSeekTimeUs = 0;
486
487    mUri.setTo("");
488    mUriHeaders.clear();
489
490    mFileSource.clear();
491
492    mBitrate = -1;
493}
494
495void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
496    if (mListener != NULL) {
497        sp<MediaPlayerBase> listener = mListener.promote();
498
499        if (listener != NULL) {
500            listener->sendEvent(msg, ext1, ext2);
501        }
502    }
503}
504
505bool AwesomePlayer::getBitrate(int64_t *bitrate) {
506    off64_t size;
507    if (mDurationUs >= 0 && mCachedSource != NULL
508            && mCachedSource->getSize(&size) == OK) {
509        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
510        return true;
511    }
512
513    if (mBitrate >= 0) {
514        *bitrate = mBitrate;
515        return true;
516    }
517
518    *bitrate = 0;
519
520    return false;
521}
522
523// Returns true iff cached duration is available/applicable.
524bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
525    int64_t bitrate;
526
527    if (mRTSPController != NULL) {
528        *durationUs = mRTSPController->getQueueDurationUs(eos);
529        return true;
530    } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
531        status_t finalStatus;
532        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
533        *durationUs = cachedDataRemaining * 8000000ll / bitrate;
534        *eos = (finalStatus != OK);
535        return true;
536    }
537
538    return false;
539}
540
541void AwesomePlayer::ensureCacheIsFetching_l() {
542    if (mCachedSource != NULL) {
543        mCachedSource->resumeFetchingIfNecessary();
544    }
545}
546
547void AwesomePlayer::onVideoLagUpdate() {
548    Mutex::Autolock autoLock(mLock);
549    if (!mVideoLagEventPending) {
550        return;
551    }
552    mVideoLagEventPending = false;
553
554    int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
555    int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
556
557    if (videoLateByUs > 300000ll) {
558        LOGV("video late by %lld ms.", videoLateByUs / 1000ll);
559
560        notifyListener_l(
561                MEDIA_INFO,
562                MEDIA_INFO_VIDEO_TRACK_LAGGING,
563                videoLateByUs / 1000ll);
564    }
565
566    postVideoLagEvent_l();
567}
568
569void AwesomePlayer::onBufferingUpdate() {
570    Mutex::Autolock autoLock(mLock);
571    if (!mBufferingEventPending) {
572        return;
573    }
574    mBufferingEventPending = false;
575
576    if (mCachedSource != NULL) {
577        status_t finalStatus;
578        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
579        bool eos = (finalStatus != OK);
580
581        if (eos) {
582            if (finalStatus == ERROR_END_OF_STREAM) {
583                notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
584            }
585            if (mFlags & PREPARING) {
586                LOGV("cache has reached EOS, prepare is done.");
587                finishAsyncPrepare_l();
588            }
589        } else {
590            int64_t bitrate;
591            if (getBitrate(&bitrate)) {
592                size_t cachedSize = mCachedSource->cachedSize();
593                int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
594
595                int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
596                if (percentage > 100) {
597                    percentage = 100;
598                }
599
600                notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
601            } else {
602                // We don't know the bitrate of the stream, use absolute size
603                // limits to maintain the cache.
604
605                if ((mFlags & PLAYING) && !eos
606                        && (cachedDataRemaining < kLowWaterMarkBytes)) {
607                    LOGI("cache is running low (< %d) , pausing.",
608                         kLowWaterMarkBytes);
609                    mFlags |= CACHE_UNDERRUN;
610                    pause_l();
611                    ensureCacheIsFetching_l();
612                    notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
613                } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
614                    if (mFlags & CACHE_UNDERRUN) {
615                        LOGI("cache has filled up (> %d), resuming.",
616                             kHighWaterMarkBytes);
617                        mFlags &= ~CACHE_UNDERRUN;
618                        play_l();
619                        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
620                    } else if (mFlags & PREPARING) {
621                        LOGV("cache has filled up (> %d), prepare is done",
622                             kHighWaterMarkBytes);
623                        finishAsyncPrepare_l();
624                    }
625                }
626            }
627        }
628    }
629
630    int64_t cachedDurationUs;
631    bool eos;
632    if (getCachedDuration_l(&cachedDurationUs, &eos)) {
633        LOGV("cachedDurationUs = %.2f secs, eos=%d",
634             cachedDurationUs / 1E6, eos);
635
636        int64_t highWaterMarkUs =
637            (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
638
639        if ((mFlags & PLAYING) && !eos
640                && (cachedDurationUs < kLowWaterMarkUs)) {
641            LOGI("cache is running low (%.2f secs) , pausing.",
642                 cachedDurationUs / 1E6);
643            mFlags |= CACHE_UNDERRUN;
644            pause_l();
645            ensureCacheIsFetching_l();
646            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
647        } else if (eos || cachedDurationUs > highWaterMarkUs) {
648            if (mFlags & CACHE_UNDERRUN) {
649                LOGI("cache has filled up (%.2f secs), resuming.",
650                     cachedDurationUs / 1E6);
651                mFlags &= ~CACHE_UNDERRUN;
652                play_l();
653                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
654            } else if (mFlags & PREPARING) {
655                LOGV("cache has filled up (%.2f secs), prepare is done",
656                     cachedDurationUs / 1E6);
657                finishAsyncPrepare_l();
658            }
659        }
660    }
661
662    postBufferingEvent_l();
663}
664
665void AwesomePlayer::onStreamDone() {
666    // Posted whenever any stream finishes playing.
667
668    Mutex::Autolock autoLock(mLock);
669    if (!mStreamDoneEventPending) {
670        return;
671    }
672    mStreamDoneEventPending = false;
673
674    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
675        LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
676
677        notifyListener_l(
678                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
679
680        pause_l(true /* at eos */);
681
682        mFlags |= AT_EOS;
683        return;
684    }
685
686    const bool allDone =
687        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
688            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
689
690    if (!allDone) {
691        return;
692    }
693
694    if (mFlags & (LOOPING | AUTO_LOOPING)) {
695        seekTo_l(0);
696
697        if (mVideoSource != NULL) {
698            postVideoEvent_l();
699        }
700    } else {
701        LOGV("MEDIA_PLAYBACK_COMPLETE");
702        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
703
704        pause_l(true /* at eos */);
705
706        mFlags |= AT_EOS;
707    }
708}
709
710status_t AwesomePlayer::play() {
711    Mutex::Autolock autoLock(mLock);
712
713    mFlags &= ~CACHE_UNDERRUN;
714
715    return play_l();
716}
717
718status_t AwesomePlayer::play_l() {
719    mFlags &= ~SEEK_PREVIEW;
720
721    if (mFlags & PLAYING) {
722        return OK;
723    }
724
725    if (!(mFlags & PREPARED)) {
726        status_t err = prepare_l();
727
728        if (err != OK) {
729            return err;
730        }
731    }
732
733    mFlags |= PLAYING;
734    mFlags |= FIRST_FRAME;
735
736    bool deferredAudioSeek = false;
737
738    if (mDecryptHandle != NULL) {
739        int64_t position;
740        getPosition(&position);
741        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
742                Playback::START, position / 1000);
743    }
744
745    if (mAudioSource != NULL) {
746        if (mAudioPlayer == NULL) {
747            if (mAudioSink != NULL) {
748                mAudioPlayer = new AudioPlayer(mAudioSink, this);
749                mAudioPlayer->setSource(mAudioSource);
750
751                mTimeSource = mAudioPlayer;
752
753                deferredAudioSeek = true;
754
755                mWatchForAudioSeekComplete = false;
756                mWatchForAudioEOS = true;
757            }
758        }
759
760        CHECK(!(mFlags & AUDIO_RUNNING));
761
762        if (mVideoSource == NULL) {
763            status_t err = startAudioPlayer_l();
764
765            if (err != OK) {
766                delete mAudioPlayer;
767                mAudioPlayer = NULL;
768
769                mFlags &= ~(PLAYING | FIRST_FRAME);
770
771                if (mDecryptHandle != NULL) {
772                    mDrmManagerClient->setPlaybackStatus(
773                            mDecryptHandle, Playback::STOP, 0);
774                }
775
776                return err;
777            }
778        }
779    }
780
781    if (mTimeSource == NULL && mAudioPlayer == NULL) {
782        mTimeSource = &mSystemTimeSource;
783    }
784
785    if (mVideoSource != NULL) {
786        // Kick off video playback
787        postVideoEvent_l();
788
789        if (mAudioSource != NULL && mVideoSource != NULL) {
790            postVideoLagEvent_l();
791        }
792    }
793
794    if (deferredAudioSeek) {
795        // If there was a seek request while we were paused
796        // and we're just starting up again, honor the request now.
797        seekAudioIfNecessary_l();
798    }
799
800    if (mFlags & AT_EOS) {
801        // Legacy behaviour, if a stream finishes playing and then
802        // is started again, we play from the start...
803        seekTo_l(0);
804    }
805
806    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
807        | IMediaPlayerService::kBatteryDataTrackDecoder;
808    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
809        params |= IMediaPlayerService::kBatteryDataTrackAudio;
810    }
811    if (mVideoSource != NULL) {
812        params |= IMediaPlayerService::kBatteryDataTrackVideo;
813    }
814    addBatteryData(params);
815
816    return OK;
817}
818
819status_t AwesomePlayer::startAudioPlayer_l() {
820    CHECK(!(mFlags & AUDIO_RUNNING));
821
822    if (mAudioSource == NULL || mAudioPlayer == NULL) {
823        return OK;
824    }
825
826    if (!(mFlags & AUDIOPLAYER_STARTED)) {
827        mFlags |= AUDIOPLAYER_STARTED;
828
829        // We've already started the MediaSource in order to enable
830        // the prefetcher to read its data.
831        status_t err = mAudioPlayer->start(
832                true /* sourceAlreadyStarted */);
833
834        if (err != OK) {
835            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
836            return err;
837        }
838    } else {
839        mAudioPlayer->resume();
840    }
841
842    mFlags |= AUDIO_RUNNING;
843
844    mWatchForAudioEOS = true;
845
846    return OK;
847}
848
849void AwesomePlayer::notifyVideoSize_l() {
850    sp<MetaData> meta = mVideoSource->getFormat();
851
852    int32_t cropLeft, cropTop, cropRight, cropBottom;
853    if (!meta->findRect(
854                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
855        int32_t width, height;
856        CHECK(meta->findInt32(kKeyWidth, &width));
857        CHECK(meta->findInt32(kKeyHeight, &height));
858
859        cropLeft = cropTop = 0;
860        cropRight = width - 1;
861        cropBottom = height - 1;
862
863        LOGV("got dimensions only %d x %d", width, height);
864    } else {
865        LOGV("got crop rect %d, %d, %d, %d",
866             cropLeft, cropTop, cropRight, cropBottom);
867    }
868
869    int32_t usableWidth = cropRight - cropLeft + 1;
870    int32_t usableHeight = cropBottom - cropTop + 1;
871    if (mDisplayWidth != 0) {
872        usableWidth = mDisplayWidth;
873    }
874    if (mDisplayHeight != 0) {
875        usableHeight = mDisplayHeight;
876    }
877
878    int32_t rotationDegrees;
879    if (!mVideoTrack->getFormat()->findInt32(
880                kKeyRotation, &rotationDegrees)) {
881        rotationDegrees = 0;
882    }
883
884    if (rotationDegrees == 90 || rotationDegrees == 270) {
885        notifyListener_l(
886                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
887    } else {
888        notifyListener_l(
889                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
890    }
891}
892
893void AwesomePlayer::initRenderer_l() {
894    if (mNativeWindow == NULL) {
895        return;
896    }
897
898    sp<MetaData> meta = mVideoSource->getFormat();
899
900    int32_t format;
901    const char *component;
902    int32_t decodedWidth, decodedHeight;
903    CHECK(meta->findInt32(kKeyColorFormat, &format));
904    CHECK(meta->findCString(kKeyDecoderComponent, &component));
905    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
906    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
907
908    int32_t rotationDegrees;
909    if (!mVideoTrack->getFormat()->findInt32(
910                kKeyRotation, &rotationDegrees)) {
911        rotationDegrees = 0;
912    }
913
914    mVideoRenderer.clear();
915
916    // Must ensure that mVideoRenderer's destructor is actually executed
917    // before creating a new one.
918    IPCThreadState::self()->flushCommands();
919
920    if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
921        // Hardware decoders avoid the CPU color conversion by decoding
922        // directly to ANativeBuffers, so we must use a renderer that
923        // just pushes those buffers to the ANativeWindow.
924        mVideoRenderer =
925            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
926    } else {
927        // Other decoders are instantiated locally and as a consequence
928        // allocate their buffers in local address space.  This renderer
929        // then performs a color conversion and copy to get the data
930        // into the ANativeBuffer.
931        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
932    }
933}
934
935status_t AwesomePlayer::pause() {
936    Mutex::Autolock autoLock(mLock);
937
938    mFlags &= ~CACHE_UNDERRUN;
939
940    return pause_l();
941}
942
943status_t AwesomePlayer::pause_l(bool at_eos) {
944    if (!(mFlags & PLAYING)) {
945        return OK;
946    }
947
948    cancelPlayerEvents(true /* keepBufferingGoing */);
949
950    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
951        if (at_eos) {
952            // If we played the audio stream to completion we
953            // want to make sure that all samples remaining in the audio
954            // track's queue are played out.
955            mAudioPlayer->pause(true /* playPendingSamples */);
956        } else {
957            mAudioPlayer->pause();
958        }
959
960        mFlags &= ~AUDIO_RUNNING;
961    }
962
963    mFlags &= ~PLAYING;
964
965    if (mDecryptHandle != NULL) {
966        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
967                Playback::PAUSE, 0);
968    }
969
970    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
971    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
972        params |= IMediaPlayerService::kBatteryDataTrackAudio;
973    }
974    if (mVideoSource != NULL) {
975        params |= IMediaPlayerService::kBatteryDataTrackVideo;
976    }
977
978    addBatteryData(params);
979
980    return OK;
981}
982
983bool AwesomePlayer::isPlaying() const {
984    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
985}
986
987void AwesomePlayer::setSurface(const sp<Surface> &surface) {
988    Mutex::Autolock autoLock(mLock);
989
990    mSurface = surface;
991    mNativeWindow = surface;
992}
993
994void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
995    Mutex::Autolock autoLock(mLock);
996
997    mSurface.clear();
998    if (surfaceTexture != NULL) {
999        mNativeWindow = new SurfaceTextureClient(surfaceTexture);
1000    }
1001
1002}
1003
1004void AwesomePlayer::setAudioSink(
1005        const sp<MediaPlayerBase::AudioSink> &audioSink) {
1006    Mutex::Autolock autoLock(mLock);
1007
1008    mAudioSink = audioSink;
1009}
1010
1011status_t AwesomePlayer::setLooping(bool shouldLoop) {
1012    Mutex::Autolock autoLock(mLock);
1013
1014    mFlags = mFlags & ~LOOPING;
1015
1016    if (shouldLoop) {
1017        mFlags |= LOOPING;
1018    }
1019
1020    return OK;
1021}
1022
1023status_t AwesomePlayer::getDuration(int64_t *durationUs) {
1024    Mutex::Autolock autoLock(mMiscStateLock);
1025
1026    if (mDurationUs < 0) {
1027        return UNKNOWN_ERROR;
1028    }
1029
1030    *durationUs = mDurationUs;
1031
1032    return OK;
1033}
1034
1035status_t AwesomePlayer::getPosition(int64_t *positionUs) {
1036    if (mRTSPController != NULL) {
1037        *positionUs = mRTSPController->getNormalPlayTimeUs();
1038    }
1039    else if (mSeeking) {
1040        *positionUs = mSeekTimeUs;
1041    } else if (mVideoSource != NULL) {
1042        Mutex::Autolock autoLock(mMiscStateLock);
1043        *positionUs = mVideoTimeUs;
1044    } else if (mAudioPlayer != NULL) {
1045        *positionUs = mAudioPlayer->getMediaTimeUs();
1046    } else {
1047        *positionUs = 0;
1048    }
1049
1050    return OK;
1051}
1052
1053status_t AwesomePlayer::seekTo(int64_t timeUs) {
1054    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
1055        Mutex::Autolock autoLock(mLock);
1056        return seekTo_l(timeUs);
1057    }
1058
1059    return OK;
1060}
1061
1062// static
1063void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1064    static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1065}
1066
1067void AwesomePlayer::onRTSPSeekDone() {
1068    notifyListener_l(MEDIA_SEEK_COMPLETE);
1069    mSeekNotificationSent = true;
1070}
1071
1072status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
1073    if (mRTSPController != NULL) {
1074        mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
1075        return OK;
1076    }
1077
1078    if (mFlags & CACHE_UNDERRUN) {
1079        mFlags &= ~CACHE_UNDERRUN;
1080        play_l();
1081    }
1082
1083    mSeeking = true;
1084    mSeekNotificationSent = false;
1085    mSeekTimeUs = timeUs;
1086    mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1087
1088    seekAudioIfNecessary_l();
1089
1090    if (!(mFlags & PLAYING)) {
1091        LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1092             " immediately.");
1093
1094        notifyListener_l(MEDIA_SEEK_COMPLETE);
1095        mSeekNotificationSent = true;
1096
1097        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1098            mFlags |= SEEK_PREVIEW;
1099            postVideoEvent_l();
1100        }
1101    }
1102
1103    return OK;
1104}
1105
1106void AwesomePlayer::seekAudioIfNecessary_l() {
1107    if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
1108        mAudioPlayer->seekTo(mSeekTimeUs);
1109
1110        mWatchForAudioSeekComplete = true;
1111        mWatchForAudioEOS = true;
1112        mSeekNotificationSent = false;
1113
1114        if (mDecryptHandle != NULL) {
1115            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1116                    Playback::PAUSE, 0);
1117            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1118                    Playback::START, mSeekTimeUs / 1000);
1119        }
1120    }
1121}
1122
1123void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1124    CHECK(source != NULL);
1125
1126    mAudioTrack = source;
1127}
1128
1129status_t AwesomePlayer::initAudioDecoder() {
1130    sp<MetaData> meta = mAudioTrack->getFormat();
1131
1132    const char *mime;
1133    CHECK(meta->findCString(kKeyMIMEType, &mime));
1134
1135    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1136        mAudioSource = mAudioTrack;
1137    } else {
1138        mAudioSource = OMXCodec::Create(
1139                mClient.interface(), mAudioTrack->getFormat(),
1140                false, // createEncoder
1141                mAudioTrack);
1142    }
1143
1144    if (mAudioSource != NULL) {
1145        int64_t durationUs;
1146        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1147            Mutex::Autolock autoLock(mMiscStateLock);
1148            if (mDurationUs < 0 || durationUs > mDurationUs) {
1149                mDurationUs = durationUs;
1150            }
1151        }
1152
1153        status_t err = mAudioSource->start();
1154
1155        if (err != OK) {
1156            mAudioSource.clear();
1157            return err;
1158        }
1159    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1160        // For legacy reasons we're simply going to ignore the absence
1161        // of an audio decoder for QCELP instead of aborting playback
1162        // altogether.
1163        return OK;
1164    }
1165
1166    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1167}
1168
1169void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1170    CHECK(source != NULL);
1171
1172    mVideoTrack = source;
1173}
1174
1175status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1176    mVideoSource = OMXCodec::Create(
1177            mClient.interface(), mVideoTrack->getFormat(),
1178            false, // createEncoder
1179            mVideoTrack,
1180            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
1181
1182    if (mVideoSource != NULL) {
1183        int64_t durationUs;
1184        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1185            Mutex::Autolock autoLock(mMiscStateLock);
1186            if (mDurationUs < 0 || durationUs > mDurationUs) {
1187                mDurationUs = durationUs;
1188            }
1189        }
1190
1191        status_t err = mVideoSource->start();
1192
1193        if (err != OK) {
1194            mVideoSource.clear();
1195            return err;
1196        }
1197    }
1198
1199    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1200}
1201
1202void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1203    if (!mSeeking || (mFlags & SEEK_PREVIEW)) {
1204        return;
1205    }
1206
1207    if (mAudioPlayer != NULL) {
1208        LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1209
1210        // If we don't have a video time, seek audio to the originally
1211        // requested seek time instead.
1212
1213        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1214        mWatchForAudioSeekComplete = true;
1215    } else if (!mSeekNotificationSent) {
1216        // If we're playing video only, report seek complete now,
1217        // otherwise audio player will notify us later.
1218        notifyListener_l(MEDIA_SEEK_COMPLETE);
1219    }
1220
1221    mFlags |= FIRST_FRAME;
1222    mSeeking = false;
1223    mSeekNotificationSent = false;
1224
1225    if (mDecryptHandle != NULL) {
1226        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1227                Playback::PAUSE, 0);
1228        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1229                Playback::START, videoTimeUs / 1000);
1230    }
1231}
1232
1233void AwesomePlayer::onVideoEvent() {
1234    Mutex::Autolock autoLock(mLock);
1235    if (!mVideoEventPending) {
1236        // The event has been cancelled in reset_l() but had already
1237        // been scheduled for execution at that time.
1238        return;
1239    }
1240    mVideoEventPending = false;
1241
1242    if (mSeeking) {
1243        if (mVideoBuffer) {
1244            mVideoBuffer->release();
1245            mVideoBuffer = NULL;
1246        }
1247
1248        if (mCachedSource != NULL && mAudioSource != NULL
1249                && !(mFlags & SEEK_PREVIEW)) {
1250            // We're going to seek the video source first, followed by
1251            // the audio source.
1252            // In order to avoid jumps in the DataSource offset caused by
1253            // the audio codec prefetching data from the old locations
1254            // while the video codec is already reading data from the new
1255            // locations, we'll "pause" the audio source, causing it to
1256            // stop reading input data until a subsequent seek.
1257
1258            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1259                mAudioPlayer->pause();
1260
1261                mFlags &= ~AUDIO_RUNNING;
1262            }
1263            mAudioSource->pause();
1264        }
1265    }
1266
1267    if (!mVideoBuffer) {
1268        MediaSource::ReadOptions options;
1269        if (mSeeking) {
1270            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1271
1272            options.setSeekTo(
1273                    mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1274        }
1275        for (;;) {
1276            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1277            options.clearSeekTo();
1278
1279            if (err != OK) {
1280                CHECK(mVideoBuffer == NULL);
1281
1282                if (err == INFO_FORMAT_CHANGED) {
1283                    LOGV("VideoSource signalled format change.");
1284
1285                    notifyVideoSize_l();
1286
1287                    if (mVideoRenderer != NULL) {
1288                        mVideoRendererIsPreview = false;
1289                        initRenderer_l();
1290                    }
1291                    continue;
1292                }
1293
1294                // So video playback is complete, but we may still have
1295                // a seek request pending that needs to be applied
1296                // to the audio track.
1297                if (mSeeking) {
1298                    LOGV("video stream ended while seeking!");
1299                }
1300                finishSeekIfNecessary(-1);
1301
1302                mFlags |= VIDEO_AT_EOS;
1303                postStreamDoneEvent_l(err);
1304                return;
1305            }
1306
1307            if (mVideoBuffer->range_length() == 0) {
1308                // Some decoders, notably the PV AVC software decoder
1309                // return spurious empty buffers that we just want to ignore.
1310
1311                mVideoBuffer->release();
1312                mVideoBuffer = NULL;
1313                continue;
1314            }
1315
1316            break;
1317        }
1318    }
1319
1320    int64_t timeUs;
1321    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1322
1323    {
1324        Mutex::Autolock autoLock(mMiscStateLock);
1325        mVideoTimeUs = timeUs;
1326    }
1327
1328    bool wasSeeking = mSeeking;
1329    finishSeekIfNecessary(timeUs);
1330
1331    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1332        status_t err = startAudioPlayer_l();
1333        if (err != OK) {
1334            LOGE("Startung the audio player failed w/ err %d", err);
1335            return;
1336        }
1337    }
1338
1339    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1340
1341    if (mFlags & FIRST_FRAME) {
1342        mFlags &= ~FIRST_FRAME;
1343        mSinceLastDropped = 0;
1344        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1345    }
1346
1347    int64_t realTimeUs, mediaTimeUs;
1348    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1349        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1350        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1351    }
1352
1353    if (!wasSeeking) {
1354        // Let's display the first frame after seeking right away.
1355
1356        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1357
1358        int64_t latenessUs = nowUs - timeUs;
1359
1360        if (latenessUs > 40000) {
1361            // We're more than 40ms late.
1362            LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
1363            if ( mSinceLastDropped > FRAME_DROP_FREQ)
1364            {
1365                LOGV("we're late by %lld us (%.2f secs) dropping one after %d frames", latenessUs, latenessUs / 1E6, mSinceLastDropped);
1366                mSinceLastDropped = 0;
1367                mVideoBuffer->release();
1368                mVideoBuffer = NULL;
1369
1370                postVideoEvent_l();
1371                return;
1372            }
1373        }
1374
1375        if (latenessUs < -10000) {
1376            // We're more than 10ms early.
1377
1378            postVideoEvent_l(10000);
1379            return;
1380        }
1381    }
1382
1383    if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1384        mVideoRendererIsPreview = false;
1385
1386        initRenderer_l();
1387    }
1388
1389    if (mVideoRenderer != NULL) {
1390        mSinceLastDropped++;
1391        mVideoRenderer->render(mVideoBuffer);
1392    }
1393
1394    mVideoBuffer->release();
1395    mVideoBuffer = NULL;
1396
1397    if (wasSeeking && (mFlags & SEEK_PREVIEW)) {
1398        mFlags &= ~SEEK_PREVIEW;
1399        return;
1400    }
1401
1402    postVideoEvent_l();
1403}
1404
1405void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1406    if (mVideoEventPending) {
1407        return;
1408    }
1409
1410    mVideoEventPending = true;
1411    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1412}
1413
1414void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1415    if (mStreamDoneEventPending) {
1416        return;
1417    }
1418    mStreamDoneEventPending = true;
1419
1420    mStreamDoneStatus = status;
1421    mQueue.postEvent(mStreamDoneEvent);
1422}
1423
1424void AwesomePlayer::postBufferingEvent_l() {
1425    if (mBufferingEventPending) {
1426        return;
1427    }
1428    mBufferingEventPending = true;
1429    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1430}
1431
1432void AwesomePlayer::postVideoLagEvent_l() {
1433    if (mVideoLagEventPending) {
1434        return;
1435    }
1436    mVideoLagEventPending = true;
1437    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1438}
1439
1440void AwesomePlayer::postCheckAudioStatusEvent_l() {
1441    if (mAudioStatusEventPending) {
1442        return;
1443    }
1444    mAudioStatusEventPending = true;
1445    mQueue.postEvent(mCheckAudioStatusEvent);
1446}
1447
1448void AwesomePlayer::onCheckAudioStatus() {
1449    Mutex::Autolock autoLock(mLock);
1450    if (!mAudioStatusEventPending) {
1451        // Event was dispatched and while we were blocking on the mutex,
1452        // has already been cancelled.
1453        return;
1454    }
1455
1456    mAudioStatusEventPending = false;
1457
1458    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1459        mWatchForAudioSeekComplete = false;
1460
1461        if (!mSeekNotificationSent) {
1462            notifyListener_l(MEDIA_SEEK_COMPLETE);
1463            mSeekNotificationSent = true;
1464        }
1465
1466        mSeeking = false;
1467    }
1468
1469    status_t finalStatus;
1470    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1471        mWatchForAudioEOS = false;
1472        mFlags |= AUDIO_AT_EOS;
1473        mFlags |= FIRST_FRAME;
1474        postStreamDoneEvent_l(finalStatus);
1475    }
1476}
1477
1478status_t AwesomePlayer::prepare() {
1479    Mutex::Autolock autoLock(mLock);
1480    return prepare_l();
1481}
1482
1483status_t AwesomePlayer::prepare_l() {
1484    if (mFlags & PREPARED) {
1485        return OK;
1486    }
1487
1488    if (mFlags & PREPARING) {
1489        return UNKNOWN_ERROR;
1490    }
1491
1492    mIsAsyncPrepare = false;
1493    status_t err = prepareAsync_l();
1494
1495    if (err != OK) {
1496        return err;
1497    }
1498
1499    while (mFlags & PREPARING) {
1500        mPreparedCondition.wait(mLock);
1501    }
1502
1503    return mPrepareResult;
1504}
1505
1506status_t AwesomePlayer::prepareAsync() {
1507    Mutex::Autolock autoLock(mLock);
1508
1509    if (mFlags & PREPARING) {
1510        return UNKNOWN_ERROR;  // async prepare already pending
1511    }
1512
1513    mIsAsyncPrepare = true;
1514    return prepareAsync_l();
1515}
1516
1517status_t AwesomePlayer::prepareAsync_l() {
1518    if (mFlags & PREPARING) {
1519        return UNKNOWN_ERROR;  // async prepare already pending
1520    }
1521
1522    if (!mQueueStarted) {
1523        mQueue.start();
1524        mQueueStarted = true;
1525    }
1526
1527    mFlags |= PREPARING;
1528    mAsyncPrepareEvent = new AwesomeEvent(
1529            this, &AwesomePlayer::onPrepareAsyncEvent);
1530
1531    mQueue.postEvent(mAsyncPrepareEvent);
1532
1533    return OK;
1534}
1535
1536status_t AwesomePlayer::finishSetDataSource_l() {
1537    sp<DataSource> dataSource;
1538
1539    if (!strncasecmp("http://", mUri.string(), 7)
1540            || !strncasecmp("https://", mUri.string(), 8)) {
1541        mConnectingDataSource = new NuHTTPDataSource;
1542
1543        mLock.unlock();
1544        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
1545        mLock.lock();
1546
1547        if (err != OK) {
1548            mConnectingDataSource.clear();
1549
1550            LOGI("mConnectingDataSource->connect() returned %d", err);
1551            return err;
1552        }
1553
1554#if 0
1555        mCachedSource = new NuCachedSource2(
1556                new ThrottledSource(
1557                    mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1558#else
1559        mCachedSource = new NuCachedSource2(mConnectingDataSource);
1560#endif
1561        mConnectingDataSource.clear();
1562
1563        dataSource = mCachedSource;
1564
1565        // We're going to prefill the cache before trying to instantiate
1566        // the extractor below, as the latter is an operation that otherwise
1567        // could block on the datasource for a significant amount of time.
1568        // During that time we'd be unable to abort the preparation phase
1569        // without this prefill.
1570
1571        mLock.unlock();
1572
1573        for (;;) {
1574            status_t finalStatus;
1575            size_t cachedDataRemaining =
1576                mCachedSource->approxDataRemaining(&finalStatus);
1577
1578            if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
1579                    || (mFlags & PREPARE_CANCELLED)) {
1580                break;
1581            }
1582
1583            usleep(200000);
1584        }
1585
1586        mLock.lock();
1587
1588        if (mFlags & PREPARE_CANCELLED) {
1589            LOGI("Prepare cancelled while waiting for initial cache fill.");
1590            return UNKNOWN_ERROR;
1591        }
1592    } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1593        if (mLooper == NULL) {
1594            mLooper = new ALooper;
1595            mLooper->setName("rtsp");
1596            mLooper->start();
1597        }
1598        mRTSPController = new ARTSPController(mLooper);
1599        mConnectingRTSPController = mRTSPController;
1600
1601        mLock.unlock();
1602        status_t err = mRTSPController->connect(mUri.string());
1603        mLock.lock();
1604
1605        mConnectingRTSPController.clear();
1606
1607        LOGI("ARTSPController::connect returned %d", err);
1608
1609        if (err != OK) {
1610            mRTSPController.clear();
1611            return err;
1612        }
1613
1614        sp<MediaExtractor> extractor = mRTSPController.get();
1615        return setDataSource_l(extractor);
1616    } else {
1617        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1618    }
1619
1620    if (dataSource == NULL) {
1621        return UNKNOWN_ERROR;
1622    }
1623
1624    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1625
1626    if (extractor == NULL) {
1627        return UNKNOWN_ERROR;
1628    }
1629
1630    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
1631    if (mDecryptHandle != NULL) {
1632        CHECK(mDrmManagerClient);
1633        if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
1634            if (DecryptApiType::WV_BASED == mDecryptHandle->decryptApiType) {
1635                LOGD("Setting mCachedSource to NULL for WVM\n");
1636                mCachedSource.clear();
1637            }
1638        } else {
1639            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
1640        }
1641    }
1642
1643    return setDataSource_l(extractor);
1644}
1645
1646void AwesomePlayer::abortPrepare(status_t err) {
1647    CHECK(err != OK);
1648
1649    if (mIsAsyncPrepare) {
1650        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1651    }
1652
1653    mPrepareResult = err;
1654    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
1655    mAsyncPrepareEvent = NULL;
1656    mPreparedCondition.broadcast();
1657}
1658
1659// static
1660bool AwesomePlayer::ContinuePreparation(void *cookie) {
1661    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1662
1663    return (me->mFlags & PREPARE_CANCELLED) == 0;
1664}
1665
1666void AwesomePlayer::onPrepareAsyncEvent() {
1667    Mutex::Autolock autoLock(mLock);
1668
1669    if (mFlags & PREPARE_CANCELLED) {
1670        LOGI("prepare was cancelled before doing anything");
1671        abortPrepare(UNKNOWN_ERROR);
1672        return;
1673    }
1674
1675    if (mUri.size() > 0) {
1676        status_t err = finishSetDataSource_l();
1677
1678        if (err != OK) {
1679            abortPrepare(err);
1680            return;
1681        }
1682    }
1683
1684    if (mVideoTrack != NULL && mVideoSource == NULL) {
1685        status_t err = initVideoDecoder();
1686
1687        if (err != OK) {
1688            abortPrepare(err);
1689            return;
1690        }
1691    }
1692
1693    if (mAudioTrack != NULL && mAudioSource == NULL) {
1694        status_t err = initAudioDecoder();
1695
1696        if (err != OK) {
1697            abortPrepare(err);
1698            return;
1699        }
1700    }
1701
1702    mFlags |= PREPARING_CONNECTED;
1703
1704    if (mCachedSource != NULL || mRTSPController != NULL) {
1705        postBufferingEvent_l();
1706    } else {
1707        finishAsyncPrepare_l();
1708    }
1709}
1710
1711void AwesomePlayer::finishAsyncPrepare_l() {
1712    if (mIsAsyncPrepare) {
1713        if (mVideoSource == NULL) {
1714            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1715        } else {
1716            notifyVideoSize_l();
1717        }
1718
1719        notifyListener_l(MEDIA_PREPARED);
1720    }
1721
1722    mPrepareResult = OK;
1723    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
1724    mFlags |= PREPARED;
1725    mAsyncPrepareEvent = NULL;
1726    mPreparedCondition.broadcast();
1727}
1728
1729uint32_t AwesomePlayer::flags() const {
1730    return mExtractorFlags;
1731}
1732
1733void AwesomePlayer::postAudioEOS() {
1734    postCheckAudioStatusEvent_l();
1735}
1736
1737void AwesomePlayer::postAudioSeekComplete() {
1738    postCheckAudioStatusEvent_l();
1739}
1740
1741}  // namespace android
1742