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