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