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