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