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