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