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