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