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