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