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