blob: 1b661f291e03d6eb0237254ba7c3c00fc589014c [file] [log] [blame]
Wei Jia53692fa2017-12-11 10:33:46 -08001/*
2 * Copyright 2017 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//#define LOG_NDEBUG 0
18#define LOG_TAG "NuPlayer2Driver"
19#include <inttypes.h>
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -070020#include <android-base/macros.h>
Wei Jia53692fa2017-12-11 10:33:46 -080021#include <utils/Log.h>
22#include <cutils/properties.h>
23
24#include "NuPlayer2Driver.h"
25
26#include "NuPlayer2.h"
27#include "NuPlayer2Source.h"
28
Wei Jiad2bb1bd2018-02-08 09:47:37 -080029#include <media/DataSourceDesc.h>
Wei Jia53692fa2017-12-11 10:33:46 -080030#include <media/stagefright/foundation/ADebug.h>
31#include <media/stagefright/foundation/ALooper.h>
32#include <media/stagefright/foundation/AUtils.h>
33#include <media/stagefright/foundation/ByteUtils.h>
34#include <media/stagefright/MediaClock.h>
35#include <media/stagefright/MetaData.h>
36#include <media/stagefright/Utils.h>
37
38#include <media/IMediaAnalyticsService.h>
39
Dongwon Kang9f631982018-07-10 12:34:41 -070040using google::protobuf::RepeatedPtrField;
41using android::media::MediaPlayer2Proto::Value;
42
Wei Jia53692fa2017-12-11 10:33:46 -080043static const int kDumpLockRetries = 50;
44static const int kDumpLockSleepUs = 20000;
45
46namespace android {
47
Dongwon Kang41929fb2018-09-09 08:29:56 -070048struct PlayerMessageWrapper : public RefBase {
49 static sp<PlayerMessageWrapper> Create(const PlayerMessage *p) {
Wei Jiac5c79da2017-12-21 18:03:05 -080050 if (p != NULL) {
Dongwon Kang41929fb2018-09-09 08:29:56 -070051 sp<PlayerMessageWrapper> pw = new PlayerMessageWrapper();
52 pw->copyFrom(p);
53 return pw;
Wei Jiac5c79da2017-12-21 18:03:05 -080054 }
55 return NULL;
56 }
57
Dongwon Kang41929fb2018-09-09 08:29:56 -070058 const PlayerMessage *getPlayerMessage() {
59 return mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080060 }
61
62protected:
Dongwon Kang41929fb2018-09-09 08:29:56 -070063 virtual ~PlayerMessageWrapper() {
64 if (mPlayerMessage != NULL) {
65 delete mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080066 }
67 }
68
69private:
Dongwon Kang41929fb2018-09-09 08:29:56 -070070 PlayerMessageWrapper()
71 : mPlayerMessage(NULL) { }
Wei Jiac5c79da2017-12-21 18:03:05 -080072
Dongwon Kang41929fb2018-09-09 08:29:56 -070073 void copyFrom(const PlayerMessage *p) {
74 if (mPlayerMessage == NULL) {
75 mPlayerMessage = new PlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080076 }
Dongwon Kang41929fb2018-09-09 08:29:56 -070077 mPlayerMessage->CopyFrom(*p);
Wei Jiac5c79da2017-12-21 18:03:05 -080078 }
79
Dongwon Kang41929fb2018-09-09 08:29:56 -070080 PlayerMessage *mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080081};
82
Wei Jia53692fa2017-12-11 10:33:46 -080083// key for media statistics
Ray Essickee54eef2018-01-24 11:16:54 -080084static const char *kKeyPlayer = "nuplayer";
Wei Jia53692fa2017-12-11 10:33:46 -080085// attrs for media statistics
Ray Essickde15b8c2018-01-30 16:35:56 -080086 // NB: these are matched with public Java API constants defined
87 // in frameworks/base/media/java/android/media/MediaPlayer2.java
88 // These must be kept synchronized with the constants there.
Wei Jia53692fa2017-12-11 10:33:46 -080089static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
90static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
91static const char *kPlayerWidth = "android.media.mediaplayer.width";
92static const char *kPlayerHeight = "android.media.mediaplayer.height";
93static const char *kPlayerFrames = "android.media.mediaplayer.frames";
94static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
Ray Essick89269d62019-01-20 14:46:19 -080095static const char *kPlayerFrameRate = "android.media.mediaplayer.fps";
Wei Jia53692fa2017-12-11 10:33:46 -080096static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
97static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
98static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
99static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
100static const char *kPlayerError = "android.media.mediaplayer.err";
101static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
Ray Essickde15b8c2018-01-30 16:35:56 -0800102
103// NB: These are not yet exposed as public Java API constants.
Ray Essick51f4c872017-12-15 12:27:56 -0800104static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
Wei Jia53692fa2017-12-11 10:33:46 -0800105static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
106//
107static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
108static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
109static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
110
111
Dichen Zhangfc9f40f2019-01-04 14:15:28 -0800112NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context)
Wei Jia53692fa2017-12-11 10:33:46 -0800113 : mState(STATE_IDLE),
Wei Jia53692fa2017-12-11 10:33:46 -0800114 mAsyncResult(UNKNOWN_ERROR),
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800115 mSrcId(0),
Wei Jia53692fa2017-12-11 10:33:46 -0800116 mSetSurfaceInProgress(false),
117 mDurationUs(-1),
118 mPositionUs(-1),
119 mSeekInProgress(false),
120 mPlayingTimeUs(0),
121 mRebufferingTimeUs(0),
122 mRebufferingEvents(0),
123 mRebufferingAtExit(false),
124 mLooper(new ALooper),
Wei Jia12b9f4a2017-12-13 15:24:13 -0800125 mNuPlayer2Looper(new ALooper),
Wei Jia53692fa2017-12-11 10:33:46 -0800126 mMediaClock(new MediaClock),
Dichen Zhangfc9f40f2019-01-04 14:15:28 -0800127 mPlayer(new NuPlayer2(pid, uid, mMediaClock, context)),
Wei Jia53692fa2017-12-11 10:33:46 -0800128 mPlayerFlags(0),
Ray Essick89269d62019-01-20 14:46:19 -0800129 mMetricsHandle(0),
Wei Jia003fdb52018-02-06 14:44:32 -0800130 mClientUid(uid),
Wei Jia53692fa2017-12-11 10:33:46 -0800131 mAtEOS(false),
132 mLooping(false),
133 mAutoLoop(false) {
134 ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
135 mLooper->setName("NuPlayer2Driver Looper");
Wei Jia12b9f4a2017-12-13 15:24:13 -0800136 mNuPlayer2Looper->setName("NuPlayer2 Looper");
Wei Jia53692fa2017-12-11 10:33:46 -0800137
138 mMediaClock->init();
139
Ray Essick89269d62019-01-20 14:46:19 -0800140 // set up media metrics record
141 mMetricsHandle = mediametrics_create(kKeyPlayer);
142 mediametrics_setUid(mMetricsHandle, mClientUid);
Wei Jia53692fa2017-12-11 10:33:46 -0800143
Wei Jia12b9f4a2017-12-13 15:24:13 -0800144 mNuPlayer2Looper->start(
Wei Jia53692fa2017-12-11 10:33:46 -0800145 false, /* runOnCallingThread */
146 true, /* canCallJava */
147 PRIORITY_AUDIO);
148
Wei Jia12b9f4a2017-12-13 15:24:13 -0800149 mNuPlayer2Looper->registerHandler(mPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800150
151 mPlayer->setDriver(this);
152}
153
154NuPlayer2Driver::~NuPlayer2Driver() {
155 ALOGV("~NuPlayer2Driver(%p)", this);
Wei Jia12b9f4a2017-12-13 15:24:13 -0800156 mNuPlayer2Looper->stop();
Wei Jia53692fa2017-12-11 10:33:46 -0800157 mLooper->stop();
158
159 // finalize any pending metrics, usually a no-op.
160 updateMetrics("destructor");
161 logMetrics("destructor");
162
Ray Essick89269d62019-01-20 14:46:19 -0800163 mediametrics_delete(mMetricsHandle);
Wei Jia53692fa2017-12-11 10:33:46 -0800164}
165
166status_t NuPlayer2Driver::initCheck() {
Wei Jia12b9f4a2017-12-13 15:24:13 -0800167 mLooper->start(
168 false, /* runOnCallingThread */
169 true, /* canCallJava */
170 PRIORITY_AUDIO);
171
172 mLooper->registerHandler(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800173 return OK;
174}
175
Wei Jiac2636032018-02-01 09:15:25 -0800176status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jia57aeffd2018-02-15 16:01:14 -0800177 ALOGV("setDataSource(%p)", this);
Wei Jia53692fa2017-12-11 10:33:46 -0800178 Mutex::Autolock autoLock(mLock);
179
180 if (mState != STATE_IDLE) {
181 return INVALID_OPERATION;
182 }
183
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800184 mSrcId = dsd->mId;
Wei Jia53692fa2017-12-11 10:33:46 -0800185 mState = STATE_SET_DATASOURCE_PENDING;
186
Wei Jiac2636032018-02-01 09:15:25 -0800187 mPlayer->setDataSourceAsync(dsd);
Wei Jia53692fa2017-12-11 10:33:46 -0800188
189 while (mState == STATE_SET_DATASOURCE_PENDING) {
190 mCondition.wait(mLock);
191 }
192
193 return mAsyncResult;
194}
195
Wei Jia57aeffd2018-02-15 16:01:14 -0800196status_t NuPlayer2Driver::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
197 ALOGV("prepareNextDataSource(%p)", this);
198 Mutex::Autolock autoLock(mLock);
199
200 mPlayer->prepareNextDataSourceAsync(dsd);
201
202 return OK;
203}
204
205status_t NuPlayer2Driver::playNextDataSource(int64_t srcId) {
206 ALOGV("playNextDataSource(%p)", this);
207 Mutex::Autolock autoLock(mLock);
208
209 mSrcId = srcId;
210 mPlayer->playNextDataSource(srcId);
211
212 return OK;
213}
214
Wei Jia28288fb2017-12-15 13:45:29 -0800215status_t NuPlayer2Driver::setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww) {
Wei Jia53692fa2017-12-11 10:33:46 -0800216 ALOGV("setVideoSurfaceTexture(%p)", this);
217 Mutex::Autolock autoLock(mLock);
218
219 if (mSetSurfaceInProgress) {
220 return INVALID_OPERATION;
221 }
222
223 switch (mState) {
224 case STATE_SET_DATASOURCE_PENDING:
225 case STATE_RESET_IN_PROGRESS:
226 return INVALID_OPERATION;
227
228 default:
229 break;
230 }
231
232 mSetSurfaceInProgress = true;
233
Wei Jia28288fb2017-12-15 13:45:29 -0800234 mPlayer->setVideoSurfaceTextureAsync(nww);
Wei Jia53692fa2017-12-11 10:33:46 -0800235
236 while (mSetSurfaceInProgress) {
237 mCondition.wait(mLock);
238 }
239
240 return OK;
241}
242
243status_t NuPlayer2Driver::getBufferingSettings(BufferingSettings* buffering) {
244 ALOGV("getBufferingSettings(%p)", this);
245 {
246 Mutex::Autolock autoLock(mLock);
247 if (mState == STATE_IDLE) {
248 return INVALID_OPERATION;
249 }
250 }
251
252 return mPlayer->getBufferingSettings(buffering);
253}
254
255status_t NuPlayer2Driver::setBufferingSettings(const BufferingSettings& buffering) {
256 ALOGV("setBufferingSettings(%p)", this);
257 {
258 Mutex::Autolock autoLock(mLock);
259 if (mState == STATE_IDLE) {
260 return INVALID_OPERATION;
261 }
262 }
263
264 return mPlayer->setBufferingSettings(buffering);
265}
266
Wei Jia53692fa2017-12-11 10:33:46 -0800267status_t NuPlayer2Driver::prepareAsync() {
268 ALOGV("prepareAsync(%p)", this);
269 Mutex::Autolock autoLock(mLock);
270
271 switch (mState) {
272 case STATE_UNPREPARED:
273 mState = STATE_PREPARING;
Wei Jia53692fa2017-12-11 10:33:46 -0800274 mPlayer->prepareAsync();
275 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800276 default:
277 return INVALID_OPERATION;
278 };
279}
280
281status_t NuPlayer2Driver::start() {
282 ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
283 Mutex::Autolock autoLock(mLock);
284 return start_l();
285}
286
287status_t NuPlayer2Driver::start_l() {
288 switch (mState) {
Wei Jia53692fa2017-12-11 10:33:46 -0800289 case STATE_PAUSED:
Wei Jia53692fa2017-12-11 10:33:46 -0800290 case STATE_PREPARED:
291 {
292 mPlayer->start();
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700293 FALLTHROUGH_INTENDED;
Wei Jia53692fa2017-12-11 10:33:46 -0800294 }
295
296 case STATE_RUNNING:
297 {
298 if (mAtEOS) {
Wei Jiad1864f92018-10-19 12:34:56 -0700299 mPlayer->rewind();
Wei Jia53692fa2017-12-11 10:33:46 -0800300 mAtEOS = false;
301 mPositionUs = -1;
302 }
303 break;
304 }
305
306 default:
307 return INVALID_OPERATION;
308 }
309
310 mState = STATE_RUNNING;
311
312 return OK;
313}
314
Wei Jia53692fa2017-12-11 10:33:46 -0800315status_t NuPlayer2Driver::pause() {
316 ALOGD("pause(%p)", this);
317 // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
318 // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
319 // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
320 // getCurrentPosition here.
Wei Jia800fe372018-02-20 15:00:45 -0800321 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800322 getCurrentPosition(&unused);
323
324 Mutex::Autolock autoLock(mLock);
325
326 switch (mState) {
327 case STATE_PAUSED:
Wei Jia53692fa2017-12-11 10:33:46 -0800328 return OK;
329
Wei Jia6376cd52018-09-26 11:42:55 -0700330 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800331 case STATE_RUNNING:
332 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800333 mPlayer->pause();
334 break;
335
336 default:
337 return INVALID_OPERATION;
338 }
339
340 return OK;
341}
342
343bool NuPlayer2Driver::isPlaying() {
344 return mState == STATE_RUNNING && !mAtEOS;
345}
346
347status_t NuPlayer2Driver::setPlaybackSettings(const AudioPlaybackRate &rate) {
348 status_t err = mPlayer->setPlaybackSettings(rate);
349 if (err == OK) {
350 // try to update position
Wei Jia800fe372018-02-20 15:00:45 -0800351 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800352 getCurrentPosition(&unused);
Wei Jia53692fa2017-12-11 10:33:46 -0800353 }
354 return err;
355}
356
357status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
358 return mPlayer->getPlaybackSettings(rate);
359}
360
361status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
362 return mPlayer->setSyncSettings(sync, videoFpsHint);
363}
364
365status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
366 return mPlayer->getSyncSettings(sync, videoFps);
367}
368
Wei Jia800fe372018-02-20 15:00:45 -0800369status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
370 ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
Wei Jia53692fa2017-12-11 10:33:46 -0800371 Mutex::Autolock autoLock(mLock);
372
Chih-Hung Hsiehd42529d2018-12-11 13:53:10 -0800373 int64_t seekTimeUs = msec * 1000LL;
Wei Jia53692fa2017-12-11 10:33:46 -0800374
375 switch (mState) {
376 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800377 case STATE_PAUSED:
378 case STATE_RUNNING:
379 {
380 mAtEOS = false;
381 mSeekInProgress = true;
Wei Jia53692fa2017-12-11 10:33:46 -0800382 mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
383 break;
384 }
385
386 default:
387 return INVALID_OPERATION;
388 }
389
390 mPositionUs = seekTimeUs;
391 return OK;
392}
393
Wei Jia800fe372018-02-20 15:00:45 -0800394status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800395 int64_t tempUs = 0;
396 {
397 Mutex::Autolock autoLock(mLock);
398 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
399 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
Wei Jia800fe372018-02-20 15:00:45 -0800400 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800401 return OK;
402 }
403 }
404
405 status_t ret = mPlayer->getCurrentPosition(&tempUs);
406
407 Mutex::Autolock autoLock(mLock);
408 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
409 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
410 // position value that's different the seek to position.
411 if (ret != OK) {
412 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
413 } else {
414 mPositionUs = tempUs;
415 }
Wei Jia800fe372018-02-20 15:00:45 -0800416 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800417 return OK;
418}
419
Wei Jia800fe372018-02-20 15:00:45 -0800420status_t NuPlayer2Driver::getDuration(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800421 Mutex::Autolock autoLock(mLock);
422
423 if (mDurationUs < 0) {
424 return UNKNOWN_ERROR;
425 }
426
Chih-Hung Hsiehd42529d2018-12-11 13:53:10 -0800427 *msec = (mDurationUs + 500LL) / 1000;
Wei Jia53692fa2017-12-11 10:33:46 -0800428
429 return OK;
430}
431
432void NuPlayer2Driver::updateMetrics(const char *where) {
433 if (where == NULL) {
434 where = "unknown";
435 }
436 ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
437
438 // gather the final stats for this record
439 Vector<sp<AMessage>> trackStats;
440 mPlayer->getStats(&trackStats);
441
442 if (trackStats.size() > 0) {
443 for (size_t i = 0; i < trackStats.size(); ++i) {
444 const sp<AMessage> &stats = trackStats.itemAt(i);
445
446 AString mime;
447 stats->findString("mime", &mime);
448
449 AString name;
450 stats->findString("component-name", &name);
451
452 if (mime.startsWith("video/")) {
453 int32_t width, height;
Ray Essick89269d62019-01-20 14:46:19 -0800454 mediametrics_setCString(mMetricsHandle, kPlayerVMime, mime.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800455 if (!name.empty()) {
Ray Essick89269d62019-01-20 14:46:19 -0800456 mediametrics_setCString(mMetricsHandle, kPlayerVCodec, name.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800457 }
458
459 if (stats->findInt32("width", &width)
460 && stats->findInt32("height", &height)) {
Ray Essick89269d62019-01-20 14:46:19 -0800461 mediametrics_setInt32(mMetricsHandle, kPlayerWidth, width);
462 mediametrics_setInt32(mMetricsHandle, kPlayerHeight, height);
Wei Jia53692fa2017-12-11 10:33:46 -0800463 }
464
465 int64_t numFramesTotal = 0;
466 int64_t numFramesDropped = 0;
467 stats->findInt64("frames-total", &numFramesTotal);
468 stats->findInt64("frames-dropped-output", &numFramesDropped);
469
Ray Essick89269d62019-01-20 14:46:19 -0800470 mediametrics_setInt64(mMetricsHandle, kPlayerFrames, numFramesTotal);
471 mediametrics_setInt64(mMetricsHandle, kPlayerFramesDropped, numFramesDropped);
Wei Jia53692fa2017-12-11 10:33:46 -0800472
Ray Essick89269d62019-01-20 14:46:19 -0800473 float frameRate = 0;
474 if (stats->findFloat("frame-rate-output", &frameRate)) {
475 mediametrics_setInt64(mMetricsHandle, kPlayerFrameRate, frameRate);
476 }
Wei Jia53692fa2017-12-11 10:33:46 -0800477
478 } else if (mime.startsWith("audio/")) {
Ray Essick89269d62019-01-20 14:46:19 -0800479 mediametrics_setCString(mMetricsHandle, kPlayerAMime, mime.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800480 if (!name.empty()) {
Ray Essick89269d62019-01-20 14:46:19 -0800481 mediametrics_setCString(mMetricsHandle, kPlayerACodec, name.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800482 }
483 }
484 }
485 }
486
487 // always provide duration and playing time, even if they have 0/unknown values.
488
489 // getDuration() uses mLock for mutex -- careful where we use it.
Wei Jia800fe372018-02-20 15:00:45 -0800490 int64_t duration_ms = -1;
Wei Jia53692fa2017-12-11 10:33:46 -0800491 getDuration(&duration_ms);
Ray Essick89269d62019-01-20 14:46:19 -0800492 mediametrics_setInt64(mMetricsHandle, kPlayerDuration, duration_ms);
Wei Jia53692fa2017-12-11 10:33:46 -0800493
Ray Essick89269d62019-01-20 14:46:19 -0800494 mediametrics_setInt64(mMetricsHandle, kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
Wei Jia53692fa2017-12-11 10:33:46 -0800495
496 if (mRebufferingEvents != 0) {
Ray Essick89269d62019-01-20 14:46:19 -0800497 mediametrics_setInt64(mMetricsHandle, kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
498 mediametrics_setInt32(mMetricsHandle, kPlayerRebufferingCount, mRebufferingEvents);
499 mediametrics_setInt32(mMetricsHandle, kPlayerRebufferingAtExit, mRebufferingAtExit);
Wei Jia53692fa2017-12-11 10:33:46 -0800500 }
501
Ray Essick89269d62019-01-20 14:46:19 -0800502 mediametrics_setCString(mMetricsHandle, kPlayerDataSourceType, mPlayer->getDataSourceType());
Wei Jia53692fa2017-12-11 10:33:46 -0800503}
504
505
506void NuPlayer2Driver::logMetrics(const char *where) {
507 if (where == NULL) {
508 where = "unknown";
509 }
510 ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
511
Ray Essick89269d62019-01-20 14:46:19 -0800512 if (mMetricsHandle == 0 || mediametrics_isEnabled() == false) {
Wei Jia53692fa2017-12-11 10:33:46 -0800513 return;
514 }
515
516 // log only non-empty records
517 // we always updateMetrics() before we get here
518 // and that always injects 3 fields (duration, playing time, and
519 // datasource) into the record.
520 // So the canonical "empty" record has 3 elements in it.
Ray Essick89269d62019-01-20 14:46:19 -0800521 if (mediametrics_count(mMetricsHandle) > 3) {
522 mediametrics_selfRecord(mMetricsHandle);
Wei Jia53692fa2017-12-11 10:33:46 -0800523 // re-init in case we prepare() and start() again.
Ray Essick89269d62019-01-20 14:46:19 -0800524 mediametrics_delete(mMetricsHandle);
525 mMetricsHandle = mediametrics_create(kKeyPlayer);
526 mediametrics_setUid(mMetricsHandle, mClientUid);
Wei Jia53692fa2017-12-11 10:33:46 -0800527 } else {
528 ALOGV("did not have anything to record");
529 }
530}
531
532status_t NuPlayer2Driver::reset() {
533 ALOGD("reset(%p) at state %d", this, mState);
534
535 updateMetrics("reset");
536 logMetrics("reset");
537
538 Mutex::Autolock autoLock(mLock);
539
540 switch (mState) {
541 case STATE_IDLE:
542 return OK;
543
544 case STATE_SET_DATASOURCE_PENDING:
545 case STATE_RESET_IN_PROGRESS:
546 return INVALID_OPERATION;
547
548 case STATE_PREPARING:
549 {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800550 notifyListener_l(mSrcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800551 break;
552 }
553
554 default:
555 break;
556 }
557
Wei Jia53692fa2017-12-11 10:33:46 -0800558 mState = STATE_RESET_IN_PROGRESS;
559 mPlayer->resetAsync();
560
561 while (mState == STATE_RESET_IN_PROGRESS) {
562 mCondition.wait(mLock);
563 }
564
565 mDurationUs = -1;
566 mPositionUs = -1;
567 mLooping = false;
568 mPlayingTimeUs = 0;
569 mRebufferingTimeUs = 0;
570 mRebufferingEvents = 0;
571 mRebufferingAtExit = false;
572
573 return OK;
574}
575
576status_t NuPlayer2Driver::notifyAt(int64_t mediaTimeUs) {
577 ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
578 return mPlayer->notifyAt(mediaTimeUs);
579}
580
581status_t NuPlayer2Driver::setLooping(int loop) {
582 mLooping = loop != 0;
583 return OK;
584}
585
Dongwon Kang9f631982018-07-10 12:34:41 -0700586status_t NuPlayer2Driver::invoke(const PlayerMessage &request, PlayerMessage *response) {
587 if (response == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800588 ALOGE("reply is a NULL pointer");
589 return BAD_VALUE;
590 }
591
Dongwon Kang9f631982018-07-10 12:34:41 -0700592 RepeatedPtrField<const Value>::const_iterator it = request.values().cbegin();
593 int32_t methodId = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800594
595 switch (methodId) {
596 case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
597 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700598 int mode = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800599 return mPlayer->setVideoScalingMode(mode);
600 }
601
602 case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
603 {
Wei Jia17944af2018-12-13 18:13:10 -0800604 int64_t srcId = (it++)->int64_value();
605 return mPlayer->getTrackInfo(srcId, response);
Wei Jia53692fa2017-12-11 10:33:46 -0800606 }
607
608 case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
609 {
Wei Jia17944af2018-12-13 18:13:10 -0800610 int64_t srcId = (it++)->int64_value();
Dongwon Kang9f631982018-07-10 12:34:41 -0700611 int trackIndex = (it++)->int32_value();
Wei Jia800fe372018-02-20 15:00:45 -0800612 int64_t msec = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800613 // getCurrentPosition should always return OK
614 getCurrentPosition(&msec);
Wei Jia17944af2018-12-13 18:13:10 -0800615 return mPlayer->selectTrack(srcId, trackIndex, true /* select */, msec * 1000LL);
Wei Jia53692fa2017-12-11 10:33:46 -0800616 }
617
618 case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
619 {
Wei Jia17944af2018-12-13 18:13:10 -0800620 int64_t srcId = (it++)->int64_value();
Dongwon Kang9f631982018-07-10 12:34:41 -0700621 int trackIndex = (it++)->int32_value();
Wei Jia17944af2018-12-13 18:13:10 -0800622 return mPlayer->selectTrack(
623 srcId, trackIndex, false /* select */, 0xdeadbeef /* not used */);
Wei Jia53692fa2017-12-11 10:33:46 -0800624 }
625
626 case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
627 {
Wei Jia17944af2018-12-13 18:13:10 -0800628 int64_t srcId = (it++)->int64_value();
Dongwon Kang9f631982018-07-10 12:34:41 -0700629 int32_t type = (it++)->int32_value();
Wei Jia17944af2018-12-13 18:13:10 -0800630 return mPlayer->getSelectedTrack(srcId, type, response);
Wei Jia53692fa2017-12-11 10:33:46 -0800631 }
632
633 default:
634 {
635 return INVALID_OPERATION;
636 }
637 }
638}
639
640void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
641 mPlayer->setAudioSink(audioSink);
642 mAudioSink = audioSink;
643}
644
645status_t NuPlayer2Driver::setParameter(
646 int /* key */, const Parcel & /* request */) {
647 return INVALID_OPERATION;
648}
649
Ray Essick89269d62019-01-20 14:46:19 -0800650status_t NuPlayer2Driver::getParameter(int key __unused, Parcel *reply __unused) {
Wei Jia53692fa2017-12-11 10:33:46 -0800651 return INVALID_OPERATION;
652}
653
Ray Essick89269d62019-01-20 14:46:19 -0800654status_t NuPlayer2Driver::getMetrics(char **buffer, size_t *length) {
655 updateMetrics("api");
656 if (mediametrics_getAttributes(mMetricsHandle, buffer, length))
657 return OK;
658 else
659 return FAILED_TRANSACTION;
660}
661
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800662void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800663 ALOGD("notifyResetComplete(%p)", this);
664 Mutex::Autolock autoLock(mLock);
665
666 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
667 mState = STATE_IDLE;
668 mCondition.broadcast();
669}
670
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800671void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800672 ALOGV("notifySetSurfaceComplete(%p)", this);
673 Mutex::Autolock autoLock(mLock);
674
675 CHECK(mSetSurfaceInProgress);
676 mSetSurfaceInProgress = false;
677
678 mCondition.broadcast();
679}
680
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800681void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800682 Mutex::Autolock autoLock(mLock);
683 mDurationUs = durationUs;
684}
685
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800686void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800687 Mutex::Autolock autoLock(mLock);
688 mPlayingTimeUs += playingUs;
689}
690
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800691void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800692 Mutex::Autolock autoLock(mLock);
693 mRebufferingTimeUs += rebufferingUs;
694 mRebufferingEvents++;
695}
696
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800697void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
Wei Jia53692fa2017-12-11 10:33:46 -0800698 Mutex::Autolock autoLock(mLock);
699 mRebufferingAtExit = status;
700}
701
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800702void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800703 ALOGV("notifySeekComplete(%p)", this);
704 Mutex::Autolock autoLock(mLock);
705 mSeekInProgress = false;
Wei Jia0151ef42018-08-24 16:40:21 -0700706 notifyListener_l(srcId, MEDIA2_SEEK_COMPLETE);
Wei Jia53692fa2017-12-11 10:33:46 -0800707}
708
709status_t NuPlayer2Driver::dump(
710 int fd, const Vector<String16> & /* args */) const {
711
712 Vector<sp<AMessage> > trackStats;
713 mPlayer->getStats(&trackStats);
714
715 AString logString(" NuPlayer2\n");
716 char buf[256] = {0};
717
718 bool locked = false;
719 for (int i = 0; i < kDumpLockRetries; ++i) {
720 if (mLock.tryLock() == NO_ERROR) {
721 locked = true;
722 break;
723 }
724 usleep(kDumpLockSleepUs);
725 }
726
727 if (locked) {
728 snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
729 mState, mAtEOS, mLooping, mAutoLoop);
730 mLock.unlock();
731 } else {
732 snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
733 }
734 logString.append(buf);
735
736 for (size_t i = 0; i < trackStats.size(); ++i) {
737 const sp<AMessage> &stats = trackStats.itemAt(i);
738
739 AString mime;
740 if (stats->findString("mime", &mime)) {
741 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
742 logString.append(buf);
743 }
744
745 AString name;
746 if (stats->findString("component-name", &name)) {
747 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
748 logString.append(buf);
749 }
750
751 if (mime.startsWith("video/")) {
752 int32_t width, height;
753 if (stats->findInt32("width", &width)
754 && stats->findInt32("height", &height)) {
755 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
756 logString.append(buf);
757 }
758
759 int64_t numFramesTotal = 0;
760 int64_t numFramesDropped = 0;
761
762 stats->findInt64("frames-total", &numFramesTotal);
763 stats->findInt64("frames-dropped-output", &numFramesDropped);
764 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
765 "percentageDropped(%.2f%%)\n",
766 (long long)numFramesTotal,
767 (long long)numFramesDropped,
768 numFramesTotal == 0
769 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
770 logString.append(buf);
771 }
772 }
773
774 ALOGI("%s", logString.c_str());
775
776 if (fd >= 0) {
777 FILE *out = fdopen(dup(fd), "w");
778 fprintf(out, "%s", logString.c_str());
779 fclose(out);
780 out = NULL;
781 }
782
783 return OK;
784}
785
Wei Jia12b9f4a2017-12-13 15:24:13 -0800786void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
787 switch (msg->what()) {
788 case kWhatNotifyListener: {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800789 int64_t srcId;
Wei Jia12b9f4a2017-12-13 15:24:13 -0800790 int32_t msgId;
Wei Jiac5c79da2017-12-21 18:03:05 -0800791 int32_t ext1 = 0;
792 int32_t ext2 = 0;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800793 CHECK(msg->findInt64("srcId", &srcId));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800794 CHECK(msg->findInt32("messageId", &msgId));
Wei Jiac5c79da2017-12-21 18:03:05 -0800795 msg->findInt32("ext1", &ext1);
796 msg->findInt32("ext2", &ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700797 sp<PlayerMessageWrapper> in;
Wei Jiac5c79da2017-12-21 18:03:05 -0800798 sp<RefBase> obj;
Dongwon Kang41929fb2018-09-09 08:29:56 -0700799 if (msg->findObject("obj", &obj) && obj != NULL) {
800 in = static_cast<PlayerMessageWrapper *>(obj.get());
Wei Jiac5c79da2017-12-21 18:03:05 -0800801 }
Dongwon Kang41929fb2018-09-09 08:29:56 -0700802 sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getPlayerMessage()));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800803 break;
804 }
805 default:
806 break;
807 }
808}
809
Wei Jia53692fa2017-12-11 10:33:46 -0800810void NuPlayer2Driver::notifyListener(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700811 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jia53692fa2017-12-11 10:33:46 -0800812 Mutex::Autolock autoLock(mLock);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800813 notifyListener_l(srcId, msg, ext1, ext2, in);
Wei Jia53692fa2017-12-11 10:33:46 -0800814}
815
816void NuPlayer2Driver::notifyListener_l(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700817 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800818 ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
819 this, (long long)srcId, msg, ext1, ext2,
Dongwon Kang41929fb2018-09-09 08:29:56 -0700820 (in == NULL ? -1 : (int)in->ByteSize()), mAutoLoop, mLooping);
Wei Jia57aeffd2018-02-15 16:01:14 -0800821 if (srcId == mSrcId) {
822 switch (msg) {
823 case MEDIA2_PLAYBACK_COMPLETE:
824 {
825 if (mState != STATE_RESET_IN_PROGRESS) {
826 if (mAutoLoop) {
827 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
828 if (mAudioSink != NULL) {
829 streamType = mAudioSink->getAudioStreamType();
830 }
831 if (streamType == AUDIO_STREAM_NOTIFICATION) {
832 ALOGW("disabling auto-loop for notification");
833 mAutoLoop = false;
834 }
Wei Jia53692fa2017-12-11 10:33:46 -0800835 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800836 if (mLooping || mAutoLoop) {
Wei Jiad1864f92018-10-19 12:34:56 -0700837 mPlayer->rewind();
Wei Jia57aeffd2018-02-15 16:01:14 -0800838 if (mAudioSink != NULL) {
839 // The renderer has stopped the sink at the end in order to play out
840 // the last little bit of audio. In looping mode, we need to restart it.
841 mAudioSink->start();
842 }
Wei Jia9af566a2018-08-10 16:36:35 -0700843
844 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
845 notify->setInt64("srcId", srcId);
846 notify->setInt32("messageId", MEDIA2_INFO);
847 notify->setInt32("ext1", MEDIA2_INFO_DATA_SOURCE_REPEAT);
848 notify->post();
Wei Jia57aeffd2018-02-15 16:01:14 -0800849 return;
Wei Jia53692fa2017-12-11 10:33:46 -0800850 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800851 if (property_get_bool("persist.debug.sf.stats", false)) {
852 Vector<String16> args;
853 dump(-1, args);
Wei Jia53692fa2017-12-11 10:33:46 -0800854 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800855 mPlayer->pause();
856 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800857 }
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700858 FALLTHROUGH_INTENDED;
Wei Jia53692fa2017-12-11 10:33:46 -0800859 }
Wei Jia53692fa2017-12-11 10:33:46 -0800860
Wei Jia57aeffd2018-02-15 16:01:14 -0800861 case MEDIA2_ERROR:
862 {
863 // when we have an error, add it to the analytics for this playback.
864 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
865 // [test against msg is due to fall through from previous switch value]
866 if (msg == MEDIA2_ERROR) {
Ray Essick89269d62019-01-20 14:46:19 -0800867 mediametrics_setInt32(mMetricsHandle, kPlayerError, ext1);
Wei Jia57aeffd2018-02-15 16:01:14 -0800868 if (ext2 != 0) {
Ray Essick89269d62019-01-20 14:46:19 -0800869 mediametrics_setInt32(mMetricsHandle, kPlayerErrorCode, ext2);
Wei Jia57aeffd2018-02-15 16:01:14 -0800870 }
Ray Essick89269d62019-01-20 14:46:19 -0800871 mediametrics_setCString(mMetricsHandle, kPlayerErrorState, stateString(mState).c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800872 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800873 mAtEOS = true;
874 break;
Wei Jia53692fa2017-12-11 10:33:46 -0800875 }
Wei Jia53692fa2017-12-11 10:33:46 -0800876
Wei Jia57aeffd2018-02-15 16:01:14 -0800877 default:
878 break;
879 }
Wei Jia53692fa2017-12-11 10:33:46 -0800880 }
881
Wei Jiac5c79da2017-12-21 18:03:05 -0800882 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800883 notify->setInt64("srcId", srcId);
Wei Jiac5c79da2017-12-21 18:03:05 -0800884 notify->setInt32("messageId", msg);
885 notify->setInt32("ext1", ext1);
886 notify->setInt32("ext2", ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700887 notify->setObject("obj", PlayerMessageWrapper::Create((PlayerMessage*)in));
Wei Jiac5c79da2017-12-21 18:03:05 -0800888 notify->post();
Wei Jia12b9f4a2017-12-13 15:24:13 -0800889}
890
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800891void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800892 Mutex::Autolock autoLock(mLock);
893
894 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
895
896 mAsyncResult = err;
897 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
898 mCondition.broadcast();
899}
900
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800901void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800902 ALOGV("notifyPrepareCompleted %d", err);
903
904 Mutex::Autolock autoLock(mLock);
905
Wei Jia57aeffd2018-02-15 16:01:14 -0800906 if (srcId != mSrcId) {
907 if (err == OK) {
908 notifyListener_l(srcId, MEDIA2_PREPARED);
909 } else {
910 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
911 }
912 return;
913 }
914
Wei Jia53692fa2017-12-11 10:33:46 -0800915 if (mState != STATE_PREPARING) {
916 // We were preparing asynchronously when the client called
917 // reset(), we sent a premature "prepared" notification and
918 // then initiated the reset. This notification is stale.
919 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
920 return;
921 }
922
923 CHECK_EQ(mState, STATE_PREPARING);
924
925 mAsyncResult = err;
926
927 if (err == OK) {
928 // update state before notifying client, so that if client calls back into NuPlayer2Driver
929 // in response, NuPlayer2Driver has the right state
930 mState = STATE_PREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800931 notifyListener_l(srcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800932 } else {
933 mState = STATE_UNPREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800934 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
Wei Jia53692fa2017-12-11 10:33:46 -0800935 }
936
937 sp<MetaData> meta = mPlayer->getFileMeta();
938 int32_t loop;
939 if (meta != NULL
940 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
941 mAutoLoop = true;
942 }
943
944 mCondition.broadcast();
945}
946
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800947void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
Wei Jia53692fa2017-12-11 10:33:46 -0800948 Mutex::Autolock autoLock(mLock);
949
950 mPlayerFlags = flags;
951}
952
953// Modular DRM
Robert Shih3c3728d2018-12-04 17:06:36 -0800954status_t NuPlayer2Driver::prepareDrm(
955 int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
Wei Jia53692fa2017-12-11 10:33:46 -0800956{
957 ALOGV("prepareDrm(%p) state: %d", this, mState);
958
959 // leaving the state verification for mediaplayer.cpp
Robert Shih3c3728d2018-12-04 17:06:36 -0800960 status_t ret = mPlayer->prepareDrm(srcId, uuid, drmSessionId);
Wei Jia53692fa2017-12-11 10:33:46 -0800961
962 ALOGV("prepareDrm ret: %d", ret);
963
964 return ret;
965}
966
Robert Shih3c3728d2018-12-04 17:06:36 -0800967status_t NuPlayer2Driver::releaseDrm(int64_t srcId)
Wei Jia53692fa2017-12-11 10:33:46 -0800968{
969 ALOGV("releaseDrm(%p) state: %d", this, mState);
970
971 // leaving the state verification for mediaplayer.cpp
Robert Shih3c3728d2018-12-04 17:06:36 -0800972 status_t ret = mPlayer->releaseDrm(srcId);
Wei Jia53692fa2017-12-11 10:33:46 -0800973
974 ALOGV("releaseDrm ret: %d", ret);
975
976 return ret;
977}
978
Ray Essick51f4c872017-12-15 12:27:56 -0800979std::string NuPlayer2Driver::stateString(State state) {
980 const char *rval = NULL;
981 char rawbuffer[16]; // allows "%d"
982
983 switch (state) {
984 case STATE_IDLE: rval = "IDLE"; break;
985 case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
986 case STATE_UNPREPARED: rval = "UNPREPARED"; break;
987 case STATE_PREPARING: rval = "PREPARING"; break;
988 case STATE_PREPARED: rval = "PREPARED"; break;
989 case STATE_RUNNING: rval = "RUNNING"; break;
990 case STATE_PAUSED: rval = "PAUSED"; break;
991 case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
Ray Essick51f4c872017-12-15 12:27:56 -0800992 default:
993 // yes, this buffer is shared and vulnerable to races
994 snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
995 rval = rawbuffer;
996 break;
997 }
998
999 return rval;
1000}
1001
Wei Jia53692fa2017-12-11 10:33:46 -08001002} // namespace android