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