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