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