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