1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "NuPlayerDriver"
19*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <android-base/macros.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerDriver.h"
25*ec779b8eSAndroid Build Coastguard Worker
26*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayer.h"
27*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerSource.h"
28*ec779b8eSAndroid Build Coastguard Worker
29*ec779b8eSAndroid Build Coastguard Worker #include <audiomanager/AudioManager.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ALooper.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AUtils.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ByteUtils.h>
34*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaClock.h>
35*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
36*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/Utils.h>
37*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/FoundationUtils.h>
38*ec779b8eSAndroid Build Coastguard Worker
39*ec779b8eSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_AUDIO
40*ec779b8eSAndroid Build Coastguard Worker #include <utils/Trace.h>
41*ec779b8eSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
42*ec779b8eSAndroid Build Coastguard Worker using ::android::base::StringPrintf;
43*ec779b8eSAndroid Build Coastguard Worker
44*ec779b8eSAndroid Build Coastguard Worker static const int kDumpLockRetries = 50;
45*ec779b8eSAndroid Build Coastguard Worker static const int kDumpLockSleepUs = 20000;
46*ec779b8eSAndroid Build Coastguard Worker
47*ec779b8eSAndroid Build Coastguard Worker namespace android {
48*ec779b8eSAndroid Build Coastguard Worker
49*ec779b8eSAndroid Build Coastguard Worker // key for media statistics
50*ec779b8eSAndroid Build Coastguard Worker static const char *kKeyPlayer = "nuplayer";
51*ec779b8eSAndroid Build Coastguard Worker // attrs for media statistics
52*ec779b8eSAndroid Build Coastguard Worker // NB: these are matched with public Java API constants defined
53*ec779b8eSAndroid Build Coastguard Worker // in frameworks/base/media/java/android/media/MediaPlayer.java
54*ec779b8eSAndroid Build Coastguard Worker // These must be kept synchronized with the constants there.
55*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
56*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
57*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerWidth = "android.media.mediaplayer.width";
58*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerHeight = "android.media.mediaplayer.height";
59*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerFrames = "android.media.mediaplayer.frames";
60*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
61*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerFrameRate = "android.media.mediaplayer.fps";
62*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
63*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
64*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
65*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
66*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerError = "android.media.mediaplayer.err";
67*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
68*ec779b8eSAndroid Build Coastguard Worker
69*ec779b8eSAndroid Build Coastguard Worker // NB: These are not yet exposed as public Java API constants.
70*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
71*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
72*ec779b8eSAndroid Build Coastguard Worker //
73*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
74*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
75*ec779b8eSAndroid Build Coastguard Worker static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
76*ec779b8eSAndroid Build Coastguard Worker
77*ec779b8eSAndroid Build Coastguard Worker
NuPlayerDriver(pid_t pid)78*ec779b8eSAndroid Build Coastguard Worker NuPlayerDriver::NuPlayerDriver(pid_t pid)
79*ec779b8eSAndroid Build Coastguard Worker : mState(STATE_IDLE),
80*ec779b8eSAndroid Build Coastguard Worker mIsAsyncPrepare(false),
81*ec779b8eSAndroid Build Coastguard Worker mAsyncResult(UNKNOWN_ERROR),
82*ec779b8eSAndroid Build Coastguard Worker mSetSurfaceInProgress(false),
83*ec779b8eSAndroid Build Coastguard Worker mDurationUs(-1),
84*ec779b8eSAndroid Build Coastguard Worker mPositionUs(-1),
85*ec779b8eSAndroid Build Coastguard Worker mSeekInProgress(false),
86*ec779b8eSAndroid Build Coastguard Worker mPlayingTimeUs(0),
87*ec779b8eSAndroid Build Coastguard Worker mRebufferingTimeUs(0),
88*ec779b8eSAndroid Build Coastguard Worker mRebufferingEvents(0),
89*ec779b8eSAndroid Build Coastguard Worker mRebufferingAtExit(false),
90*ec779b8eSAndroid Build Coastguard Worker mLooper(new ALooper),
91*ec779b8eSAndroid Build Coastguard Worker mMediaClock(new MediaClock),
92*ec779b8eSAndroid Build Coastguard Worker mPlayer(new NuPlayer(pid, mMediaClock)),
93*ec779b8eSAndroid Build Coastguard Worker mPlayerFlags(0),
94*ec779b8eSAndroid Build Coastguard Worker mCachedPlayerIId(PLAYER_PIID_INVALID),
95*ec779b8eSAndroid Build Coastguard Worker mMetricsItem(NULL),
96*ec779b8eSAndroid Build Coastguard Worker mClientUid(-1),
97*ec779b8eSAndroid Build Coastguard Worker mAtEOS(false),
98*ec779b8eSAndroid Build Coastguard Worker mLooping(false),
99*ec779b8eSAndroid Build Coastguard Worker mAutoLoop(false) {
100*ec779b8eSAndroid Build Coastguard Worker ALOGD("NuPlayerDriver(%p) created, clientPid(%d)", this, pid);
101*ec779b8eSAndroid Build Coastguard Worker mLooper->setName("NuPlayerDriver Looper");
102*ec779b8eSAndroid Build Coastguard Worker
103*ec779b8eSAndroid Build Coastguard Worker mMediaClock->init();
104*ec779b8eSAndroid Build Coastguard Worker
105*ec779b8eSAndroid Build Coastguard Worker // set up an analytics record
106*ec779b8eSAndroid Build Coastguard Worker mMetricsItem = mediametrics::Item::create(kKeyPlayer);
107*ec779b8eSAndroid Build Coastguard Worker
108*ec779b8eSAndroid Build Coastguard Worker mLooper->start(
109*ec779b8eSAndroid Build Coastguard Worker false, /* runOnCallingThread */
110*ec779b8eSAndroid Build Coastguard Worker true, /* canCallJava */
111*ec779b8eSAndroid Build Coastguard Worker PRIORITY_AUDIO);
112*ec779b8eSAndroid Build Coastguard Worker
113*ec779b8eSAndroid Build Coastguard Worker mLooper->registerHandler(mPlayer);
114*ec779b8eSAndroid Build Coastguard Worker
115*ec779b8eSAndroid Build Coastguard Worker mPlayer->init(this);
116*ec779b8eSAndroid Build Coastguard Worker }
117*ec779b8eSAndroid Build Coastguard Worker
~NuPlayerDriver()118*ec779b8eSAndroid Build Coastguard Worker NuPlayerDriver::~NuPlayerDriver() {
119*ec779b8eSAndroid Build Coastguard Worker ALOGV("~NuPlayerDriver(%p)", this);
120*ec779b8eSAndroid Build Coastguard Worker mLooper->stop();
121*ec779b8eSAndroid Build Coastguard Worker
122*ec779b8eSAndroid Build Coastguard Worker // finalize any pending metrics, usually a no-op.
123*ec779b8eSAndroid Build Coastguard Worker updateMetrics("destructor");
124*ec779b8eSAndroid Build Coastguard Worker logMetrics("destructor");
125*ec779b8eSAndroid Build Coastguard Worker
126*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mMetricsLock);
127*ec779b8eSAndroid Build Coastguard Worker if (mMetricsItem != NULL) {
128*ec779b8eSAndroid Build Coastguard Worker delete mMetricsItem;
129*ec779b8eSAndroid Build Coastguard Worker mMetricsItem = NULL;
130*ec779b8eSAndroid Build Coastguard Worker }
131*ec779b8eSAndroid Build Coastguard Worker }
132*ec779b8eSAndroid Build Coastguard Worker
initCheck()133*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::initCheck() {
134*ec779b8eSAndroid Build Coastguard Worker return OK;
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker
setUID(uid_t uid)137*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setUID(uid_t uid) {
138*ec779b8eSAndroid Build Coastguard Worker mPlayer->setUID(uid);
139*ec779b8eSAndroid Build Coastguard Worker mClientUid = uid;
140*ec779b8eSAndroid Build Coastguard Worker
141*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mMetricsLock);
142*ec779b8eSAndroid Build Coastguard Worker if (mMetricsItem) {
143*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setUid(mClientUid);
144*ec779b8eSAndroid Build Coastguard Worker }
145*ec779b8eSAndroid Build Coastguard Worker
146*ec779b8eSAndroid Build Coastguard Worker return OK;
147*ec779b8eSAndroid Build Coastguard Worker }
148*ec779b8eSAndroid Build Coastguard Worker
setDataSource(const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)149*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(
150*ec779b8eSAndroid Build Coastguard Worker const sp<IMediaHTTPService> &httpService,
151*ec779b8eSAndroid Build Coastguard Worker const char *url,
152*ec779b8eSAndroid Build Coastguard Worker const KeyedVector<String8, String8> *headers) {
153*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource(%p) url(%s)", this, uriDebugString(url, false).c_str());
154*ec779b8eSAndroid Build Coastguard Worker ATRACE_BEGIN(StringPrintf("setDataSource(%p)", this).c_str());
155*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
156*ec779b8eSAndroid Build Coastguard Worker
157*ec779b8eSAndroid Build Coastguard Worker if (mState != STATE_IDLE) {
158*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
159*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
160*ec779b8eSAndroid Build Coastguard Worker }
161*ec779b8eSAndroid Build Coastguard Worker
162*ec779b8eSAndroid Build Coastguard Worker mState = STATE_SET_DATASOURCE_PENDING;
163*ec779b8eSAndroid Build Coastguard Worker
164*ec779b8eSAndroid Build Coastguard Worker mPlayer->setDataSourceAsync(httpService, url, headers);
165*ec779b8eSAndroid Build Coastguard Worker
166*ec779b8eSAndroid Build Coastguard Worker while (mState == STATE_SET_DATASOURCE_PENDING) {
167*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
168*ec779b8eSAndroid Build Coastguard Worker }
169*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
170*ec779b8eSAndroid Build Coastguard Worker
171*ec779b8eSAndroid Build Coastguard Worker return mAsyncResult;
172*ec779b8eSAndroid Build Coastguard Worker }
173*ec779b8eSAndroid Build Coastguard Worker
setDataSource(int fd,int64_t offset,int64_t length)174*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
175*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource(%p) file(%d)", this, fd);
176*ec779b8eSAndroid Build Coastguard Worker ATRACE_BEGIN(StringPrintf("setDataSource(%p) file(%d)", this, fd).c_str());
177*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
178*ec779b8eSAndroid Build Coastguard Worker
179*ec779b8eSAndroid Build Coastguard Worker if (mState != STATE_IDLE) {
180*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
181*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
182*ec779b8eSAndroid Build Coastguard Worker }
183*ec779b8eSAndroid Build Coastguard Worker
184*ec779b8eSAndroid Build Coastguard Worker mState = STATE_SET_DATASOURCE_PENDING;
185*ec779b8eSAndroid Build Coastguard Worker
186*ec779b8eSAndroid Build Coastguard Worker mPlayer->setDataSourceAsync(fd, offset, length);
187*ec779b8eSAndroid Build Coastguard Worker
188*ec779b8eSAndroid Build Coastguard Worker while (mState == STATE_SET_DATASOURCE_PENDING) {
189*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
190*ec779b8eSAndroid Build Coastguard Worker }
191*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
192*ec779b8eSAndroid Build Coastguard Worker
193*ec779b8eSAndroid Build Coastguard Worker return mAsyncResult;
194*ec779b8eSAndroid Build Coastguard Worker }
195*ec779b8eSAndroid Build Coastguard Worker
setDataSource(const sp<IStreamSource> & source)196*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
197*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource(%p) stream source", this);
198*ec779b8eSAndroid Build Coastguard Worker ATRACE_BEGIN(StringPrintf("setDataSource(%p) stream source", this).c_str());
199*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
200*ec779b8eSAndroid Build Coastguard Worker
201*ec779b8eSAndroid Build Coastguard Worker if (mState != STATE_IDLE) {
202*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
203*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
204*ec779b8eSAndroid Build Coastguard Worker }
205*ec779b8eSAndroid Build Coastguard Worker
206*ec779b8eSAndroid Build Coastguard Worker mState = STATE_SET_DATASOURCE_PENDING;
207*ec779b8eSAndroid Build Coastguard Worker
208*ec779b8eSAndroid Build Coastguard Worker mPlayer->setDataSourceAsync(source);
209*ec779b8eSAndroid Build Coastguard Worker
210*ec779b8eSAndroid Build Coastguard Worker while (mState == STATE_SET_DATASOURCE_PENDING) {
211*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
212*ec779b8eSAndroid Build Coastguard Worker }
213*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
214*ec779b8eSAndroid Build Coastguard Worker
215*ec779b8eSAndroid Build Coastguard Worker return mAsyncResult;
216*ec779b8eSAndroid Build Coastguard Worker }
217*ec779b8eSAndroid Build Coastguard Worker
setDataSource(const sp<DataSource> & source)218*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(const sp<DataSource> &source) {
219*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource(%p) callback source", this);
220*ec779b8eSAndroid Build Coastguard Worker ATRACE_BEGIN(StringPrintf("setDataSource(%p) callback source", this).c_str());
221*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
222*ec779b8eSAndroid Build Coastguard Worker
223*ec779b8eSAndroid Build Coastguard Worker if (mState != STATE_IDLE) {
224*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
225*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
226*ec779b8eSAndroid Build Coastguard Worker }
227*ec779b8eSAndroid Build Coastguard Worker
228*ec779b8eSAndroid Build Coastguard Worker mState = STATE_SET_DATASOURCE_PENDING;
229*ec779b8eSAndroid Build Coastguard Worker
230*ec779b8eSAndroid Build Coastguard Worker mPlayer->setDataSourceAsync(source);
231*ec779b8eSAndroid Build Coastguard Worker
232*ec779b8eSAndroid Build Coastguard Worker while (mState == STATE_SET_DATASOURCE_PENDING) {
233*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
234*ec779b8eSAndroid Build Coastguard Worker }
235*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
236*ec779b8eSAndroid Build Coastguard Worker
237*ec779b8eSAndroid Build Coastguard Worker return mAsyncResult;
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker
setDataSource(const String8 & rtpParams)240*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setDataSource(const String8& rtpParams) {
241*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource(%p) rtp source", this);
242*ec779b8eSAndroid Build Coastguard Worker ATRACE_BEGIN(StringPrintf("setDataSource(%p) rtp source", this).c_str());
243*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
244*ec779b8eSAndroid Build Coastguard Worker
245*ec779b8eSAndroid Build Coastguard Worker if (mState != STATE_IDLE) {
246*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
247*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
248*ec779b8eSAndroid Build Coastguard Worker }
249*ec779b8eSAndroid Build Coastguard Worker
250*ec779b8eSAndroid Build Coastguard Worker mState = STATE_SET_DATASOURCE_PENDING;
251*ec779b8eSAndroid Build Coastguard Worker
252*ec779b8eSAndroid Build Coastguard Worker mPlayer->setDataSourceAsync(rtpParams);
253*ec779b8eSAndroid Build Coastguard Worker
254*ec779b8eSAndroid Build Coastguard Worker while (mState == STATE_SET_DATASOURCE_PENDING) {
255*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
256*ec779b8eSAndroid Build Coastguard Worker }
257*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
258*ec779b8eSAndroid Build Coastguard Worker
259*ec779b8eSAndroid Build Coastguard Worker return mAsyncResult;
260*ec779b8eSAndroid Build Coastguard Worker }
261*ec779b8eSAndroid Build Coastguard Worker
262*ec779b8eSAndroid Build Coastguard Worker
setVideoSurfaceTexture(const sp<IGraphicBufferProducer> & bufferProducer)263*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setVideoSurfaceTexture(
264*ec779b8eSAndroid Build Coastguard Worker const sp<IGraphicBufferProducer> &bufferProducer) {
265*ec779b8eSAndroid Build Coastguard Worker ALOGV("setVideoSurfaceTexture(%p)", this);
266*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
267*ec779b8eSAndroid Build Coastguard Worker
268*ec779b8eSAndroid Build Coastguard Worker if (mSetSurfaceInProgress) {
269*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
270*ec779b8eSAndroid Build Coastguard Worker }
271*ec779b8eSAndroid Build Coastguard Worker
272*ec779b8eSAndroid Build Coastguard Worker switch (mState) {
273*ec779b8eSAndroid Build Coastguard Worker case STATE_SET_DATASOURCE_PENDING:
274*ec779b8eSAndroid Build Coastguard Worker case STATE_RESET_IN_PROGRESS:
275*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
276*ec779b8eSAndroid Build Coastguard Worker
277*ec779b8eSAndroid Build Coastguard Worker default:
278*ec779b8eSAndroid Build Coastguard Worker break;
279*ec779b8eSAndroid Build Coastguard Worker }
280*ec779b8eSAndroid Build Coastguard Worker
281*ec779b8eSAndroid Build Coastguard Worker mSetSurfaceInProgress = true;
282*ec779b8eSAndroid Build Coastguard Worker
283*ec779b8eSAndroid Build Coastguard Worker mPlayer->setVideoSurfaceTextureAsync(bufferProducer);
284*ec779b8eSAndroid Build Coastguard Worker
285*ec779b8eSAndroid Build Coastguard Worker while (mSetSurfaceInProgress) {
286*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
287*ec779b8eSAndroid Build Coastguard Worker }
288*ec779b8eSAndroid Build Coastguard Worker
289*ec779b8eSAndroid Build Coastguard Worker return OK;
290*ec779b8eSAndroid Build Coastguard Worker }
291*ec779b8eSAndroid Build Coastguard Worker
getBufferingSettings(BufferingSettings * buffering)292*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getBufferingSettings(BufferingSettings* buffering) {
293*ec779b8eSAndroid Build Coastguard Worker ALOGV("getBufferingSettings(%p)", this);
294*ec779b8eSAndroid Build Coastguard Worker {
295*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
296*ec779b8eSAndroid Build Coastguard Worker if (mState == STATE_IDLE) {
297*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
298*ec779b8eSAndroid Build Coastguard Worker }
299*ec779b8eSAndroid Build Coastguard Worker }
300*ec779b8eSAndroid Build Coastguard Worker
301*ec779b8eSAndroid Build Coastguard Worker return mPlayer->getBufferingSettings(buffering);
302*ec779b8eSAndroid Build Coastguard Worker }
303*ec779b8eSAndroid Build Coastguard Worker
setBufferingSettings(const BufferingSettings & buffering)304*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setBufferingSettings(const BufferingSettings& buffering) {
305*ec779b8eSAndroid Build Coastguard Worker ALOGV("setBufferingSettings(%p)", this);
306*ec779b8eSAndroid Build Coastguard Worker {
307*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
308*ec779b8eSAndroid Build Coastguard Worker if (mState == STATE_IDLE) {
309*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
310*ec779b8eSAndroid Build Coastguard Worker }
311*ec779b8eSAndroid Build Coastguard Worker }
312*ec779b8eSAndroid Build Coastguard Worker
313*ec779b8eSAndroid Build Coastguard Worker return mPlayer->setBufferingSettings(buffering);
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker
prepare()316*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::prepare() {
317*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepare(%p)", this);
318*ec779b8eSAndroid Build Coastguard Worker ATRACE_BEGIN(StringPrintf("prepare(%p)", this).c_str());
319*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
320*ec779b8eSAndroid Build Coastguard Worker status_t ret = prepare_l();
321*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
322*ec779b8eSAndroid Build Coastguard Worker return ret;
323*ec779b8eSAndroid Build Coastguard Worker }
324*ec779b8eSAndroid Build Coastguard Worker
prepare_l()325*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::prepare_l() {
326*ec779b8eSAndroid Build Coastguard Worker switch (mState) {
327*ec779b8eSAndroid Build Coastguard Worker case STATE_UNPREPARED:
328*ec779b8eSAndroid Build Coastguard Worker mState = STATE_PREPARING;
329*ec779b8eSAndroid Build Coastguard Worker
330*ec779b8eSAndroid Build Coastguard Worker // Make sure we're not posting any notifications, success or
331*ec779b8eSAndroid Build Coastguard Worker // failure information is only communicated through our result
332*ec779b8eSAndroid Build Coastguard Worker // code.
333*ec779b8eSAndroid Build Coastguard Worker mIsAsyncPrepare = false;
334*ec779b8eSAndroid Build Coastguard Worker mPlayer->prepareAsync();
335*ec779b8eSAndroid Build Coastguard Worker while (mState == STATE_PREPARING) {
336*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
337*ec779b8eSAndroid Build Coastguard Worker }
338*ec779b8eSAndroid Build Coastguard Worker return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR;
339*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED:
340*ec779b8eSAndroid Build Coastguard Worker // this is really just paused. handle as seek to start
341*ec779b8eSAndroid Build Coastguard Worker mAtEOS = false;
342*ec779b8eSAndroid Build Coastguard Worker mState = STATE_STOPPED_AND_PREPARING;
343*ec779b8eSAndroid Build Coastguard Worker mIsAsyncPrepare = false;
344*ec779b8eSAndroid Build Coastguard Worker mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
345*ec779b8eSAndroid Build Coastguard Worker true /* needNotify */);
346*ec779b8eSAndroid Build Coastguard Worker while (mState == STATE_STOPPED_AND_PREPARING) {
347*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
348*ec779b8eSAndroid Build Coastguard Worker }
349*ec779b8eSAndroid Build Coastguard Worker return (mState == STATE_STOPPED_AND_PREPARED) ? OK : UNKNOWN_ERROR;
350*ec779b8eSAndroid Build Coastguard Worker default:
351*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
352*ec779b8eSAndroid Build Coastguard Worker };
353*ec779b8eSAndroid Build Coastguard Worker }
354*ec779b8eSAndroid Build Coastguard Worker
prepareAsync()355*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::prepareAsync() {
356*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepareAsync(%p)", this);
357*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
358*ec779b8eSAndroid Build Coastguard Worker
359*ec779b8eSAndroid Build Coastguard Worker switch (mState) {
360*ec779b8eSAndroid Build Coastguard Worker case STATE_UNPREPARED:
361*ec779b8eSAndroid Build Coastguard Worker mState = STATE_PREPARING;
362*ec779b8eSAndroid Build Coastguard Worker mIsAsyncPrepare = true;
363*ec779b8eSAndroid Build Coastguard Worker mPlayer->prepareAsync();
364*ec779b8eSAndroid Build Coastguard Worker return OK;
365*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED:
366*ec779b8eSAndroid Build Coastguard Worker // this is really just paused. handle as seek to start
367*ec779b8eSAndroid Build Coastguard Worker mAtEOS = false;
368*ec779b8eSAndroid Build Coastguard Worker mState = STATE_STOPPED_AND_PREPARING;
369*ec779b8eSAndroid Build Coastguard Worker mIsAsyncPrepare = true;
370*ec779b8eSAndroid Build Coastguard Worker mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
371*ec779b8eSAndroid Build Coastguard Worker true /* needNotify */);
372*ec779b8eSAndroid Build Coastguard Worker return OK;
373*ec779b8eSAndroid Build Coastguard Worker default:
374*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
375*ec779b8eSAndroid Build Coastguard Worker };
376*ec779b8eSAndroid Build Coastguard Worker }
377*ec779b8eSAndroid Build Coastguard Worker
start()378*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::start() {
379*ec779b8eSAndroid Build Coastguard Worker ALOGV("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
380*ec779b8eSAndroid Build Coastguard Worker ATRACE_BEGIN(StringPrintf("start(%p), state is %d, eos is %d", this, mState, mAtEOS).c_str());
381*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
382*ec779b8eSAndroid Build Coastguard Worker status_t ret = start_l();
383*ec779b8eSAndroid Build Coastguard Worker ATRACE_END();
384*ec779b8eSAndroid Build Coastguard Worker return ret;
385*ec779b8eSAndroid Build Coastguard Worker }
386*ec779b8eSAndroid Build Coastguard Worker
start_l()387*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::start_l() {
388*ec779b8eSAndroid Build Coastguard Worker switch (mState) {
389*ec779b8eSAndroid Build Coastguard Worker case STATE_UNPREPARED:
390*ec779b8eSAndroid Build Coastguard Worker {
391*ec779b8eSAndroid Build Coastguard Worker status_t err = prepare_l();
392*ec779b8eSAndroid Build Coastguard Worker
393*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
394*ec779b8eSAndroid Build Coastguard Worker return err;
395*ec779b8eSAndroid Build Coastguard Worker }
396*ec779b8eSAndroid Build Coastguard Worker
397*ec779b8eSAndroid Build Coastguard Worker CHECK_EQ(mState, STATE_PREPARED);
398*ec779b8eSAndroid Build Coastguard Worker
399*ec779b8eSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
400*ec779b8eSAndroid Build Coastguard Worker }
401*ec779b8eSAndroid Build Coastguard Worker
402*ec779b8eSAndroid Build Coastguard Worker case STATE_PAUSED:
403*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED_AND_PREPARED:
404*ec779b8eSAndroid Build Coastguard Worker case STATE_PREPARED:
405*ec779b8eSAndroid Build Coastguard Worker {
406*ec779b8eSAndroid Build Coastguard Worker mPlayer->start();
407*ec779b8eSAndroid Build Coastguard Worker
408*ec779b8eSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
409*ec779b8eSAndroid Build Coastguard Worker }
410*ec779b8eSAndroid Build Coastguard Worker
411*ec779b8eSAndroid Build Coastguard Worker case STATE_RUNNING:
412*ec779b8eSAndroid Build Coastguard Worker {
413*ec779b8eSAndroid Build Coastguard Worker if (mAtEOS) {
414*ec779b8eSAndroid Build Coastguard Worker mPlayer->seekToAsync(0);
415*ec779b8eSAndroid Build Coastguard Worker mAtEOS = false;
416*ec779b8eSAndroid Build Coastguard Worker mPositionUs = -1;
417*ec779b8eSAndroid Build Coastguard Worker }
418*ec779b8eSAndroid Build Coastguard Worker break;
419*ec779b8eSAndroid Build Coastguard Worker }
420*ec779b8eSAndroid Build Coastguard Worker
421*ec779b8eSAndroid Build Coastguard Worker default:
422*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
423*ec779b8eSAndroid Build Coastguard Worker }
424*ec779b8eSAndroid Build Coastguard Worker
425*ec779b8eSAndroid Build Coastguard Worker mState = STATE_RUNNING;
426*ec779b8eSAndroid Build Coastguard Worker
427*ec779b8eSAndroid Build Coastguard Worker return OK;
428*ec779b8eSAndroid Build Coastguard Worker }
429*ec779b8eSAndroid Build Coastguard Worker
stop()430*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::stop() {
431*ec779b8eSAndroid Build Coastguard Worker ALOGD("stop(%p)", this);
432*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
433*ec779b8eSAndroid Build Coastguard Worker
434*ec779b8eSAndroid Build Coastguard Worker switch (mState) {
435*ec779b8eSAndroid Build Coastguard Worker case STATE_RUNNING:
436*ec779b8eSAndroid Build Coastguard Worker mPlayer->pause();
437*ec779b8eSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
438*ec779b8eSAndroid Build Coastguard Worker
439*ec779b8eSAndroid Build Coastguard Worker case STATE_PAUSED:
440*ec779b8eSAndroid Build Coastguard Worker mState = STATE_STOPPED;
441*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(MEDIA_STOPPED);
442*ec779b8eSAndroid Build Coastguard Worker break;
443*ec779b8eSAndroid Build Coastguard Worker
444*ec779b8eSAndroid Build Coastguard Worker case STATE_PREPARED:
445*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED:
446*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED_AND_PREPARING:
447*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED_AND_PREPARED:
448*ec779b8eSAndroid Build Coastguard Worker mState = STATE_STOPPED;
449*ec779b8eSAndroid Build Coastguard Worker break;
450*ec779b8eSAndroid Build Coastguard Worker
451*ec779b8eSAndroid Build Coastguard Worker default:
452*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
453*ec779b8eSAndroid Build Coastguard Worker }
454*ec779b8eSAndroid Build Coastguard Worker
455*ec779b8eSAndroid Build Coastguard Worker return OK;
456*ec779b8eSAndroid Build Coastguard Worker }
457*ec779b8eSAndroid Build Coastguard Worker
pause()458*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::pause() {
459*ec779b8eSAndroid Build Coastguard Worker ALOGD("pause(%p)", this);
460*ec779b8eSAndroid Build Coastguard Worker // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
461*ec779b8eSAndroid Build Coastguard Worker // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
462*ec779b8eSAndroid Build Coastguard Worker // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
463*ec779b8eSAndroid Build Coastguard Worker // getCurrentPosition here.
464*ec779b8eSAndroid Build Coastguard Worker int unused;
465*ec779b8eSAndroid Build Coastguard Worker getCurrentPosition(&unused);
466*ec779b8eSAndroid Build Coastguard Worker
467*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
468*ec779b8eSAndroid Build Coastguard Worker
469*ec779b8eSAndroid Build Coastguard Worker switch (mState) {
470*ec779b8eSAndroid Build Coastguard Worker case STATE_PAUSED:
471*ec779b8eSAndroid Build Coastguard Worker case STATE_PREPARED:
472*ec779b8eSAndroid Build Coastguard Worker return OK;
473*ec779b8eSAndroid Build Coastguard Worker
474*ec779b8eSAndroid Build Coastguard Worker case STATE_RUNNING:
475*ec779b8eSAndroid Build Coastguard Worker mState = STATE_PAUSED;
476*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(MEDIA_PAUSED);
477*ec779b8eSAndroid Build Coastguard Worker mPlayer->pause();
478*ec779b8eSAndroid Build Coastguard Worker break;
479*ec779b8eSAndroid Build Coastguard Worker
480*ec779b8eSAndroid Build Coastguard Worker default:
481*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
482*ec779b8eSAndroid Build Coastguard Worker }
483*ec779b8eSAndroid Build Coastguard Worker
484*ec779b8eSAndroid Build Coastguard Worker return OK;
485*ec779b8eSAndroid Build Coastguard Worker }
486*ec779b8eSAndroid Build Coastguard Worker
isPlaying()487*ec779b8eSAndroid Build Coastguard Worker bool NuPlayerDriver::isPlaying() {
488*ec779b8eSAndroid Build Coastguard Worker return mState == STATE_RUNNING && !mAtEOS;
489*ec779b8eSAndroid Build Coastguard Worker }
490*ec779b8eSAndroid Build Coastguard Worker
setPlaybackSettings(const AudioPlaybackRate & rate)491*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setPlaybackSettings(const AudioPlaybackRate &rate) {
492*ec779b8eSAndroid Build Coastguard Worker status_t err = mPlayer->setPlaybackSettings(rate);
493*ec779b8eSAndroid Build Coastguard Worker if (err == OK) {
494*ec779b8eSAndroid Build Coastguard Worker // try to update position
495*ec779b8eSAndroid Build Coastguard Worker int unused;
496*ec779b8eSAndroid Build Coastguard Worker getCurrentPosition(&unused);
497*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
498*ec779b8eSAndroid Build Coastguard Worker if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
499*ec779b8eSAndroid Build Coastguard Worker mState = STATE_PAUSED;
500*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(MEDIA_PAUSED);
501*ec779b8eSAndroid Build Coastguard Worker } else if (rate.mSpeed != 0.f
502*ec779b8eSAndroid Build Coastguard Worker && (mState == STATE_PAUSED
503*ec779b8eSAndroid Build Coastguard Worker || mState == STATE_STOPPED_AND_PREPARED
504*ec779b8eSAndroid Build Coastguard Worker || mState == STATE_PREPARED)) {
505*ec779b8eSAndroid Build Coastguard Worker err = start_l();
506*ec779b8eSAndroid Build Coastguard Worker }
507*ec779b8eSAndroid Build Coastguard Worker }
508*ec779b8eSAndroid Build Coastguard Worker return err;
509*ec779b8eSAndroid Build Coastguard Worker }
510*ec779b8eSAndroid Build Coastguard Worker
getPlaybackSettings(AudioPlaybackRate * rate)511*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getPlaybackSettings(AudioPlaybackRate *rate) {
512*ec779b8eSAndroid Build Coastguard Worker return mPlayer->getPlaybackSettings(rate);
513*ec779b8eSAndroid Build Coastguard Worker }
514*ec779b8eSAndroid Build Coastguard Worker
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)515*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
516*ec779b8eSAndroid Build Coastguard Worker return mPlayer->setSyncSettings(sync, videoFpsHint);
517*ec779b8eSAndroid Build Coastguard Worker }
518*ec779b8eSAndroid Build Coastguard Worker
getSyncSettings(AVSyncSettings * sync,float * videoFps)519*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
520*ec779b8eSAndroid Build Coastguard Worker return mPlayer->getSyncSettings(sync, videoFps);
521*ec779b8eSAndroid Build Coastguard Worker }
522*ec779b8eSAndroid Build Coastguard Worker
seekTo(int msec,MediaPlayerSeekMode mode)523*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::seekTo(int msec, MediaPlayerSeekMode mode) {
524*ec779b8eSAndroid Build Coastguard Worker ALOGV("seekTo(%p) (%d ms, %d) at state %d", this, msec, mode, mState);
525*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
526*ec779b8eSAndroid Build Coastguard Worker
527*ec779b8eSAndroid Build Coastguard Worker int64_t seekTimeUs = msec * 1000LL;
528*ec779b8eSAndroid Build Coastguard Worker
529*ec779b8eSAndroid Build Coastguard Worker switch (mState) {
530*ec779b8eSAndroid Build Coastguard Worker case STATE_PREPARED:
531*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED_AND_PREPARED:
532*ec779b8eSAndroid Build Coastguard Worker case STATE_PAUSED:
533*ec779b8eSAndroid Build Coastguard Worker case STATE_RUNNING:
534*ec779b8eSAndroid Build Coastguard Worker {
535*ec779b8eSAndroid Build Coastguard Worker mAtEOS = false;
536*ec779b8eSAndroid Build Coastguard Worker mSeekInProgress = true;
537*ec779b8eSAndroid Build Coastguard Worker // seeks can take a while, so we essentially paused
538*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(MEDIA_PAUSED);
539*ec779b8eSAndroid Build Coastguard Worker mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
540*ec779b8eSAndroid Build Coastguard Worker break;
541*ec779b8eSAndroid Build Coastguard Worker }
542*ec779b8eSAndroid Build Coastguard Worker
543*ec779b8eSAndroid Build Coastguard Worker default:
544*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
545*ec779b8eSAndroid Build Coastguard Worker }
546*ec779b8eSAndroid Build Coastguard Worker
547*ec779b8eSAndroid Build Coastguard Worker mPositionUs = seekTimeUs;
548*ec779b8eSAndroid Build Coastguard Worker return OK;
549*ec779b8eSAndroid Build Coastguard Worker }
550*ec779b8eSAndroid Build Coastguard Worker
getCurrentPosition(int * msec)551*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getCurrentPosition(int *msec) {
552*ec779b8eSAndroid Build Coastguard Worker int64_t tempUs = 0;
553*ec779b8eSAndroid Build Coastguard Worker {
554*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
555*ec779b8eSAndroid Build Coastguard Worker if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
556*ec779b8eSAndroid Build Coastguard Worker tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
557*ec779b8eSAndroid Build Coastguard Worker *msec = (int)divRound(tempUs, (int64_t)(1000));
558*ec779b8eSAndroid Build Coastguard Worker return OK;
559*ec779b8eSAndroid Build Coastguard Worker }
560*ec779b8eSAndroid Build Coastguard Worker }
561*ec779b8eSAndroid Build Coastguard Worker
562*ec779b8eSAndroid Build Coastguard Worker status_t ret = mPlayer->getCurrentPosition(&tempUs);
563*ec779b8eSAndroid Build Coastguard Worker
564*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
565*ec779b8eSAndroid Build Coastguard Worker // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
566*ec779b8eSAndroid Build Coastguard Worker // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
567*ec779b8eSAndroid Build Coastguard Worker // position value that's different the seek to position.
568*ec779b8eSAndroid Build Coastguard Worker if (ret != OK) {
569*ec779b8eSAndroid Build Coastguard Worker tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
570*ec779b8eSAndroid Build Coastguard Worker } else {
571*ec779b8eSAndroid Build Coastguard Worker mPositionUs = tempUs;
572*ec779b8eSAndroid Build Coastguard Worker }
573*ec779b8eSAndroid Build Coastguard Worker *msec = (int)divRound(tempUs, (int64_t)(1000));
574*ec779b8eSAndroid Build Coastguard Worker return OK;
575*ec779b8eSAndroid Build Coastguard Worker }
576*ec779b8eSAndroid Build Coastguard Worker
getDuration(int * msec)577*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getDuration(int *msec) {
578*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
579*ec779b8eSAndroid Build Coastguard Worker
580*ec779b8eSAndroid Build Coastguard Worker if (mDurationUs < 0) {
581*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
582*ec779b8eSAndroid Build Coastguard Worker }
583*ec779b8eSAndroid Build Coastguard Worker
584*ec779b8eSAndroid Build Coastguard Worker *msec = (mDurationUs + 500LL) / 1000;
585*ec779b8eSAndroid Build Coastguard Worker
586*ec779b8eSAndroid Build Coastguard Worker return OK;
587*ec779b8eSAndroid Build Coastguard Worker }
588*ec779b8eSAndroid Build Coastguard Worker
updateMetrics(const char * where)589*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::updateMetrics(const char *where) {
590*ec779b8eSAndroid Build Coastguard Worker
591*ec779b8eSAndroid Build Coastguard Worker if (where == NULL) {
592*ec779b8eSAndroid Build Coastguard Worker where = "unknown";
593*ec779b8eSAndroid Build Coastguard Worker }
594*ec779b8eSAndroid Build Coastguard Worker ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
595*ec779b8eSAndroid Build Coastguard Worker
596*ec779b8eSAndroid Build Coastguard Worker // avoid nested locks by gathering our data outside of the metrics lock.
597*ec779b8eSAndroid Build Coastguard Worker
598*ec779b8eSAndroid Build Coastguard Worker // final track statistics for this record
599*ec779b8eSAndroid Build Coastguard Worker Vector<sp<AMessage>> trackStats;
600*ec779b8eSAndroid Build Coastguard Worker mPlayer->getStats(&trackStats);
601*ec779b8eSAndroid Build Coastguard Worker
602*ec779b8eSAndroid Build Coastguard Worker // getDuration() uses mLock
603*ec779b8eSAndroid Build Coastguard Worker int duration_ms = -1;
604*ec779b8eSAndroid Build Coastguard Worker getDuration(&duration_ms);
605*ec779b8eSAndroid Build Coastguard Worker
606*ec779b8eSAndroid Build Coastguard Worker mPlayer->updateInternalTimers();
607*ec779b8eSAndroid Build Coastguard Worker
608*ec779b8eSAndroid Build Coastguard Worker int64_t playingTimeUs;
609*ec779b8eSAndroid Build Coastguard Worker int64_t rebufferingTimeUs;
610*ec779b8eSAndroid Build Coastguard Worker int32_t rebufferingEvents;
611*ec779b8eSAndroid Build Coastguard Worker bool rebufferingAtExit;
612*ec779b8eSAndroid Build Coastguard Worker {
613*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
614*ec779b8eSAndroid Build Coastguard Worker
615*ec779b8eSAndroid Build Coastguard Worker playingTimeUs = mPlayingTimeUs;
616*ec779b8eSAndroid Build Coastguard Worker rebufferingTimeUs = mRebufferingTimeUs;
617*ec779b8eSAndroid Build Coastguard Worker rebufferingEvents = mRebufferingEvents;
618*ec779b8eSAndroid Build Coastguard Worker rebufferingAtExit = mRebufferingAtExit;
619*ec779b8eSAndroid Build Coastguard Worker }
620*ec779b8eSAndroid Build Coastguard Worker
621*ec779b8eSAndroid Build Coastguard Worker // finish the rest of the gathering under our mutex to avoid metrics races.
622*ec779b8eSAndroid Build Coastguard Worker // some of the fields we read are updated under mLock.
623*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mMetricsLock);
624*ec779b8eSAndroid Build Coastguard Worker
625*ec779b8eSAndroid Build Coastguard Worker if (mMetricsItem == NULL) {
626*ec779b8eSAndroid Build Coastguard Worker return;
627*ec779b8eSAndroid Build Coastguard Worker }
628*ec779b8eSAndroid Build Coastguard Worker
629*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt64(kPlayerDuration, duration_ms);
630*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt64(kPlayerPlaying, (playingTimeUs+500)/1000 );
631*ec779b8eSAndroid Build Coastguard Worker
632*ec779b8eSAndroid Build Coastguard Worker if (rebufferingEvents != 0) {
633*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt64(kPlayerRebuffering, (rebufferingTimeUs+500)/1000 );
634*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt32(kPlayerRebufferingCount, rebufferingEvents);
635*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt32(kPlayerRebufferingAtExit, rebufferingAtExit);
636*ec779b8eSAndroid Build Coastguard Worker }
637*ec779b8eSAndroid Build Coastguard Worker
638*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
639*ec779b8eSAndroid Build Coastguard Worker
640*ec779b8eSAndroid Build Coastguard Worker if (trackStats.size() > 0) {
641*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < trackStats.size(); ++i) {
642*ec779b8eSAndroid Build Coastguard Worker const sp<AMessage> &stats = trackStats.itemAt(i);
643*ec779b8eSAndroid Build Coastguard Worker
644*ec779b8eSAndroid Build Coastguard Worker AString mime;
645*ec779b8eSAndroid Build Coastguard Worker stats->findString("mime", &mime);
646*ec779b8eSAndroid Build Coastguard Worker
647*ec779b8eSAndroid Build Coastguard Worker AString name;
648*ec779b8eSAndroid Build Coastguard Worker stats->findString("component-name", &name);
649*ec779b8eSAndroid Build Coastguard Worker
650*ec779b8eSAndroid Build Coastguard Worker if (mime.startsWith("video/")) {
651*ec779b8eSAndroid Build Coastguard Worker int32_t width, height;
652*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setCString(kPlayerVMime, mime.c_str());
653*ec779b8eSAndroid Build Coastguard Worker if (!name.empty()) {
654*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setCString(kPlayerVCodec, name.c_str());
655*ec779b8eSAndroid Build Coastguard Worker }
656*ec779b8eSAndroid Build Coastguard Worker
657*ec779b8eSAndroid Build Coastguard Worker if (stats->findInt32("width", &width)
658*ec779b8eSAndroid Build Coastguard Worker && stats->findInt32("height", &height)) {
659*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt32(kPlayerWidth, width);
660*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt32(kPlayerHeight, height);
661*ec779b8eSAndroid Build Coastguard Worker }
662*ec779b8eSAndroid Build Coastguard Worker
663*ec779b8eSAndroid Build Coastguard Worker int64_t numFramesTotal = 0;
664*ec779b8eSAndroid Build Coastguard Worker int64_t numFramesDropped = 0;
665*ec779b8eSAndroid Build Coastguard Worker stats->findInt64("frames-total", &numFramesTotal);
666*ec779b8eSAndroid Build Coastguard Worker stats->findInt64("frames-dropped-output", &numFramesDropped);
667*ec779b8eSAndroid Build Coastguard Worker
668*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt64(kPlayerFrames, numFramesTotal);
669*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
670*ec779b8eSAndroid Build Coastguard Worker
671*ec779b8eSAndroid Build Coastguard Worker float frameRate = 0;
672*ec779b8eSAndroid Build Coastguard Worker if (stats->findFloat("frame-rate-total", &frameRate)) {
673*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setDouble(kPlayerFrameRate, (double) frameRate);
674*ec779b8eSAndroid Build Coastguard Worker }
675*ec779b8eSAndroid Build Coastguard Worker
676*ec779b8eSAndroid Build Coastguard Worker } else if (mime.startsWith("audio/")) {
677*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setCString(kPlayerAMime, mime.c_str());
678*ec779b8eSAndroid Build Coastguard Worker if (!name.empty()) {
679*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setCString(kPlayerACodec, name.c_str());
680*ec779b8eSAndroid Build Coastguard Worker }
681*ec779b8eSAndroid Build Coastguard Worker }
682*ec779b8eSAndroid Build Coastguard Worker }
683*ec779b8eSAndroid Build Coastguard Worker }
684*ec779b8eSAndroid Build Coastguard Worker }
685*ec779b8eSAndroid Build Coastguard Worker
686*ec779b8eSAndroid Build Coastguard Worker
logMetrics(const char * where)687*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::logMetrics(const char *where) {
688*ec779b8eSAndroid Build Coastguard Worker if (where == NULL) {
689*ec779b8eSAndroid Build Coastguard Worker where = "unknown";
690*ec779b8eSAndroid Build Coastguard Worker }
691*ec779b8eSAndroid Build Coastguard Worker ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
692*ec779b8eSAndroid Build Coastguard Worker
693*ec779b8eSAndroid Build Coastguard Worker // ensure mMetricsItem stability while we write it out
694*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mMetricsLock);
695*ec779b8eSAndroid Build Coastguard Worker
696*ec779b8eSAndroid Build Coastguard Worker if (mMetricsItem == NULL || mMetricsItem->isEnabled() == false) {
697*ec779b8eSAndroid Build Coastguard Worker return;
698*ec779b8eSAndroid Build Coastguard Worker }
699*ec779b8eSAndroid Build Coastguard Worker
700*ec779b8eSAndroid Build Coastguard Worker // log only non-empty records
701*ec779b8eSAndroid Build Coastguard Worker // we always updateMetrics() before we get here
702*ec779b8eSAndroid Build Coastguard Worker // and that always injects 3 fields (duration, playing time, and
703*ec779b8eSAndroid Build Coastguard Worker // datasource) into the record.
704*ec779b8eSAndroid Build Coastguard Worker // So the canonical "empty" record has 3 elements in it.
705*ec779b8eSAndroid Build Coastguard Worker if (mMetricsItem->count() > 3) {
706*ec779b8eSAndroid Build Coastguard Worker
707*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->selfrecord();
708*ec779b8eSAndroid Build Coastguard Worker
709*ec779b8eSAndroid Build Coastguard Worker // re-init in case we prepare() and start() again.
710*ec779b8eSAndroid Build Coastguard Worker delete mMetricsItem ;
711*ec779b8eSAndroid Build Coastguard Worker mMetricsItem = mediametrics::Item::create(kKeyPlayer);
712*ec779b8eSAndroid Build Coastguard Worker if (mMetricsItem) {
713*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setUid(mClientUid);
714*ec779b8eSAndroid Build Coastguard Worker }
715*ec779b8eSAndroid Build Coastguard Worker } else {
716*ec779b8eSAndroid Build Coastguard Worker ALOGV("nothing to record (only %zu fields)", mMetricsItem->count());
717*ec779b8eSAndroid Build Coastguard Worker }
718*ec779b8eSAndroid Build Coastguard Worker }
719*ec779b8eSAndroid Build Coastguard Worker
reset()720*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::reset() {
721*ec779b8eSAndroid Build Coastguard Worker ALOGD("reset(%p) at state %d", this, mState);
722*ec779b8eSAndroid Build Coastguard Worker
723*ec779b8eSAndroid Build Coastguard Worker updateMetrics("reset");
724*ec779b8eSAndroid Build Coastguard Worker logMetrics("reset");
725*ec779b8eSAndroid Build Coastguard Worker
726*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
727*ec779b8eSAndroid Build Coastguard Worker
728*ec779b8eSAndroid Build Coastguard Worker switch (mState) {
729*ec779b8eSAndroid Build Coastguard Worker case STATE_IDLE:
730*ec779b8eSAndroid Build Coastguard Worker return OK;
731*ec779b8eSAndroid Build Coastguard Worker
732*ec779b8eSAndroid Build Coastguard Worker case STATE_SET_DATASOURCE_PENDING:
733*ec779b8eSAndroid Build Coastguard Worker case STATE_RESET_IN_PROGRESS:
734*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
735*ec779b8eSAndroid Build Coastguard Worker
736*ec779b8eSAndroid Build Coastguard Worker case STATE_PREPARING:
737*ec779b8eSAndroid Build Coastguard Worker {
738*ec779b8eSAndroid Build Coastguard Worker CHECK(mIsAsyncPrepare);
739*ec779b8eSAndroid Build Coastguard Worker
740*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(MEDIA_PREPARED);
741*ec779b8eSAndroid Build Coastguard Worker break;
742*ec779b8eSAndroid Build Coastguard Worker }
743*ec779b8eSAndroid Build Coastguard Worker
744*ec779b8eSAndroid Build Coastguard Worker default:
745*ec779b8eSAndroid Build Coastguard Worker break;
746*ec779b8eSAndroid Build Coastguard Worker }
747*ec779b8eSAndroid Build Coastguard Worker
748*ec779b8eSAndroid Build Coastguard Worker if (mState != STATE_STOPPED) {
749*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(MEDIA_STOPPED);
750*ec779b8eSAndroid Build Coastguard Worker }
751*ec779b8eSAndroid Build Coastguard Worker
752*ec779b8eSAndroid Build Coastguard Worker if (property_get_bool("persist.debug.sf.stats", false)) {
753*ec779b8eSAndroid Build Coastguard Worker Vector<String16> args;
754*ec779b8eSAndroid Build Coastguard Worker dump(-1, args);
755*ec779b8eSAndroid Build Coastguard Worker }
756*ec779b8eSAndroid Build Coastguard Worker
757*ec779b8eSAndroid Build Coastguard Worker mState = STATE_RESET_IN_PROGRESS;
758*ec779b8eSAndroid Build Coastguard Worker mPlayer->resetAsync();
759*ec779b8eSAndroid Build Coastguard Worker
760*ec779b8eSAndroid Build Coastguard Worker while (mState == STATE_RESET_IN_PROGRESS) {
761*ec779b8eSAndroid Build Coastguard Worker mCondition.wait(mLock);
762*ec779b8eSAndroid Build Coastguard Worker }
763*ec779b8eSAndroid Build Coastguard Worker
764*ec779b8eSAndroid Build Coastguard Worker mDurationUs = -1;
765*ec779b8eSAndroid Build Coastguard Worker mPositionUs = -1;
766*ec779b8eSAndroid Build Coastguard Worker mLooping = false;
767*ec779b8eSAndroid Build Coastguard Worker mPlayingTimeUs = 0;
768*ec779b8eSAndroid Build Coastguard Worker mRebufferingTimeUs = 0;
769*ec779b8eSAndroid Build Coastguard Worker mRebufferingEvents = 0;
770*ec779b8eSAndroid Build Coastguard Worker mRebufferingAtExit = false;
771*ec779b8eSAndroid Build Coastguard Worker
772*ec779b8eSAndroid Build Coastguard Worker return OK;
773*ec779b8eSAndroid Build Coastguard Worker }
774*ec779b8eSAndroid Build Coastguard Worker
notifyAt(int64_t mediaTimeUs)775*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::notifyAt(int64_t mediaTimeUs) {
776*ec779b8eSAndroid Build Coastguard Worker ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
777*ec779b8eSAndroid Build Coastguard Worker return mPlayer->notifyAt(mediaTimeUs);
778*ec779b8eSAndroid Build Coastguard Worker }
779*ec779b8eSAndroid Build Coastguard Worker
setLooping(int loop)780*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setLooping(int loop) {
781*ec779b8eSAndroid Build Coastguard Worker mLooping = loop != 0;
782*ec779b8eSAndroid Build Coastguard Worker return OK;
783*ec779b8eSAndroid Build Coastguard Worker }
784*ec779b8eSAndroid Build Coastguard Worker
playerType()785*ec779b8eSAndroid Build Coastguard Worker player_type NuPlayerDriver::playerType() {
786*ec779b8eSAndroid Build Coastguard Worker return NU_PLAYER;
787*ec779b8eSAndroid Build Coastguard Worker }
788*ec779b8eSAndroid Build Coastguard Worker
invoke(const Parcel & request,Parcel * reply)789*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
790*ec779b8eSAndroid Build Coastguard Worker if (reply == NULL) {
791*ec779b8eSAndroid Build Coastguard Worker ALOGE("reply is a NULL pointer");
792*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
793*ec779b8eSAndroid Build Coastguard Worker }
794*ec779b8eSAndroid Build Coastguard Worker
795*ec779b8eSAndroid Build Coastguard Worker int32_t methodId;
796*ec779b8eSAndroid Build Coastguard Worker status_t ret = request.readInt32(&methodId);
797*ec779b8eSAndroid Build Coastguard Worker if (ret != OK) {
798*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to retrieve the requested method to invoke");
799*ec779b8eSAndroid Build Coastguard Worker return ret;
800*ec779b8eSAndroid Build Coastguard Worker }
801*ec779b8eSAndroid Build Coastguard Worker
802*ec779b8eSAndroid Build Coastguard Worker switch (methodId) {
803*ec779b8eSAndroid Build Coastguard Worker case INVOKE_ID_SET_VIDEO_SCALING_MODE:
804*ec779b8eSAndroid Build Coastguard Worker {
805*ec779b8eSAndroid Build Coastguard Worker int mode = request.readInt32();
806*ec779b8eSAndroid Build Coastguard Worker return mPlayer->setVideoScalingMode(mode);
807*ec779b8eSAndroid Build Coastguard Worker }
808*ec779b8eSAndroid Build Coastguard Worker
809*ec779b8eSAndroid Build Coastguard Worker case INVOKE_ID_GET_TRACK_INFO:
810*ec779b8eSAndroid Build Coastguard Worker {
811*ec779b8eSAndroid Build Coastguard Worker return mPlayer->getTrackInfo(reply);
812*ec779b8eSAndroid Build Coastguard Worker }
813*ec779b8eSAndroid Build Coastguard Worker
814*ec779b8eSAndroid Build Coastguard Worker case INVOKE_ID_SELECT_TRACK:
815*ec779b8eSAndroid Build Coastguard Worker {
816*ec779b8eSAndroid Build Coastguard Worker int trackIndex = request.readInt32();
817*ec779b8eSAndroid Build Coastguard Worker int msec = 0;
818*ec779b8eSAndroid Build Coastguard Worker // getCurrentPosition should always return OK
819*ec779b8eSAndroid Build Coastguard Worker getCurrentPosition(&msec);
820*ec779b8eSAndroid Build Coastguard Worker return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000LL);
821*ec779b8eSAndroid Build Coastguard Worker }
822*ec779b8eSAndroid Build Coastguard Worker
823*ec779b8eSAndroid Build Coastguard Worker case INVOKE_ID_UNSELECT_TRACK:
824*ec779b8eSAndroid Build Coastguard Worker {
825*ec779b8eSAndroid Build Coastguard Worker int trackIndex = request.readInt32();
826*ec779b8eSAndroid Build Coastguard Worker return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
827*ec779b8eSAndroid Build Coastguard Worker }
828*ec779b8eSAndroid Build Coastguard Worker
829*ec779b8eSAndroid Build Coastguard Worker case INVOKE_ID_GET_SELECTED_TRACK:
830*ec779b8eSAndroid Build Coastguard Worker {
831*ec779b8eSAndroid Build Coastguard Worker int32_t type = request.readInt32();
832*ec779b8eSAndroid Build Coastguard Worker return mPlayer->getSelectedTrack(type, reply);
833*ec779b8eSAndroid Build Coastguard Worker }
834*ec779b8eSAndroid Build Coastguard Worker
835*ec779b8eSAndroid Build Coastguard Worker case INVOKE_ID_SET_PLAYER_IID:
836*ec779b8eSAndroid Build Coastguard Worker {
837*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mAudioSinkLock);
838*ec779b8eSAndroid Build Coastguard Worker mCachedPlayerIId = request.readInt32();
839*ec779b8eSAndroid Build Coastguard Worker if (mAudioSink != nullptr) {
840*ec779b8eSAndroid Build Coastguard Worker mAudioSink->setPlayerIId(mCachedPlayerIId);
841*ec779b8eSAndroid Build Coastguard Worker }
842*ec779b8eSAndroid Build Coastguard Worker return OK;
843*ec779b8eSAndroid Build Coastguard Worker }
844*ec779b8eSAndroid Build Coastguard Worker
845*ec779b8eSAndroid Build Coastguard Worker default:
846*ec779b8eSAndroid Build Coastguard Worker {
847*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
848*ec779b8eSAndroid Build Coastguard Worker }
849*ec779b8eSAndroid Build Coastguard Worker }
850*ec779b8eSAndroid Build Coastguard Worker }
851*ec779b8eSAndroid Build Coastguard Worker
setAudioSink(const sp<AudioSink> & audioSink)852*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
853*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mAudioSinkLock);
854*ec779b8eSAndroid Build Coastguard Worker mPlayer->setAudioSink(audioSink);
855*ec779b8eSAndroid Build Coastguard Worker mAudioSink = audioSink;
856*ec779b8eSAndroid Build Coastguard Worker if (mCachedPlayerIId != PLAYER_PIID_INVALID) {
857*ec779b8eSAndroid Build Coastguard Worker mAudioSink->setPlayerIId(mCachedPlayerIId);
858*ec779b8eSAndroid Build Coastguard Worker }
859*ec779b8eSAndroid Build Coastguard Worker }
860*ec779b8eSAndroid Build Coastguard Worker
setParameter(int key,const Parcel & request)861*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::setParameter(
862*ec779b8eSAndroid Build Coastguard Worker int key, const Parcel &request ) {
863*ec779b8eSAndroid Build Coastguard Worker if (key == KEY_PARAMETER_RTP_ATTRIBUTES) {
864*ec779b8eSAndroid Build Coastguard Worker mPlayer->setTargetBitrate(request.readInt32());
865*ec779b8eSAndroid Build Coastguard Worker return OK;
866*ec779b8eSAndroid Build Coastguard Worker }
867*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
868*ec779b8eSAndroid Build Coastguard Worker }
869*ec779b8eSAndroid Build Coastguard Worker
getParameter(int key,Parcel * reply)870*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
871*ec779b8eSAndroid Build Coastguard Worker
872*ec779b8eSAndroid Build Coastguard Worker if (key == FOURCC('m','t','r','X')) {
873*ec779b8eSAndroid Build Coastguard Worker // mtrX -- a play on 'metrics' (not matrix)
874*ec779b8eSAndroid Build Coastguard Worker // gather current info all together, parcel it, and send it back
875*ec779b8eSAndroid Build Coastguard Worker updateMetrics("api");
876*ec779b8eSAndroid Build Coastguard Worker
877*ec779b8eSAndroid Build Coastguard Worker // ensure mMetricsItem stability while writing to parcel
878*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mMetricsLock);
879*ec779b8eSAndroid Build Coastguard Worker if (mMetricsItem != NULL) {
880*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->writeToParcel(reply);
881*ec779b8eSAndroid Build Coastguard Worker }
882*ec779b8eSAndroid Build Coastguard Worker return OK;
883*ec779b8eSAndroid Build Coastguard Worker }
884*ec779b8eSAndroid Build Coastguard Worker
885*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
886*ec779b8eSAndroid Build Coastguard Worker }
887*ec779b8eSAndroid Build Coastguard Worker
getMetadata(const media::Metadata::Filter &,Parcel * records)888*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::getMetadata(
889*ec779b8eSAndroid Build Coastguard Worker const media::Metadata::Filter& /* ids */, Parcel *records) {
890*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
891*ec779b8eSAndroid Build Coastguard Worker
892*ec779b8eSAndroid Build Coastguard Worker using media::Metadata;
893*ec779b8eSAndroid Build Coastguard Worker
894*ec779b8eSAndroid Build Coastguard Worker Metadata meta(records);
895*ec779b8eSAndroid Build Coastguard Worker
896*ec779b8eSAndroid Build Coastguard Worker meta.appendBool(
897*ec779b8eSAndroid Build Coastguard Worker Metadata::kPauseAvailable,
898*ec779b8eSAndroid Build Coastguard Worker mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
899*ec779b8eSAndroid Build Coastguard Worker
900*ec779b8eSAndroid Build Coastguard Worker meta.appendBool(
901*ec779b8eSAndroid Build Coastguard Worker Metadata::kSeekBackwardAvailable,
902*ec779b8eSAndroid Build Coastguard Worker mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
903*ec779b8eSAndroid Build Coastguard Worker
904*ec779b8eSAndroid Build Coastguard Worker meta.appendBool(
905*ec779b8eSAndroid Build Coastguard Worker Metadata::kSeekForwardAvailable,
906*ec779b8eSAndroid Build Coastguard Worker mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
907*ec779b8eSAndroid Build Coastguard Worker
908*ec779b8eSAndroid Build Coastguard Worker meta.appendBool(
909*ec779b8eSAndroid Build Coastguard Worker Metadata::kSeekAvailable,
910*ec779b8eSAndroid Build Coastguard Worker mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
911*ec779b8eSAndroid Build Coastguard Worker
912*ec779b8eSAndroid Build Coastguard Worker return OK;
913*ec779b8eSAndroid Build Coastguard Worker }
914*ec779b8eSAndroid Build Coastguard Worker
notifyResetComplete()915*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyResetComplete() {
916*ec779b8eSAndroid Build Coastguard Worker ALOGD("notifyResetComplete(%p)", this);
917*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
918*ec779b8eSAndroid Build Coastguard Worker
919*ec779b8eSAndroid Build Coastguard Worker CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
920*ec779b8eSAndroid Build Coastguard Worker mState = STATE_IDLE;
921*ec779b8eSAndroid Build Coastguard Worker mCondition.broadcast();
922*ec779b8eSAndroid Build Coastguard Worker }
923*ec779b8eSAndroid Build Coastguard Worker
notifySetSurfaceComplete()924*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifySetSurfaceComplete() {
925*ec779b8eSAndroid Build Coastguard Worker ALOGV("notifySetSurfaceComplete(%p)", this);
926*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
927*ec779b8eSAndroid Build Coastguard Worker
928*ec779b8eSAndroid Build Coastguard Worker CHECK(mSetSurfaceInProgress);
929*ec779b8eSAndroid Build Coastguard Worker mSetSurfaceInProgress = false;
930*ec779b8eSAndroid Build Coastguard Worker
931*ec779b8eSAndroid Build Coastguard Worker mCondition.broadcast();
932*ec779b8eSAndroid Build Coastguard Worker }
933*ec779b8eSAndroid Build Coastguard Worker
notifyDuration(int64_t durationUs)934*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyDuration(int64_t durationUs) {
935*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
936*ec779b8eSAndroid Build Coastguard Worker mDurationUs = durationUs;
937*ec779b8eSAndroid Build Coastguard Worker }
938*ec779b8eSAndroid Build Coastguard Worker
notifyMorePlayingTimeUs(int64_t playingUs)939*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyMorePlayingTimeUs(int64_t playingUs) {
940*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
941*ec779b8eSAndroid Build Coastguard Worker mPlayingTimeUs += playingUs;
942*ec779b8eSAndroid Build Coastguard Worker }
943*ec779b8eSAndroid Build Coastguard Worker
notifyMoreRebufferingTimeUs(int64_t rebufferingUs)944*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyMoreRebufferingTimeUs(int64_t rebufferingUs) {
945*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
946*ec779b8eSAndroid Build Coastguard Worker mRebufferingTimeUs += rebufferingUs;
947*ec779b8eSAndroid Build Coastguard Worker mRebufferingEvents++;
948*ec779b8eSAndroid Build Coastguard Worker }
949*ec779b8eSAndroid Build Coastguard Worker
notifyRebufferingWhenExit(bool status)950*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyRebufferingWhenExit(bool status) {
951*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
952*ec779b8eSAndroid Build Coastguard Worker mRebufferingAtExit = status;
953*ec779b8eSAndroid Build Coastguard Worker }
954*ec779b8eSAndroid Build Coastguard Worker
notifySeekComplete()955*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifySeekComplete() {
956*ec779b8eSAndroid Build Coastguard Worker ALOGV("notifySeekComplete(%p)", this);
957*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
958*ec779b8eSAndroid Build Coastguard Worker mSeekInProgress = false;
959*ec779b8eSAndroid Build Coastguard Worker notifySeekComplete_l();
960*ec779b8eSAndroid Build Coastguard Worker }
961*ec779b8eSAndroid Build Coastguard Worker
notifySeekComplete_l()962*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifySeekComplete_l() {
963*ec779b8eSAndroid Build Coastguard Worker bool wasSeeking = true;
964*ec779b8eSAndroid Build Coastguard Worker if (mState == STATE_STOPPED_AND_PREPARING) {
965*ec779b8eSAndroid Build Coastguard Worker wasSeeking = false;
966*ec779b8eSAndroid Build Coastguard Worker mState = STATE_STOPPED_AND_PREPARED;
967*ec779b8eSAndroid Build Coastguard Worker mCondition.broadcast();
968*ec779b8eSAndroid Build Coastguard Worker if (!mIsAsyncPrepare) {
969*ec779b8eSAndroid Build Coastguard Worker // if we are preparing synchronously, no need to notify listener
970*ec779b8eSAndroid Build Coastguard Worker return;
971*ec779b8eSAndroid Build Coastguard Worker }
972*ec779b8eSAndroid Build Coastguard Worker } else if (mState == STATE_STOPPED) {
973*ec779b8eSAndroid Build Coastguard Worker // no need to notify listener
974*ec779b8eSAndroid Build Coastguard Worker return;
975*ec779b8eSAndroid Build Coastguard Worker }
976*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED);
977*ec779b8eSAndroid Build Coastguard Worker }
978*ec779b8eSAndroid Build Coastguard Worker
dump(int fd,const Vector<String16> &) const979*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::dump(
980*ec779b8eSAndroid Build Coastguard Worker int fd, const Vector<String16> & /* args */) const {
981*ec779b8eSAndroid Build Coastguard Worker
982*ec779b8eSAndroid Build Coastguard Worker Vector<sp<AMessage> > trackStats;
983*ec779b8eSAndroid Build Coastguard Worker mPlayer->getStats(&trackStats);
984*ec779b8eSAndroid Build Coastguard Worker
985*ec779b8eSAndroid Build Coastguard Worker AString logString(" NuPlayer\n");
986*ec779b8eSAndroid Build Coastguard Worker char buf[256] = {0};
987*ec779b8eSAndroid Build Coastguard Worker
988*ec779b8eSAndroid Build Coastguard Worker bool locked = false;
989*ec779b8eSAndroid Build Coastguard Worker for (int i = 0; i < kDumpLockRetries; ++i) {
990*ec779b8eSAndroid Build Coastguard Worker if (mLock.tryLock() == NO_ERROR) {
991*ec779b8eSAndroid Build Coastguard Worker locked = true;
992*ec779b8eSAndroid Build Coastguard Worker break;
993*ec779b8eSAndroid Build Coastguard Worker }
994*ec779b8eSAndroid Build Coastguard Worker usleep(kDumpLockSleepUs);
995*ec779b8eSAndroid Build Coastguard Worker }
996*ec779b8eSAndroid Build Coastguard Worker
997*ec779b8eSAndroid Build Coastguard Worker if (locked) {
998*ec779b8eSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d), ",
999*ec779b8eSAndroid Build Coastguard Worker mState, mAtEOS, mLooping, mAutoLoop);
1000*ec779b8eSAndroid Build Coastguard Worker logString.append(buf);
1001*ec779b8eSAndroid Build Coastguard Worker mPlayer->dump(logString);
1002*ec779b8eSAndroid Build Coastguard Worker logString.append("\n");
1003*ec779b8eSAndroid Build Coastguard Worker mLock.unlock();
1004*ec779b8eSAndroid Build Coastguard Worker } else {
1005*ec779b8eSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
1006*ec779b8eSAndroid Build Coastguard Worker logString.append(buf);
1007*ec779b8eSAndroid Build Coastguard Worker }
1008*ec779b8eSAndroid Build Coastguard Worker
1009*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < trackStats.size(); ++i) {
1010*ec779b8eSAndroid Build Coastguard Worker const sp<AMessage> &stats = trackStats.itemAt(i);
1011*ec779b8eSAndroid Build Coastguard Worker
1012*ec779b8eSAndroid Build Coastguard Worker AString mime;
1013*ec779b8eSAndroid Build Coastguard Worker if (stats->findString("mime", &mime)) {
1014*ec779b8eSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
1015*ec779b8eSAndroid Build Coastguard Worker logString.append(buf);
1016*ec779b8eSAndroid Build Coastguard Worker }
1017*ec779b8eSAndroid Build Coastguard Worker
1018*ec779b8eSAndroid Build Coastguard Worker AString name;
1019*ec779b8eSAndroid Build Coastguard Worker if (stats->findString("component-name", &name)) {
1020*ec779b8eSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
1021*ec779b8eSAndroid Build Coastguard Worker logString.append(buf);
1022*ec779b8eSAndroid Build Coastguard Worker }
1023*ec779b8eSAndroid Build Coastguard Worker
1024*ec779b8eSAndroid Build Coastguard Worker if (mime.startsWith("video/")) {
1025*ec779b8eSAndroid Build Coastguard Worker int32_t width, height;
1026*ec779b8eSAndroid Build Coastguard Worker if (stats->findInt32("width", &width)
1027*ec779b8eSAndroid Build Coastguard Worker && stats->findInt32("height", &height)) {
1028*ec779b8eSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
1029*ec779b8eSAndroid Build Coastguard Worker logString.append(buf);
1030*ec779b8eSAndroid Build Coastguard Worker }
1031*ec779b8eSAndroid Build Coastguard Worker
1032*ec779b8eSAndroid Build Coastguard Worker int64_t numFramesTotal = 0;
1033*ec779b8eSAndroid Build Coastguard Worker int64_t numFramesDropped = 0;
1034*ec779b8eSAndroid Build Coastguard Worker
1035*ec779b8eSAndroid Build Coastguard Worker stats->findInt64("frames-total", &numFramesTotal);
1036*ec779b8eSAndroid Build Coastguard Worker stats->findInt64("frames-dropped-output", &numFramesDropped);
1037*ec779b8eSAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
1038*ec779b8eSAndroid Build Coastguard Worker "percentageDropped(%.2f%%)\n",
1039*ec779b8eSAndroid Build Coastguard Worker (long long)numFramesTotal,
1040*ec779b8eSAndroid Build Coastguard Worker (long long)numFramesDropped,
1041*ec779b8eSAndroid Build Coastguard Worker numFramesTotal == 0
1042*ec779b8eSAndroid Build Coastguard Worker ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
1043*ec779b8eSAndroid Build Coastguard Worker logString.append(buf);
1044*ec779b8eSAndroid Build Coastguard Worker }
1045*ec779b8eSAndroid Build Coastguard Worker }
1046*ec779b8eSAndroid Build Coastguard Worker
1047*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s", logString.c_str());
1048*ec779b8eSAndroid Build Coastguard Worker
1049*ec779b8eSAndroid Build Coastguard Worker if (fd >= 0) {
1050*ec779b8eSAndroid Build Coastguard Worker FILE *out = fdopen(dup(fd), "w");
1051*ec779b8eSAndroid Build Coastguard Worker fprintf(out, "%s", logString.c_str());
1052*ec779b8eSAndroid Build Coastguard Worker fclose(out);
1053*ec779b8eSAndroid Build Coastguard Worker out = NULL;
1054*ec779b8eSAndroid Build Coastguard Worker }
1055*ec779b8eSAndroid Build Coastguard Worker
1056*ec779b8eSAndroid Build Coastguard Worker return OK;
1057*ec779b8eSAndroid Build Coastguard Worker }
1058*ec779b8eSAndroid Build Coastguard Worker
notifyListener(int msg,int ext1,int ext2,const Parcel * in)1059*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyListener(
1060*ec779b8eSAndroid Build Coastguard Worker int msg, int ext1, int ext2, const Parcel *in) {
1061*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
1062*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(msg, ext1, ext2, in);
1063*ec779b8eSAndroid Build Coastguard Worker }
1064*ec779b8eSAndroid Build Coastguard Worker
notifyListener_l(int msg,int ext1,int ext2,const Parcel * in)1065*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyListener_l(
1066*ec779b8eSAndroid Build Coastguard Worker int msg, int ext1, int ext2, const Parcel *in) {
1067*ec779b8eSAndroid Build Coastguard Worker ALOGV("notifyListener_l(%p), (%d, %d, %d, %d), loop setting(%d, %d)",
1068*ec779b8eSAndroid Build Coastguard Worker this, msg, ext1, ext2, (in == NULL ? -1 : (int)in->dataSize()), mAutoLoop, mLooping);
1069*ec779b8eSAndroid Build Coastguard Worker switch (msg) {
1070*ec779b8eSAndroid Build Coastguard Worker case MEDIA_PLAYBACK_COMPLETE:
1071*ec779b8eSAndroid Build Coastguard Worker {
1072*ec779b8eSAndroid Build Coastguard Worker if (mState != STATE_RESET_IN_PROGRESS) {
1073*ec779b8eSAndroid Build Coastguard Worker if (mAutoLoop) {
1074*ec779b8eSAndroid Build Coastguard Worker audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
1075*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mAudioSinkLock);
1076*ec779b8eSAndroid Build Coastguard Worker if (mAudioSink != NULL) {
1077*ec779b8eSAndroid Build Coastguard Worker streamType = mAudioSink->getAudioStreamType();
1078*ec779b8eSAndroid Build Coastguard Worker }
1079*ec779b8eSAndroid Build Coastguard Worker if (streamType == AUDIO_STREAM_NOTIFICATION) {
1080*ec779b8eSAndroid Build Coastguard Worker ALOGW("disabling auto-loop for notification");
1081*ec779b8eSAndroid Build Coastguard Worker mAutoLoop = false;
1082*ec779b8eSAndroid Build Coastguard Worker }
1083*ec779b8eSAndroid Build Coastguard Worker }
1084*ec779b8eSAndroid Build Coastguard Worker if (mLooping || mAutoLoop) {
1085*ec779b8eSAndroid Build Coastguard Worker mPlayer->seekToAsync(0);
1086*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mAudioSinkLock);
1087*ec779b8eSAndroid Build Coastguard Worker if (mAudioSink != NULL) {
1088*ec779b8eSAndroid Build Coastguard Worker // The renderer has stopped the sink at the end in order to play out
1089*ec779b8eSAndroid Build Coastguard Worker // the last little bit of audio. If we're looping, we need to restart it.
1090*ec779b8eSAndroid Build Coastguard Worker mAudioSink->start();
1091*ec779b8eSAndroid Build Coastguard Worker }
1092*ec779b8eSAndroid Build Coastguard Worker // don't send completion event when looping
1093*ec779b8eSAndroid Build Coastguard Worker return;
1094*ec779b8eSAndroid Build Coastguard Worker }
1095*ec779b8eSAndroid Build Coastguard Worker if (property_get_bool("persist.debug.sf.stats", false)) {
1096*ec779b8eSAndroid Build Coastguard Worker Vector<String16> args;
1097*ec779b8eSAndroid Build Coastguard Worker dump(-1, args);
1098*ec779b8eSAndroid Build Coastguard Worker }
1099*ec779b8eSAndroid Build Coastguard Worker mPlayer->pause();
1100*ec779b8eSAndroid Build Coastguard Worker mState = STATE_PAUSED;
1101*ec779b8eSAndroid Build Coastguard Worker }
1102*ec779b8eSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
1103*ec779b8eSAndroid Build Coastguard Worker }
1104*ec779b8eSAndroid Build Coastguard Worker
1105*ec779b8eSAndroid Build Coastguard Worker case MEDIA_ERROR:
1106*ec779b8eSAndroid Build Coastguard Worker {
1107*ec779b8eSAndroid Build Coastguard Worker // when we have an error, add it to the analytics for this playback.
1108*ec779b8eSAndroid Build Coastguard Worker // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
1109*ec779b8eSAndroid Build Coastguard Worker // [test against msg is due to fall through from previous switch value]
1110*ec779b8eSAndroid Build Coastguard Worker if (msg == MEDIA_ERROR) {
1111*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mMetricsLock);
1112*ec779b8eSAndroid Build Coastguard Worker if (mMetricsItem != NULL) {
1113*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt32(kPlayerError, ext1);
1114*ec779b8eSAndroid Build Coastguard Worker if (ext2 != 0) {
1115*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setInt32(kPlayerErrorCode, ext2);
1116*ec779b8eSAndroid Build Coastguard Worker }
1117*ec779b8eSAndroid Build Coastguard Worker mMetricsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
1118*ec779b8eSAndroid Build Coastguard Worker }
1119*ec779b8eSAndroid Build Coastguard Worker }
1120*ec779b8eSAndroid Build Coastguard Worker mAtEOS = true;
1121*ec779b8eSAndroid Build Coastguard Worker break;
1122*ec779b8eSAndroid Build Coastguard Worker }
1123*ec779b8eSAndroid Build Coastguard Worker
1124*ec779b8eSAndroid Build Coastguard Worker default:
1125*ec779b8eSAndroid Build Coastguard Worker break;
1126*ec779b8eSAndroid Build Coastguard Worker }
1127*ec779b8eSAndroid Build Coastguard Worker
1128*ec779b8eSAndroid Build Coastguard Worker mLock.unlock();
1129*ec779b8eSAndroid Build Coastguard Worker sendEvent(msg, ext1, ext2, in);
1130*ec779b8eSAndroid Build Coastguard Worker mLock.lock();
1131*ec779b8eSAndroid Build Coastguard Worker }
1132*ec779b8eSAndroid Build Coastguard Worker
notifySetDataSourceCompleted(status_t err)1133*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
1134*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
1135*ec779b8eSAndroid Build Coastguard Worker
1136*ec779b8eSAndroid Build Coastguard Worker CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
1137*ec779b8eSAndroid Build Coastguard Worker
1138*ec779b8eSAndroid Build Coastguard Worker mAsyncResult = err;
1139*ec779b8eSAndroid Build Coastguard Worker mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
1140*ec779b8eSAndroid Build Coastguard Worker mCondition.broadcast();
1141*ec779b8eSAndroid Build Coastguard Worker }
1142*ec779b8eSAndroid Build Coastguard Worker
notifyPrepareCompleted(status_t err)1143*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
1144*ec779b8eSAndroid Build Coastguard Worker ALOGV("notifyPrepareCompleted %d", err);
1145*ec779b8eSAndroid Build Coastguard Worker
1146*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
1147*ec779b8eSAndroid Build Coastguard Worker
1148*ec779b8eSAndroid Build Coastguard Worker if (mState != STATE_PREPARING) {
1149*ec779b8eSAndroid Build Coastguard Worker // We were preparing asynchronously when the client called
1150*ec779b8eSAndroid Build Coastguard Worker // reset(), we sent a premature "prepared" notification and
1151*ec779b8eSAndroid Build Coastguard Worker // then initiated the reset. This notification is stale.
1152*ec779b8eSAndroid Build Coastguard Worker CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
1153*ec779b8eSAndroid Build Coastguard Worker return;
1154*ec779b8eSAndroid Build Coastguard Worker }
1155*ec779b8eSAndroid Build Coastguard Worker
1156*ec779b8eSAndroid Build Coastguard Worker CHECK_EQ(mState, STATE_PREPARING);
1157*ec779b8eSAndroid Build Coastguard Worker
1158*ec779b8eSAndroid Build Coastguard Worker mAsyncResult = err;
1159*ec779b8eSAndroid Build Coastguard Worker
1160*ec779b8eSAndroid Build Coastguard Worker if (err == OK) {
1161*ec779b8eSAndroid Build Coastguard Worker // update state before notifying client, so that if client calls back into NuPlayerDriver
1162*ec779b8eSAndroid Build Coastguard Worker // in response, NuPlayerDriver has the right state
1163*ec779b8eSAndroid Build Coastguard Worker mState = STATE_PREPARED;
1164*ec779b8eSAndroid Build Coastguard Worker if (mIsAsyncPrepare) {
1165*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(MEDIA_PREPARED);
1166*ec779b8eSAndroid Build Coastguard Worker }
1167*ec779b8eSAndroid Build Coastguard Worker } else {
1168*ec779b8eSAndroid Build Coastguard Worker mState = STATE_UNPREPARED;
1169*ec779b8eSAndroid Build Coastguard Worker if (mIsAsyncPrepare) {
1170*ec779b8eSAndroid Build Coastguard Worker notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1171*ec779b8eSAndroid Build Coastguard Worker }
1172*ec779b8eSAndroid Build Coastguard Worker }
1173*ec779b8eSAndroid Build Coastguard Worker
1174*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta = mPlayer->getFileMeta();
1175*ec779b8eSAndroid Build Coastguard Worker int32_t loop;
1176*ec779b8eSAndroid Build Coastguard Worker if (meta != NULL
1177*ec779b8eSAndroid Build Coastguard Worker && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
1178*ec779b8eSAndroid Build Coastguard Worker mAutoLoop = true;
1179*ec779b8eSAndroid Build Coastguard Worker }
1180*ec779b8eSAndroid Build Coastguard Worker
1181*ec779b8eSAndroid Build Coastguard Worker mCondition.broadcast();
1182*ec779b8eSAndroid Build Coastguard Worker }
1183*ec779b8eSAndroid Build Coastguard Worker
notifyFlagsChanged(uint32_t flags)1184*ec779b8eSAndroid Build Coastguard Worker void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
1185*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
1186*ec779b8eSAndroid Build Coastguard Worker
1187*ec779b8eSAndroid Build Coastguard Worker mPlayerFlags = flags;
1188*ec779b8eSAndroid Build Coastguard Worker }
1189*ec779b8eSAndroid Build Coastguard Worker
1190*ec779b8eSAndroid Build Coastguard Worker // Modular DRM
prepareDrm(const uint8_t uuid[16],const Vector<uint8_t> & drmSessionId)1191*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
1192*ec779b8eSAndroid Build Coastguard Worker {
1193*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepareDrm(%p) state: %d", this, mState);
1194*ec779b8eSAndroid Build Coastguard Worker
1195*ec779b8eSAndroid Build Coastguard Worker // leaving the state verification for mediaplayer.cpp
1196*ec779b8eSAndroid Build Coastguard Worker status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
1197*ec779b8eSAndroid Build Coastguard Worker
1198*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepareDrm ret: %d", ret);
1199*ec779b8eSAndroid Build Coastguard Worker
1200*ec779b8eSAndroid Build Coastguard Worker return ret;
1201*ec779b8eSAndroid Build Coastguard Worker }
1202*ec779b8eSAndroid Build Coastguard Worker
releaseDrm()1203*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayerDriver::releaseDrm()
1204*ec779b8eSAndroid Build Coastguard Worker {
1205*ec779b8eSAndroid Build Coastguard Worker ALOGV("releaseDrm(%p) state: %d", this, mState);
1206*ec779b8eSAndroid Build Coastguard Worker
1207*ec779b8eSAndroid Build Coastguard Worker // leaving the state verification for mediaplayer.cpp
1208*ec779b8eSAndroid Build Coastguard Worker status_t ret = mPlayer->releaseDrm();
1209*ec779b8eSAndroid Build Coastguard Worker
1210*ec779b8eSAndroid Build Coastguard Worker ALOGV("releaseDrm ret: %d", ret);
1211*ec779b8eSAndroid Build Coastguard Worker
1212*ec779b8eSAndroid Build Coastguard Worker return ret;
1213*ec779b8eSAndroid Build Coastguard Worker }
1214*ec779b8eSAndroid Build Coastguard Worker
stateString(State state)1215*ec779b8eSAndroid Build Coastguard Worker std::string NuPlayerDriver::stateString(State state) {
1216*ec779b8eSAndroid Build Coastguard Worker const char *rval = NULL;
1217*ec779b8eSAndroid Build Coastguard Worker char rawbuffer[16]; // allows "%d"
1218*ec779b8eSAndroid Build Coastguard Worker
1219*ec779b8eSAndroid Build Coastguard Worker switch (state) {
1220*ec779b8eSAndroid Build Coastguard Worker case STATE_IDLE: rval = "IDLE"; break;
1221*ec779b8eSAndroid Build Coastguard Worker case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1222*ec779b8eSAndroid Build Coastguard Worker case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1223*ec779b8eSAndroid Build Coastguard Worker case STATE_PREPARING: rval = "PREPARING"; break;
1224*ec779b8eSAndroid Build Coastguard Worker case STATE_PREPARED: rval = "PREPARED"; break;
1225*ec779b8eSAndroid Build Coastguard Worker case STATE_RUNNING: rval = "RUNNING"; break;
1226*ec779b8eSAndroid Build Coastguard Worker case STATE_PAUSED: rval = "PAUSED"; break;
1227*ec779b8eSAndroid Build Coastguard Worker case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
1228*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED: rval = "STOPPED"; break;
1229*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
1230*ec779b8eSAndroid Build Coastguard Worker case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
1231*ec779b8eSAndroid Build Coastguard Worker default:
1232*ec779b8eSAndroid Build Coastguard Worker // yes, this buffer is shared and vulnerable to races
1233*ec779b8eSAndroid Build Coastguard Worker snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1234*ec779b8eSAndroid Build Coastguard Worker rval = rawbuffer;
1235*ec779b8eSAndroid Build Coastguard Worker break;
1236*ec779b8eSAndroid Build Coastguard Worker }
1237*ec779b8eSAndroid Build Coastguard Worker
1238*ec779b8eSAndroid Build Coastguard Worker return rval;
1239*ec779b8eSAndroid Build Coastguard Worker }
1240*ec779b8eSAndroid Build Coastguard Worker
1241*ec779b8eSAndroid Build Coastguard Worker } // namespace android
1242