AwesomePlayer.cpp revision a6490c65f93e1cbe969fba499978e8d64214108a
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());
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            ALOGI("cache is running low (%.2f secs) , pausing.",
757                 cachedDurationUs / 1E6);
758            modifyFlags(CACHE_UNDERRUN, SET);
759            pause_l();
760            ensureCacheIsFetching_l();
761            sendCacheStats();
762            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
763        } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
764            if (mFlags & CACHE_UNDERRUN) {
765                ALOGI("cache has filled up (%.2f secs), resuming.",
766                     cachedDurationUs / 1E6);
767                modifyFlags(CACHE_UNDERRUN, CLEAR);
768                play_l();
769                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
770            } else if (mFlags & PREPARING) {
771                ALOGV("cache has filled up (%.2f secs), prepare is done",
772                     cachedDurationUs / 1E6);
773                finishAsyncPrepare_l();
774            }
775        }
776    }
777
778    postBufferingEvent_l();
779}
780
781void AwesomePlayer::sendCacheStats() {
782    sp<MediaPlayerBase> listener = mListener.promote();
783    if (listener != NULL && mCachedSource != NULL) {
784        int32_t kbps = 0;
785        status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
786        if (err == OK) {
787            listener->sendEvent(
788                MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
789        }
790    }
791}
792
793void AwesomePlayer::onStreamDone() {
794    // Posted whenever any stream finishes playing.
795    ATRACE_CALL();
796
797    Mutex::Autolock autoLock(mLock);
798    if (!mStreamDoneEventPending) {
799        return;
800    }
801    mStreamDoneEventPending = false;
802
803    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
804        ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
805
806        notifyListener_l(
807                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
808
809        pause_l(true /* at eos */);
810
811        modifyFlags(AT_EOS, SET);
812        return;
813    }
814
815    const bool allDone =
816        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
817            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
818
819    if (!allDone) {
820        return;
821    }
822
823    if ((mFlags & LOOPING)
824            || ((mFlags & AUTO_LOOPING)
825                && (mAudioSink == NULL || mAudioSink->realtime()))) {
826        // Don't AUTO_LOOP if we're being recorded, since that cannot be
827        // turned off and recording would go on indefinitely.
828
829        seekTo_l(0);
830
831        if (mVideoSource != NULL) {
832            postVideoEvent_l();
833        }
834    } else {
835        ALOGV("MEDIA_PLAYBACK_COMPLETE");
836        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
837
838        pause_l(true /* at eos */);
839
840        modifyFlags(AT_EOS, SET);
841    }
842}
843
844status_t AwesomePlayer::play() {
845    ATRACE_CALL();
846
847    Mutex::Autolock autoLock(mLock);
848
849    modifyFlags(CACHE_UNDERRUN, CLEAR);
850
851    return play_l();
852}
853
854status_t AwesomePlayer::play_l() {
855    modifyFlags(SEEK_PREVIEW, CLEAR);
856
857    if (mFlags & PLAYING) {
858        return OK;
859    }
860
861    if (!(mFlags & PREPARED)) {
862        status_t err = prepare_l();
863
864        if (err != OK) {
865            return err;
866        }
867    }
868
869    modifyFlags(PLAYING, SET);
870    modifyFlags(FIRST_FRAME, SET);
871
872    if (mDecryptHandle != NULL) {
873        int64_t position;
874        getPosition(&position);
875        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
876                Playback::START, position / 1000);
877    }
878
879    if (mAudioSource != NULL) {
880        if (mAudioPlayer == NULL) {
881            if (mAudioSink != NULL) {
882                bool allowDeepBuffering;
883                int64_t cachedDurationUs;
884                bool eos;
885                if (mVideoSource == NULL
886                        && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||
887                        (getCachedDuration_l(&cachedDurationUs, &eos) &&
888                        cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) {
889                    allowDeepBuffering = true;
890                } else {
891                    allowDeepBuffering = false;
892                }
893
894                mAudioPlayer = new AudioPlayer(mAudioSink, allowDeepBuffering, this);
895                mAudioPlayer->setSource(mAudioSource);
896
897                mTimeSource = mAudioPlayer;
898
899                // If there was a seek request before we ever started,
900                // honor the request now.
901                // Make sure to do this before starting the audio player
902                // to avoid a race condition.
903                seekAudioIfNecessary_l();
904            }
905        }
906
907        CHECK(!(mFlags & AUDIO_RUNNING));
908
909        if (mVideoSource == NULL) {
910            // We don't want to post an error notification at this point,
911            // the error returned from MediaPlayer::start() will suffice.
912
913            status_t err = startAudioPlayer_l(
914                    false /* sendErrorNotification */);
915
916            if (err != OK) {
917                delete mAudioPlayer;
918                mAudioPlayer = NULL;
919
920                modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
921
922                if (mDecryptHandle != NULL) {
923                    mDrmManagerClient->setPlaybackStatus(
924                            mDecryptHandle, Playback::STOP, 0);
925                }
926
927                return err;
928            }
929        }
930    }
931
932    if (mTimeSource == NULL && mAudioPlayer == NULL) {
933        mTimeSource = &mSystemTimeSource;
934    }
935
936    if (mVideoSource != NULL) {
937        // Kick off video playback
938        postVideoEvent_l();
939
940        if (mAudioSource != NULL && mVideoSource != NULL) {
941            postVideoLagEvent_l();
942        }
943    }
944
945    if (mFlags & AT_EOS) {
946        // Legacy behaviour, if a stream finishes playing and then
947        // is started again, we play from the start...
948        seekTo_l(0);
949    }
950
951    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
952        | IMediaPlayerService::kBatteryDataTrackDecoder;
953    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
954        params |= IMediaPlayerService::kBatteryDataTrackAudio;
955    }
956    if (mVideoSource != NULL) {
957        params |= IMediaPlayerService::kBatteryDataTrackVideo;
958    }
959    addBatteryData(params);
960
961    return OK;
962}
963
964status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
965    CHECK(!(mFlags & AUDIO_RUNNING));
966
967    if (mAudioSource == NULL || mAudioPlayer == NULL) {
968        return OK;
969    }
970
971    if (!(mFlags & AUDIOPLAYER_STARTED)) {
972        bool wasSeeking = mAudioPlayer->isSeeking();
973
974        // We've already started the MediaSource in order to enable
975        // the prefetcher to read its data.
976        status_t err = mAudioPlayer->start(
977                true /* sourceAlreadyStarted */);
978
979        if (err != OK) {
980            if (sendErrorNotification) {
981                notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
982            }
983
984            return err;
985        }
986
987        modifyFlags(AUDIOPLAYER_STARTED, SET);
988
989        if (wasSeeking) {
990            CHECK(!mAudioPlayer->isSeeking());
991
992            // We will have finished the seek while starting the audio player.
993            postAudioSeekComplete();
994        }
995    } else {
996        mAudioPlayer->resume();
997    }
998
999    modifyFlags(AUDIO_RUNNING, SET);
1000
1001    mWatchForAudioEOS = true;
1002
1003    return OK;
1004}
1005
1006void AwesomePlayer::notifyVideoSize_l() {
1007    ATRACE_CALL();
1008    sp<MetaData> meta = mVideoSource->getFormat();
1009
1010    int32_t cropLeft, cropTop, cropRight, cropBottom;
1011    if (!meta->findRect(
1012                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1013        int32_t width, height;
1014        CHECK(meta->findInt32(kKeyWidth, &width));
1015        CHECK(meta->findInt32(kKeyHeight, &height));
1016
1017        cropLeft = cropTop = 0;
1018        cropRight = width - 1;
1019        cropBottom = height - 1;
1020
1021        ALOGV("got dimensions only %d x %d", width, height);
1022    } else {
1023        ALOGV("got crop rect %d, %d, %d, %d",
1024             cropLeft, cropTop, cropRight, cropBottom);
1025    }
1026
1027    int32_t displayWidth;
1028    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1029        ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1030        mDisplayWidth = displayWidth;
1031    }
1032    int32_t displayHeight;
1033    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1034        ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1035        mDisplayHeight = displayHeight;
1036    }
1037
1038    int32_t usableWidth = cropRight - cropLeft + 1;
1039    int32_t usableHeight = cropBottom - cropTop + 1;
1040    if (mDisplayWidth != 0) {
1041        usableWidth = mDisplayWidth;
1042    }
1043    if (mDisplayHeight != 0) {
1044        usableHeight = mDisplayHeight;
1045    }
1046
1047    {
1048        Mutex::Autolock autoLock(mStatsLock);
1049        mStats.mVideoWidth = usableWidth;
1050        mStats.mVideoHeight = usableHeight;
1051    }
1052
1053    int32_t rotationDegrees;
1054    if (!mVideoTrack->getFormat()->findInt32(
1055                kKeyRotation, &rotationDegrees)) {
1056        rotationDegrees = 0;
1057    }
1058
1059    if (rotationDegrees == 90 || rotationDegrees == 270) {
1060        notifyListener_l(
1061                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1062    } else {
1063        notifyListener_l(
1064                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1065    }
1066}
1067
1068void AwesomePlayer::initRenderer_l() {
1069    ATRACE_CALL();
1070
1071    if (mNativeWindow == NULL) {
1072        return;
1073    }
1074
1075    sp<MetaData> meta = mVideoSource->getFormat();
1076
1077    int32_t format;
1078    const char *component;
1079    int32_t decodedWidth, decodedHeight;
1080    CHECK(meta->findInt32(kKeyColorFormat, &format));
1081    CHECK(meta->findCString(kKeyDecoderComponent, &component));
1082    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1083    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
1084
1085    int32_t rotationDegrees;
1086    if (!mVideoTrack->getFormat()->findInt32(
1087                kKeyRotation, &rotationDegrees)) {
1088        rotationDegrees = 0;
1089    }
1090
1091    mVideoRenderer.clear();
1092
1093    // Must ensure that mVideoRenderer's destructor is actually executed
1094    // before creating a new one.
1095    IPCThreadState::self()->flushCommands();
1096
1097    // Even if set scaling mode fails, we will continue anyway
1098    setVideoScalingMode_l(mVideoScalingMode);
1099    if (USE_SURFACE_ALLOC
1100            && !strncmp(component, "OMX.", 4)
1101            && strncmp(component, "OMX.google.", 11)
1102            && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) {
1103        // Hardware decoders avoid the CPU color conversion by decoding
1104        // directly to ANativeBuffers, so we must use a renderer that
1105        // just pushes those buffers to the ANativeWindow.
1106        mVideoRenderer =
1107            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
1108    } else {
1109        // Other decoders are instantiated locally and as a consequence
1110        // allocate their buffers in local address space.  This renderer
1111        // then performs a color conversion and copy to get the data
1112        // into the ANativeBuffer.
1113        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
1114    }
1115}
1116
1117status_t AwesomePlayer::pause() {
1118    ATRACE_CALL();
1119
1120    Mutex::Autolock autoLock(mLock);
1121
1122    modifyFlags(CACHE_UNDERRUN, CLEAR);
1123
1124    return pause_l();
1125}
1126
1127status_t AwesomePlayer::pause_l(bool at_eos) {
1128    if (!(mFlags & PLAYING)) {
1129        return OK;
1130    }
1131
1132    cancelPlayerEvents(true /* keepNotifications */);
1133
1134    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1135        if (at_eos) {
1136            // If we played the audio stream to completion we
1137            // want to make sure that all samples remaining in the audio
1138            // track's queue are played out.
1139            mAudioPlayer->pause(true /* playPendingSamples */);
1140        } else {
1141            mAudioPlayer->pause();
1142        }
1143
1144        modifyFlags(AUDIO_RUNNING, CLEAR);
1145    }
1146
1147    if (mFlags & TEXTPLAYER_INITIALIZED) {
1148        mTextDriver->pause();
1149        modifyFlags(TEXT_RUNNING, CLEAR);
1150    }
1151
1152    modifyFlags(PLAYING, CLEAR);
1153
1154    if (mDecryptHandle != NULL) {
1155        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1156                Playback::PAUSE, 0);
1157    }
1158
1159    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1160    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1161        params |= IMediaPlayerService::kBatteryDataTrackAudio;
1162    }
1163    if (mVideoSource != NULL) {
1164        params |= IMediaPlayerService::kBatteryDataTrackVideo;
1165    }
1166
1167    addBatteryData(params);
1168
1169    return OK;
1170}
1171
1172bool AwesomePlayer::isPlaying() const {
1173    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1174}
1175
1176status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1177    Mutex::Autolock autoLock(mLock);
1178
1179    status_t err;
1180    if (surfaceTexture != NULL) {
1181        err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
1182    } else {
1183        err = setNativeWindow_l(NULL);
1184    }
1185
1186    return err;
1187}
1188
1189void AwesomePlayer::shutdownVideoDecoder_l() {
1190    if (mVideoBuffer) {
1191        mVideoBuffer->release();
1192        mVideoBuffer = NULL;
1193    }
1194
1195    mVideoSource->stop();
1196
1197    // The following hack is necessary to ensure that the OMX
1198    // component is completely released by the time we may try
1199    // to instantiate it again.
1200    wp<MediaSource> tmp = mVideoSource;
1201    mVideoSource.clear();
1202    while (tmp.promote() != NULL) {
1203        usleep(1000);
1204    }
1205    IPCThreadState::self()->flushCommands();
1206    ALOGV("video decoder shutdown completed");
1207}
1208
1209status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1210    mNativeWindow = native;
1211
1212    if (mVideoSource == NULL) {
1213        return OK;
1214    }
1215
1216    ALOGV("attempting to reconfigure to use new surface");
1217
1218    bool wasPlaying = (mFlags & PLAYING) != 0;
1219
1220    pause_l();
1221    mVideoRenderer.clear();
1222
1223    shutdownVideoDecoder_l();
1224
1225    status_t err = initVideoDecoder();
1226
1227    if (err != OK) {
1228        ALOGE("failed to reinstantiate video decoder after surface change.");
1229        return err;
1230    }
1231
1232    if (mLastVideoTimeUs >= 0) {
1233        mSeeking = SEEK;
1234        mSeekTimeUs = mLastVideoTimeUs;
1235        modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1236    }
1237
1238    if (wasPlaying) {
1239        play_l();
1240    }
1241
1242    return OK;
1243}
1244
1245void AwesomePlayer::setAudioSink(
1246        const sp<MediaPlayerBase::AudioSink> &audioSink) {
1247    Mutex::Autolock autoLock(mLock);
1248
1249    mAudioSink = audioSink;
1250}
1251
1252status_t AwesomePlayer::setLooping(bool shouldLoop) {
1253    Mutex::Autolock autoLock(mLock);
1254
1255    modifyFlags(LOOPING, CLEAR);
1256
1257    if (shouldLoop) {
1258        modifyFlags(LOOPING, SET);
1259    }
1260
1261    return OK;
1262}
1263
1264status_t AwesomePlayer::getDuration(int64_t *durationUs) {
1265    Mutex::Autolock autoLock(mMiscStateLock);
1266
1267    if (mDurationUs < 0) {
1268        return UNKNOWN_ERROR;
1269    }
1270
1271    *durationUs = mDurationUs;
1272
1273    return OK;
1274}
1275
1276status_t AwesomePlayer::getPosition(int64_t *positionUs) {
1277    if (mSeeking != NO_SEEK) {
1278        *positionUs = mSeekTimeUs;
1279    } else if (mVideoSource != NULL
1280            && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1281        Mutex::Autolock autoLock(mMiscStateLock);
1282        *positionUs = mVideoTimeUs;
1283    } else if (mAudioPlayer != NULL) {
1284        *positionUs = mAudioPlayer->getMediaTimeUs();
1285    } else {
1286        *positionUs = 0;
1287    }
1288
1289    return OK;
1290}
1291
1292status_t AwesomePlayer::seekTo(int64_t timeUs) {
1293    ATRACE_CALL();
1294
1295    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
1296        Mutex::Autolock autoLock(mLock);
1297        return seekTo_l(timeUs);
1298    }
1299
1300    return OK;
1301}
1302
1303status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
1304    if (mFlags & CACHE_UNDERRUN) {
1305        modifyFlags(CACHE_UNDERRUN, CLEAR);
1306        play_l();
1307    }
1308
1309    if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1310        // Video playback completed before, there's no pending
1311        // video event right now. In order for this new seek
1312        // to be honored, we need to post one.
1313
1314        postVideoEvent_l();
1315    }
1316
1317    mSeeking = SEEK;
1318    mSeekNotificationSent = false;
1319    mSeekTimeUs = timeUs;
1320    modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
1321
1322    seekAudioIfNecessary_l();
1323
1324    if (mFlags & TEXTPLAYER_INITIALIZED) {
1325        mTextDriver->seekToAsync(mSeekTimeUs);
1326    }
1327
1328    if (!(mFlags & PLAYING)) {
1329        ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
1330             " immediately.");
1331
1332        notifyListener_l(MEDIA_SEEK_COMPLETE);
1333        mSeekNotificationSent = true;
1334
1335        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1336            modifyFlags(SEEK_PREVIEW, SET);
1337            postVideoEvent_l();
1338        }
1339    }
1340
1341    return OK;
1342}
1343
1344void AwesomePlayer::seekAudioIfNecessary_l() {
1345    if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1346        mAudioPlayer->seekTo(mSeekTimeUs);
1347
1348        mWatchForAudioSeekComplete = true;
1349        mWatchForAudioEOS = true;
1350
1351        if (mDecryptHandle != NULL) {
1352            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1353                    Playback::PAUSE, 0);
1354            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1355                    Playback::START, mSeekTimeUs / 1000);
1356        }
1357    }
1358}
1359
1360void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1361    CHECK(source != NULL);
1362
1363    mAudioTrack = source;
1364}
1365
1366void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) {
1367    CHECK(source != NULL);
1368
1369    if (mTextDriver == NULL) {
1370        mTextDriver = new TimedTextDriver(mListener);
1371    }
1372
1373    mTextDriver->addInBandTextSource(trackIndex, source);
1374}
1375
1376status_t AwesomePlayer::initAudioDecoder() {
1377    ATRACE_CALL();
1378
1379    sp<MetaData> meta = mAudioTrack->getFormat();
1380
1381    const char *mime;
1382    CHECK(meta->findCString(kKeyMIMEType, &mime));
1383
1384    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1385        mAudioSource = mAudioTrack;
1386    } else {
1387        mAudioSource = OMXCodec::Create(
1388                mClient.interface(), mAudioTrack->getFormat(),
1389                false, // createEncoder
1390                mAudioTrack);
1391    }
1392
1393    if (mAudioSource != NULL) {
1394        int64_t durationUs;
1395        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1396            Mutex::Autolock autoLock(mMiscStateLock);
1397            if (mDurationUs < 0 || durationUs > mDurationUs) {
1398                mDurationUs = durationUs;
1399            }
1400        }
1401
1402        status_t err = mAudioSource->start();
1403
1404        if (err != OK) {
1405            mAudioSource.clear();
1406            return err;
1407        }
1408    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1409        // For legacy reasons we're simply going to ignore the absence
1410        // of an audio decoder for QCELP instead of aborting playback
1411        // altogether.
1412        return OK;
1413    }
1414
1415    if (mAudioSource != NULL) {
1416        Mutex::Autolock autoLock(mStatsLock);
1417        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
1418        const char *component;
1419        if (!mAudioSource->getFormat()
1420                ->findCString(kKeyDecoderComponent, &component)) {
1421            component = "none";
1422        }
1423
1424        stat->mDecoderName = component;
1425    }
1426
1427    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1428}
1429
1430void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1431    CHECK(source != NULL);
1432
1433    mVideoTrack = source;
1434}
1435
1436status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1437    ATRACE_CALL();
1438
1439    // Either the application or the DRM system can independently say
1440    // that there must be a hardware-protected path to an external video sink.
1441    // For now we always require a hardware-protected path to external video sink
1442    // if content is DRMed, but eventually this could be optional per DRM agent.
1443    // When the application wants protection, then
1444    //   (USE_SURFACE_ALLOC && (mSurface != 0) &&
1445    //   (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1446    // will be true, but that part is already handled by SurfaceFlinger.
1447
1448#ifdef DEBUG_HDCP
1449    // For debugging, we allow a system property to control the protected usage.
1450    // In case of uninitialized or unexpected property, we default to "DRM only".
1451    bool setProtectionBit = false;
1452    char value[PROPERTY_VALUE_MAX];
1453    if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1454        if (!strcmp(value, "never")) {
1455            // nop
1456        } else if (!strcmp(value, "always")) {
1457            setProtectionBit = true;
1458        } else if (!strcmp(value, "drm-only")) {
1459            if (mDecryptHandle != NULL) {
1460                setProtectionBit = true;
1461            }
1462        // property value is empty, or unexpected value
1463        } else {
1464            if (mDecryptHandle != NULL) {
1465                setProtectionBit = true;
1466            }
1467        }
1468    // can' read property value
1469    } else {
1470        if (mDecryptHandle != NULL) {
1471            setProtectionBit = true;
1472        }
1473    }
1474    // note that usage bit is already cleared, so no need to clear it in the "else" case
1475    if (setProtectionBit) {
1476        flags |= OMXCodec::kEnableGrallocUsageProtected;
1477    }
1478#else
1479    if (mDecryptHandle != NULL) {
1480        flags |= OMXCodec::kEnableGrallocUsageProtected;
1481    }
1482#endif
1483    ALOGV("initVideoDecoder flags=0x%x", flags);
1484    mVideoSource = OMXCodec::Create(
1485            mClient.interface(), mVideoTrack->getFormat(),
1486            false, // createEncoder
1487            mVideoTrack,
1488            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
1489
1490    if (mVideoSource != NULL) {
1491        int64_t durationUs;
1492        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1493            Mutex::Autolock autoLock(mMiscStateLock);
1494            if (mDurationUs < 0 || durationUs > mDurationUs) {
1495                mDurationUs = durationUs;
1496            }
1497        }
1498
1499        status_t err = mVideoSource->start();
1500
1501        if (err != OK) {
1502            mVideoSource.clear();
1503            return err;
1504        }
1505    }
1506
1507    if (mVideoSource != NULL) {
1508        const char *componentName;
1509        CHECK(mVideoSource->getFormat()
1510                ->findCString(kKeyDecoderComponent, &componentName));
1511
1512        {
1513            Mutex::Autolock autoLock(mStatsLock);
1514            TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1515
1516            stat->mDecoderName = componentName;
1517        }
1518
1519        static const char *kPrefix = "OMX.Nvidia.";
1520        static const char *kSuffix = ".decode";
1521        static const size_t kSuffixLength = strlen(kSuffix);
1522
1523        size_t componentNameLength = strlen(componentName);
1524
1525        if (!strncmp(componentName, kPrefix, strlen(kPrefix))
1526                && componentNameLength >= kSuffixLength
1527                && !strcmp(&componentName[
1528                    componentNameLength - kSuffixLength], kSuffix)) {
1529            modifyFlags(SLOW_DECODER_HACK, SET);
1530        }
1531    }
1532
1533    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1534}
1535
1536void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1537    ATRACE_CALL();
1538
1539    if (mSeeking == SEEK_VIDEO_ONLY) {
1540        mSeeking = NO_SEEK;
1541        return;
1542    }
1543
1544    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1545        return;
1546    }
1547
1548    if (mAudioPlayer != NULL) {
1549        ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1550
1551        // If we don't have a video time, seek audio to the originally
1552        // requested seek time instead.
1553
1554        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1555        mWatchForAudioSeekComplete = true;
1556        mWatchForAudioEOS = true;
1557    } else if (!mSeekNotificationSent) {
1558        // If we're playing video only, report seek complete now,
1559        // otherwise audio player will notify us later.
1560        notifyListener_l(MEDIA_SEEK_COMPLETE);
1561        mSeekNotificationSent = true;
1562    }
1563
1564    modifyFlags(FIRST_FRAME, SET);
1565    mSeeking = NO_SEEK;
1566
1567    if (mDecryptHandle != NULL) {
1568        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1569                Playback::PAUSE, 0);
1570        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1571                Playback::START, videoTimeUs / 1000);
1572    }
1573}
1574
1575void AwesomePlayer::onVideoEvent() {
1576    ATRACE_CALL();
1577    Mutex::Autolock autoLock(mLock);
1578    if (!mVideoEventPending) {
1579        // The event has been cancelled in reset_l() but had already
1580        // been scheduled for execution at that time.
1581        return;
1582    }
1583    mVideoEventPending = false;
1584
1585    if (mSeeking != NO_SEEK) {
1586        if (mVideoBuffer) {
1587            mVideoBuffer->release();
1588            mVideoBuffer = NULL;
1589        }
1590
1591        if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
1592                && !(mFlags & SEEK_PREVIEW)) {
1593            // We're going to seek the video source first, followed by
1594            // the audio source.
1595            // In order to avoid jumps in the DataSource offset caused by
1596            // the audio codec prefetching data from the old locations
1597            // while the video codec is already reading data from the new
1598            // locations, we'll "pause" the audio source, causing it to
1599            // stop reading input data until a subsequent seek.
1600
1601            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1602                mAudioPlayer->pause();
1603
1604                modifyFlags(AUDIO_RUNNING, CLEAR);
1605            }
1606            mAudioSource->pause();
1607        }
1608    }
1609
1610    if (!mVideoBuffer) {
1611        MediaSource::ReadOptions options;
1612        if (mSeeking != NO_SEEK) {
1613            ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1614
1615            options.setSeekTo(
1616                    mSeekTimeUs,
1617                    mSeeking == SEEK_VIDEO_ONLY
1618                        ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1619                        : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1620        }
1621        for (;;) {
1622            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1623            options.clearSeekTo();
1624
1625            if (err != OK) {
1626                CHECK(mVideoBuffer == NULL);
1627
1628                if (err == INFO_FORMAT_CHANGED) {
1629                    ALOGV("VideoSource signalled format change.");
1630
1631                    notifyVideoSize_l();
1632
1633                    if (mVideoRenderer != NULL) {
1634                        mVideoRendererIsPreview = false;
1635                        initRenderer_l();
1636                    }
1637                    continue;
1638                }
1639
1640                // So video playback is complete, but we may still have
1641                // a seek request pending that needs to be applied
1642                // to the audio track.
1643                if (mSeeking != NO_SEEK) {
1644                    ALOGV("video stream ended while seeking!");
1645                }
1646                finishSeekIfNecessary(-1);
1647
1648                if (mAudioPlayer != NULL
1649                        && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1650                    startAudioPlayer_l();
1651                }
1652
1653                modifyFlags(VIDEO_AT_EOS, SET);
1654                postStreamDoneEvent_l(err);
1655                return;
1656            }
1657
1658            if (mVideoBuffer->range_length() == 0) {
1659                // Some decoders, notably the PV AVC software decoder
1660                // return spurious empty buffers that we just want to ignore.
1661
1662                mVideoBuffer->release();
1663                mVideoBuffer = NULL;
1664                continue;
1665            }
1666
1667            break;
1668        }
1669
1670        {
1671            Mutex::Autolock autoLock(mStatsLock);
1672            ++mStats.mNumVideoFramesDecoded;
1673        }
1674    }
1675
1676    int64_t timeUs;
1677    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1678
1679    mLastVideoTimeUs = timeUs;
1680
1681    if (mSeeking == SEEK_VIDEO_ONLY) {
1682        if (mSeekTimeUs > timeUs) {
1683            ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1684                 mSeekTimeUs, timeUs);
1685        }
1686    }
1687
1688    {
1689        Mutex::Autolock autoLock(mMiscStateLock);
1690        mVideoTimeUs = timeUs;
1691    }
1692
1693    SeekType wasSeeking = mSeeking;
1694    finishSeekIfNecessary(timeUs);
1695
1696    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1697        status_t err = startAudioPlayer_l();
1698        if (err != OK) {
1699            ALOGE("Starting the audio player failed w/ err %d", err);
1700            return;
1701        }
1702    }
1703
1704    if ((mFlags & TEXTPLAYER_INITIALIZED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1705        mTextDriver->start();
1706        modifyFlags(TEXT_RUNNING, SET);
1707    }
1708
1709    TimeSource *ts =
1710        ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
1711            ? &mSystemTimeSource : mTimeSource;
1712
1713    if (mFlags & FIRST_FRAME) {
1714        modifyFlags(FIRST_FRAME, CLEAR);
1715        mSinceLastDropped = 0;
1716        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1717    }
1718
1719    int64_t realTimeUs, mediaTimeUs;
1720    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1721        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1722        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1723    }
1724
1725    if (wasSeeking == SEEK_VIDEO_ONLY) {
1726        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1727
1728        int64_t latenessUs = nowUs - timeUs;
1729
1730        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1731
1732        if (latenessUs > 0) {
1733            ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1734        }
1735    }
1736
1737    if (wasSeeking == NO_SEEK) {
1738        // Let's display the first frame after seeking right away.
1739
1740        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1741
1742        int64_t latenessUs = nowUs - timeUs;
1743
1744        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1745
1746        if (latenessUs > 500000ll
1747                && mAudioPlayer != NULL
1748                && mAudioPlayer->getMediaTimeMapping(
1749                    &realTimeUs, &mediaTimeUs)) {
1750            ALOGI("we're much too late (%.2f secs), video skipping ahead",
1751                 latenessUs / 1E6);
1752
1753            mVideoBuffer->release();
1754            mVideoBuffer = NULL;
1755
1756            mSeeking = SEEK_VIDEO_ONLY;
1757            mSeekTimeUs = mediaTimeUs;
1758
1759            postVideoEvent_l();
1760            return;
1761        }
1762
1763        if (latenessUs > 40000) {
1764            // We're more than 40ms late.
1765            ALOGV("we're late by %lld us (%.2f secs)",
1766                 latenessUs, latenessUs / 1E6);
1767
1768            if (!(mFlags & SLOW_DECODER_HACK)
1769                    || mSinceLastDropped > FRAME_DROP_FREQ)
1770            {
1771                ALOGV("we're late by %lld us (%.2f secs) dropping "
1772                     "one after %d frames",
1773                     latenessUs, latenessUs / 1E6, mSinceLastDropped);
1774
1775                mSinceLastDropped = 0;
1776                mVideoBuffer->release();
1777                mVideoBuffer = NULL;
1778
1779                {
1780                    Mutex::Autolock autoLock(mStatsLock);
1781                    ++mStats.mNumVideoFramesDropped;
1782                }
1783
1784                postVideoEvent_l();
1785                return;
1786            }
1787        }
1788
1789        if (latenessUs < -10000) {
1790            // We're more than 10ms early.
1791            postVideoEvent_l(10000);
1792            return;
1793        }
1794    }
1795
1796    if ((mNativeWindow != NULL)
1797            && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
1798        mVideoRendererIsPreview = false;
1799
1800        initRenderer_l();
1801    }
1802
1803    if (mVideoRenderer != NULL) {
1804        mSinceLastDropped++;
1805        mVideoRenderer->render(mVideoBuffer);
1806    }
1807
1808    mVideoBuffer->release();
1809    mVideoBuffer = NULL;
1810
1811    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
1812        modifyFlags(SEEK_PREVIEW, CLEAR);
1813        return;
1814    }
1815
1816    postVideoEvent_l();
1817}
1818
1819void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1820    ATRACE_CALL();
1821
1822    if (mVideoEventPending) {
1823        return;
1824    }
1825
1826    mVideoEventPending = true;
1827    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1828}
1829
1830void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1831    if (mStreamDoneEventPending) {
1832        return;
1833    }
1834    mStreamDoneEventPending = true;
1835
1836    mStreamDoneStatus = status;
1837    mQueue.postEvent(mStreamDoneEvent);
1838}
1839
1840void AwesomePlayer::postBufferingEvent_l() {
1841    if (mBufferingEventPending) {
1842        return;
1843    }
1844    mBufferingEventPending = true;
1845    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1846}
1847
1848void AwesomePlayer::postVideoLagEvent_l() {
1849    if (mVideoLagEventPending) {
1850        return;
1851    }
1852    mVideoLagEventPending = true;
1853    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1854}
1855
1856void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
1857    Mutex::Autolock autoLock(mAudioLock);
1858    if (mAudioStatusEventPending) {
1859        return;
1860    }
1861    mAudioStatusEventPending = true;
1862    // Do not honor delay when looping in order to limit audio gap
1863    if (mFlags & (LOOPING | AUTO_LOOPING)) {
1864        delayUs = 0;
1865    }
1866    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
1867}
1868
1869void AwesomePlayer::onCheckAudioStatus() {
1870    {
1871        Mutex::Autolock autoLock(mAudioLock);
1872        if (!mAudioStatusEventPending) {
1873            // Event was dispatched and while we were blocking on the mutex,
1874            // has already been cancelled.
1875            return;
1876        }
1877
1878        mAudioStatusEventPending = false;
1879    }
1880
1881    Mutex::Autolock autoLock(mLock);
1882
1883    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1884        mWatchForAudioSeekComplete = false;
1885
1886        if (!mSeekNotificationSent) {
1887            notifyListener_l(MEDIA_SEEK_COMPLETE);
1888            mSeekNotificationSent = true;
1889        }
1890
1891        mSeeking = NO_SEEK;
1892    }
1893
1894    status_t finalStatus;
1895    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1896        mWatchForAudioEOS = false;
1897        modifyFlags(AUDIO_AT_EOS, SET);
1898        modifyFlags(FIRST_FRAME, SET);
1899        postStreamDoneEvent_l(finalStatus);
1900    }
1901}
1902
1903status_t AwesomePlayer::prepare() {
1904    ATRACE_CALL();
1905    Mutex::Autolock autoLock(mLock);
1906    return prepare_l();
1907}
1908
1909status_t AwesomePlayer::prepare_l() {
1910    if (mFlags & PREPARED) {
1911        return OK;
1912    }
1913
1914    if (mFlags & PREPARING) {
1915        return UNKNOWN_ERROR;
1916    }
1917
1918    mIsAsyncPrepare = false;
1919    status_t err = prepareAsync_l();
1920
1921    if (err != OK) {
1922        return err;
1923    }
1924
1925    while (mFlags & PREPARING) {
1926        mPreparedCondition.wait(mLock);
1927    }
1928
1929    return mPrepareResult;
1930}
1931
1932status_t AwesomePlayer::prepareAsync() {
1933    ATRACE_CALL();
1934    Mutex::Autolock autoLock(mLock);
1935
1936    if (mFlags & PREPARING) {
1937        return UNKNOWN_ERROR;  // async prepare already pending
1938    }
1939
1940    mIsAsyncPrepare = true;
1941    return prepareAsync_l();
1942}
1943
1944status_t AwesomePlayer::prepareAsync_l() {
1945    if (mFlags & PREPARING) {
1946        return UNKNOWN_ERROR;  // async prepare already pending
1947    }
1948
1949    if (!mQueueStarted) {
1950        mQueue.start();
1951        mQueueStarted = true;
1952    }
1953
1954    modifyFlags(PREPARING, SET);
1955    mAsyncPrepareEvent = new AwesomeEvent(
1956            this, &AwesomePlayer::onPrepareAsyncEvent);
1957
1958    mQueue.postEvent(mAsyncPrepareEvent);
1959
1960    return OK;
1961}
1962
1963status_t AwesomePlayer::finishSetDataSource_l() {
1964    ATRACE_CALL();
1965    sp<DataSource> dataSource;
1966
1967    bool isWidevineStreaming = false;
1968    if (!strncasecmp("widevine://", mUri.string(), 11)) {
1969        isWidevineStreaming = true;
1970
1971        String8 newURI = String8("http://");
1972        newURI.append(mUri.string() + 11);
1973
1974        mUri = newURI;
1975    }
1976
1977    AString sniffedMIME;
1978
1979    if (!strncasecmp("http://", mUri.string(), 7)
1980            || !strncasecmp("https://", mUri.string(), 8)
1981            || isWidevineStreaming) {
1982        mConnectingDataSource = HTTPBase::Create(
1983                (mFlags & INCOGNITO)
1984                    ? HTTPBase::kFlagIncognito
1985                    : 0);
1986
1987        if (mUIDValid) {
1988            mConnectingDataSource->setUID(mUID);
1989        }
1990
1991        String8 cacheConfig;
1992        bool disconnectAtHighwatermark;
1993        NuCachedSource2::RemoveCacheSpecificHeaders(
1994                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
1995
1996        mLock.unlock();
1997        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
1998        mLock.lock();
1999
2000        if (err != OK) {
2001            mConnectingDataSource.clear();
2002
2003            ALOGI("mConnectingDataSource->connect() returned %d", err);
2004            return err;
2005        }
2006
2007        if (!isWidevineStreaming) {
2008            // The widevine extractor does its own caching.
2009
2010#if 0
2011            mCachedSource = new NuCachedSource2(
2012                    new ThrottledSource(
2013                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
2014#else
2015            mCachedSource = new NuCachedSource2(
2016                    mConnectingDataSource,
2017                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
2018                    disconnectAtHighwatermark);
2019#endif
2020
2021            dataSource = mCachedSource;
2022        } else {
2023            dataSource = mConnectingDataSource;
2024        }
2025
2026        mConnectingDataSource.clear();
2027
2028        String8 contentType = dataSource->getMIMEType();
2029
2030        if (strncasecmp(contentType.string(), "audio/", 6)) {
2031            // We're not doing this for streams that appear to be audio-only
2032            // streams to ensure that even low bandwidth streams start
2033            // playing back fairly instantly.
2034
2035            // We're going to prefill the cache before trying to instantiate
2036            // the extractor below, as the latter is an operation that otherwise
2037            // could block on the datasource for a significant amount of time.
2038            // During that time we'd be unable to abort the preparation phase
2039            // without this prefill.
2040            if (mCachedSource != NULL) {
2041                // We're going to prefill the cache before trying to instantiate
2042                // the extractor below, as the latter is an operation that otherwise
2043                // could block on the datasource for a significant amount of time.
2044                // During that time we'd be unable to abort the preparation phase
2045                // without this prefill.
2046
2047                mLock.unlock();
2048
2049                // Initially make sure we have at least 192 KB for the sniff
2050                // to complete without blocking.
2051                static const size_t kMinBytesForSniffing = 192 * 1024;
2052
2053                off64_t metaDataSize = -1ll;
2054                for (;;) {
2055                    status_t finalStatus;
2056                    size_t cachedDataRemaining =
2057                        mCachedSource->approxDataRemaining(&finalStatus);
2058
2059                    if (finalStatus != OK
2060                            || (metaDataSize >= 0
2061                                && cachedDataRemaining >= metaDataSize)
2062                            || (mFlags & PREPARE_CANCELLED)) {
2063                        break;
2064                    }
2065
2066                    ALOGV("now cached %d bytes of data", cachedDataRemaining);
2067
2068                    if (metaDataSize < 0
2069                            && cachedDataRemaining >= kMinBytesForSniffing) {
2070                        String8 tmp;
2071                        float confidence;
2072                        sp<AMessage> meta;
2073                        if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2074                            mLock.lock();
2075                            return UNKNOWN_ERROR;
2076                        }
2077
2078                        // We successfully identified the file's extractor to
2079                        // be, remember this mime type so we don't have to
2080                        // sniff it again when we call MediaExtractor::Create()
2081                        // below.
2082                        sniffedMIME = tmp.string();
2083
2084                        if (meta == NULL
2085                                || !meta->findInt64(
2086                                    "meta-data-size", &metaDataSize)) {
2087                            metaDataSize = kHighWaterMarkBytes;
2088                        }
2089
2090                        CHECK_GE(metaDataSize, 0ll);
2091                        ALOGV("metaDataSize = %lld bytes", metaDataSize);
2092                    }
2093
2094                    usleep(200000);
2095                }
2096
2097                mLock.lock();
2098            }
2099
2100            if (mFlags & PREPARE_CANCELLED) {
2101                ALOGI("Prepare cancelled while waiting for initial cache fill.");
2102                return UNKNOWN_ERROR;
2103            }
2104        }
2105    } else {
2106        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2107    }
2108
2109    if (dataSource == NULL) {
2110        return UNKNOWN_ERROR;
2111    }
2112
2113    sp<MediaExtractor> extractor;
2114
2115    if (isWidevineStreaming) {
2116        String8 mimeType;
2117        float confidence;
2118        sp<AMessage> dummy;
2119        bool success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
2120
2121        if (!success
2122                || strcasecmp(
2123                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2124            return ERROR_UNSUPPORTED;
2125        }
2126
2127        mWVMExtractor = new WVMExtractor(dataSource);
2128        mWVMExtractor->setAdaptiveStreamingMode(true);
2129        if (mUIDValid)
2130            mWVMExtractor->setUID(mUID);
2131        extractor = mWVMExtractor;
2132    } else {
2133        extractor = MediaExtractor::Create(
2134                dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
2135
2136        if (extractor == NULL) {
2137            return UNKNOWN_ERROR;
2138        }
2139    }
2140
2141    if (extractor->getDrmFlag()) {
2142        checkDrmStatus(dataSource);
2143    }
2144
2145    status_t err = setDataSource_l(extractor);
2146
2147    if (err != OK) {
2148        mWVMExtractor.clear();
2149
2150        return err;
2151    }
2152
2153    return OK;
2154}
2155
2156void AwesomePlayer::abortPrepare(status_t err) {
2157    CHECK(err != OK);
2158
2159    if (mIsAsyncPrepare) {
2160        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2161    }
2162
2163    mPrepareResult = err;
2164    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2165    mAsyncPrepareEvent = NULL;
2166    mPreparedCondition.broadcast();
2167}
2168
2169// static
2170bool AwesomePlayer::ContinuePreparation(void *cookie) {
2171    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2172
2173    return (me->mFlags & PREPARE_CANCELLED) == 0;
2174}
2175
2176void AwesomePlayer::onPrepareAsyncEvent() {
2177    Mutex::Autolock autoLock(mLock);
2178
2179    if (mFlags & PREPARE_CANCELLED) {
2180        ALOGI("prepare was cancelled before doing anything");
2181        abortPrepare(UNKNOWN_ERROR);
2182        return;
2183    }
2184
2185    if (mUri.size() > 0) {
2186        status_t err = finishSetDataSource_l();
2187
2188        if (err != OK) {
2189            abortPrepare(err);
2190            return;
2191        }
2192    }
2193
2194    if (mVideoTrack != NULL && mVideoSource == NULL) {
2195        status_t err = initVideoDecoder();
2196
2197        if (err != OK) {
2198            abortPrepare(err);
2199            return;
2200        }
2201    }
2202
2203    if (mAudioTrack != NULL && mAudioSource == NULL) {
2204        status_t err = initAudioDecoder();
2205
2206        if (err != OK) {
2207            abortPrepare(err);
2208            return;
2209        }
2210    }
2211
2212    modifyFlags(PREPARING_CONNECTED, SET);
2213
2214    if (isStreamingHTTP()) {
2215        postBufferingEvent_l();
2216    } else {
2217        finishAsyncPrepare_l();
2218    }
2219}
2220
2221void AwesomePlayer::finishAsyncPrepare_l() {
2222    if (mIsAsyncPrepare) {
2223        if (mVideoSource == NULL) {
2224            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2225        } else {
2226            notifyVideoSize_l();
2227        }
2228
2229        notifyListener_l(MEDIA_PREPARED);
2230    }
2231
2232    mPrepareResult = OK;
2233    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2234    modifyFlags(PREPARED, SET);
2235    mAsyncPrepareEvent = NULL;
2236    mPreparedCondition.broadcast();
2237}
2238
2239uint32_t AwesomePlayer::flags() const {
2240    return mExtractorFlags;
2241}
2242
2243void AwesomePlayer::postAudioEOS(int64_t delayUs) {
2244    postCheckAudioStatusEvent(delayUs);
2245}
2246
2247void AwesomePlayer::postAudioSeekComplete() {
2248    postCheckAudioStatusEvent(0);
2249}
2250
2251status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
2252    switch (key) {
2253        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2254        {
2255            return setCacheStatCollectFreq(request);
2256        }
2257        case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
2258        {
2259            if (mAudioPlayer != NULL) {
2260                return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
2261            } else {
2262                return NO_INIT;
2263            }
2264        }
2265        default:
2266        {
2267            return ERROR_UNSUPPORTED;
2268        }
2269    }
2270}
2271
2272status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2273    if (mCachedSource != NULL) {
2274        int32_t freqMs = request.readInt32();
2275        ALOGD("Request to keep cache stats in the past %d ms",
2276            freqMs);
2277        return mCachedSource->setCacheStatCollectFreq(freqMs);
2278    }
2279    return ERROR_UNSUPPORTED;
2280}
2281
2282status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
2283    switch (key) {
2284    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2285        {
2286            int32_t channelCount;
2287            if (mAudioTrack == 0 ||
2288                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2289                channelCount = 0;
2290            }
2291            reply->writeInt32(channelCount);
2292        }
2293        return OK;
2294    default:
2295        {
2296            return ERROR_UNSUPPORTED;
2297        }
2298    }
2299}
2300
2301status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
2302    Mutex::Autolock autoLock(mLock);
2303    size_t trackCount = mExtractor->countTracks();
2304    if (mTextDriver != NULL) {
2305        trackCount += mTextDriver->countExternalTracks();
2306    }
2307
2308    reply->writeInt32(trackCount);
2309    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
2310        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2311
2312        const char *_mime;
2313        CHECK(meta->findCString(kKeyMIMEType, &_mime));
2314
2315        String8 mime = String8(_mime);
2316
2317        reply->writeInt32(2); // 2 fields
2318
2319        if (!strncasecmp(mime.string(), "video/", 6)) {
2320            reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
2321        } else if (!strncasecmp(mime.string(), "audio/", 6)) {
2322            reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
2323        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
2324            reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
2325        } else {
2326            reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
2327        }
2328
2329        const char *lang;
2330        if (!meta->findCString(kKeyMediaLanguage, &lang)) {
2331            lang = "und";
2332        }
2333        reply->writeString16(String16(lang));
2334    }
2335
2336    if (mTextDriver != NULL) {
2337        mTextDriver->getExternalTrackInfo(reply);
2338    }
2339    return OK;
2340}
2341
2342status_t AwesomePlayer::selectAudioTrack_l(
2343        const sp<MediaSource>& source, size_t trackIndex) {
2344
2345    ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags);
2346
2347    {
2348        Mutex::Autolock autoLock(mStatsLock);
2349        if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
2350            ALOGI("Track %d is active. Does nothing.", trackIndex);
2351            return OK;
2352        }
2353        //mStats.mFlags = mFlags;
2354    }
2355
2356    if (mSeeking != NO_SEEK) {
2357        ALOGE("Selecting a track while seeking is not supported");
2358        return ERROR_UNSUPPORTED;
2359    }
2360
2361    if ((mFlags & PREPARED) == 0) {
2362        ALOGE("Data source has not finished preparation");
2363        return ERROR_UNSUPPORTED;
2364    }
2365
2366    CHECK(source != NULL);
2367    bool wasPlaying = (mFlags & PLAYING) != 0;
2368
2369    pause_l();
2370
2371    int64_t curTimeUs;
2372    CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
2373
2374    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
2375            && mAudioSource != NULL) {
2376        // If we had an audio player, it would have effectively
2377        // taken possession of the audio source and stopped it when
2378        // _it_ is stopped. Otherwise this is still our responsibility.
2379        mAudioSource->stop();
2380    }
2381    mAudioSource.clear();
2382
2383    mTimeSource = NULL;
2384
2385    delete mAudioPlayer;
2386    mAudioPlayer = NULL;
2387
2388    modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
2389
2390    setAudioSource(source);
2391
2392    modifyFlags(AUDIO_AT_EOS, CLEAR);
2393    modifyFlags(AT_EOS, CLEAR);
2394
2395    status_t err;
2396    if ((err = initAudioDecoder()) != OK) {
2397        ALOGE("Failed to init audio decoder: 0x%x", err);
2398        return err;
2399    }
2400
2401    mSeekNotificationSent = true;
2402    seekTo_l(curTimeUs);
2403
2404    if (wasPlaying) {
2405        play_l();
2406    }
2407
2408    mActiveAudioTrackIndex = trackIndex;
2409
2410    return OK;
2411}
2412
2413status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
2414    ATRACE_CALL();
2415    ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
2416    Mutex::Autolock autoLock(mLock);
2417    size_t trackCount = mExtractor->countTracks();
2418    if (mTextDriver != NULL) {
2419        trackCount += mTextDriver->countExternalTracks();
2420    }
2421    if (trackIndex >= trackCount) {
2422        ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount);
2423        return ERROR_OUT_OF_RANGE;
2424    }
2425
2426    bool isAudioTrack = false;
2427    if (trackIndex < mExtractor->countTracks()) {
2428        sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
2429        const char *mime;
2430        CHECK(meta->findCString(kKeyMIMEType, &mime));
2431        isAudioTrack = !strncasecmp(mime, "audio/", 6);
2432
2433        if (!isAudioTrack && !strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
2434            ALOGE("Track %d is not either audio or timed text", trackIndex);
2435            return ERROR_UNSUPPORTED;
2436        }
2437    }
2438
2439    if (isAudioTrack) {
2440        if (!select) {
2441            ALOGE("Deselect an audio track (%d) is not supported", trackIndex);
2442            return ERROR_UNSUPPORTED;
2443        }
2444        return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
2445    }
2446
2447    // Timed text track handling
2448    if (mTextDriver == NULL) {
2449        return INVALID_OPERATION;
2450    }
2451
2452    status_t err = OK;
2453    if (select) {
2454        err = mTextDriver->selectTrack(trackIndex);
2455        if (err == OK) {
2456            modifyFlags(TEXTPLAYER_INITIALIZED, SET);
2457            if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
2458                mTextDriver->start();
2459                modifyFlags(TEXT_RUNNING, SET);
2460            }
2461        }
2462    } else {
2463        err = mTextDriver->unselectTrack(trackIndex);
2464        if (err == OK) {
2465            modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
2466            modifyFlags(TEXT_RUNNING, CLEAR);
2467        }
2468    }
2469    return err;
2470}
2471
2472size_t AwesomePlayer::countTracks() const {
2473    return mExtractor->countTracks() + mTextDriver->countExternalTracks();
2474}
2475
2476status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
2477    Mutex::Autolock lock(mLock);
2478    return setVideoScalingMode_l(mode);
2479}
2480
2481status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
2482    mVideoScalingMode = mode;
2483    if (mNativeWindow != NULL) {
2484        status_t err = native_window_set_scaling_mode(
2485                mNativeWindow.get(), mVideoScalingMode);
2486        if (err != OK) {
2487            ALOGW("Failed to set scaling mode: %d", err);
2488        }
2489    }
2490    return OK;
2491}
2492
2493status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
2494    ATRACE_CALL();
2495    if (NULL == reply) {
2496        return android::BAD_VALUE;
2497    }
2498    int32_t methodId;
2499    status_t ret = request.readInt32(&methodId);
2500    if (ret != android::OK) {
2501        return ret;
2502    }
2503    switch(methodId) {
2504        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
2505        {
2506            int mode = request.readInt32();
2507            return setVideoScalingMode(mode);
2508        }
2509
2510        case INVOKE_ID_GET_TRACK_INFO:
2511        {
2512            return getTrackInfo(reply);
2513        }
2514        case INVOKE_ID_ADD_EXTERNAL_SOURCE:
2515        {
2516            Mutex::Autolock autoLock(mLock);
2517            if (mTextDriver == NULL) {
2518                mTextDriver = new TimedTextDriver(mListener);
2519            }
2520            // String values written in Parcel are UTF-16 values.
2521            String8 uri(request.readString16());
2522            String8 mimeType(request.readString16());
2523            size_t nTracks = countTracks();
2524            return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
2525        }
2526        case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
2527        {
2528            Mutex::Autolock autoLock(mLock);
2529            if (mTextDriver == NULL) {
2530                mTextDriver = new TimedTextDriver(mListener);
2531            }
2532            int fd         = request.readFileDescriptor();
2533            off64_t offset = request.readInt64();
2534            off64_t length  = request.readInt64();
2535            String8 mimeType(request.readString16());
2536            size_t nTracks = countTracks();
2537            return mTextDriver->addOutOfBandTextSource(
2538                    nTracks, fd, offset, length, mimeType);
2539        }
2540        case INVOKE_ID_SELECT_TRACK:
2541        {
2542            int trackIndex = request.readInt32();
2543            return selectTrack(trackIndex, true /* select */);
2544        }
2545        case INVOKE_ID_UNSELECT_TRACK:
2546        {
2547            int trackIndex = request.readInt32();
2548            return selectTrack(trackIndex, false /* select */);
2549        }
2550        default:
2551        {
2552            return ERROR_UNSUPPORTED;
2553        }
2554    }
2555    // It will not reach here.
2556    return OK;
2557}
2558
2559bool AwesomePlayer::isStreamingHTTP() const {
2560    return mCachedSource != NULL || mWVMExtractor != NULL;
2561}
2562
2563status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2564    Mutex::Autolock autoLock(mStatsLock);
2565
2566    FILE *out = fdopen(dup(fd), "w");
2567
2568    fprintf(out, " AwesomePlayer\n");
2569    if (mStats.mFd < 0) {
2570        fprintf(out, "  URI(%s)", mStats.mURI.string());
2571    } else {
2572        fprintf(out, "  fd(%d)", mStats.mFd);
2573    }
2574
2575    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2576
2577    if (mStats.mBitrate >= 0) {
2578        fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2579    }
2580
2581    fprintf(out, "\n");
2582
2583    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2584        const TrackStat &stat = mStats.mTracks.itemAt(i);
2585
2586        fprintf(out, "  Track %d\n", i + 1);
2587        fprintf(out, "   MIME(%s)", stat.mMIME.string());
2588
2589        if (!stat.mDecoderName.isEmpty()) {
2590            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2591        }
2592
2593        fprintf(out, "\n");
2594
2595        if ((ssize_t)i == mStats.mVideoTrackIndex) {
2596            fprintf(out,
2597                    "   videoDimensions(%d x %d), "
2598                    "numVideoFramesDecoded(%lld), "
2599                    "numVideoFramesDropped(%lld)\n",
2600                    mStats.mVideoWidth,
2601                    mStats.mVideoHeight,
2602                    mStats.mNumVideoFramesDecoded,
2603                    mStats.mNumVideoFramesDropped);
2604        }
2605    }
2606
2607    fclose(out);
2608    out = NULL;
2609
2610    return OK;
2611}
2612
2613void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2614    switch (mode) {
2615        case SET:
2616            mFlags |= value;
2617            break;
2618        case CLEAR:
2619            mFlags &= ~value;
2620            break;
2621        case ASSIGN:
2622            mFlags = value;
2623            break;
2624        default:
2625            TRESPASS();
2626    }
2627
2628    {
2629        Mutex::Autolock autoLock(mStatsLock);
2630        mStats.mFlags = mFlags;
2631    }
2632}
2633
2634}  // namespace android
2635