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