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