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