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