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