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