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