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