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