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