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