blob: 1876496c0ac7ae39244e3925b90ee7aad2296ee2 [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 Essick06278042019-02-12 12:20:02 -080084static const char *kKeyPlayer = "nuplayer2";
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
Ray Essick06278042019-02-12 12:20:02 -0800111static const char *kPlayerVersion = "android.media.mediaplayer.version";
112
Wei Jia53692fa2017-12-11 10:33:46 -0800113
Dichen Zhangfc9f40f2019-01-04 14:15:28 -0800114NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context)
Wei Jia53692fa2017-12-11 10:33:46 -0800115 : mState(STATE_IDLE),
Wei Jia53692fa2017-12-11 10:33:46 -0800116 mAsyncResult(UNKNOWN_ERROR),
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800117 mSrcId(0),
Wei Jia53692fa2017-12-11 10:33:46 -0800118 mSetSurfaceInProgress(false),
119 mDurationUs(-1),
120 mPositionUs(-1),
121 mSeekInProgress(false),
122 mPlayingTimeUs(0),
123 mRebufferingTimeUs(0),
124 mRebufferingEvents(0),
125 mRebufferingAtExit(false),
126 mLooper(new ALooper),
Wei Jia12b9f4a2017-12-13 15:24:13 -0800127 mNuPlayer2Looper(new ALooper),
Wei Jia53692fa2017-12-11 10:33:46 -0800128 mMediaClock(new MediaClock),
Dichen Zhangfc9f40f2019-01-04 14:15:28 -0800129 mPlayer(new NuPlayer2(pid, uid, mMediaClock, context)),
Wei Jia53692fa2017-12-11 10:33:46 -0800130 mPlayerFlags(0),
Ray Essick89269d62019-01-20 14:46:19 -0800131 mMetricsHandle(0),
Ray Essick06278042019-02-12 12:20:02 -0800132 mPlayerVersion(0),
Wei Jia003fdb52018-02-06 14:44:32 -0800133 mClientUid(uid),
Wei Jia53692fa2017-12-11 10:33:46 -0800134 mAtEOS(false),
135 mLooping(false),
136 mAutoLoop(false) {
137 ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
138 mLooper->setName("NuPlayer2Driver Looper");
Wei Jia12b9f4a2017-12-13 15:24:13 -0800139 mNuPlayer2Looper->setName("NuPlayer2 Looper");
Wei Jia53692fa2017-12-11 10:33:46 -0800140
141 mMediaClock->init();
142
Ray Essick06278042019-02-12 12:20:02 -0800143 // XXX: what version are we?
144 // Ideally, this ticks with the apk version info for the APEX packaging
145
Ray Essick89269d62019-01-20 14:46:19 -0800146 // set up media metrics record
147 mMetricsHandle = mediametrics_create(kKeyPlayer);
148 mediametrics_setUid(mMetricsHandle, mClientUid);
Ray Essick06278042019-02-12 12:20:02 -0800149 mediametrics_setInt64(mMetricsHandle, kPlayerVersion, mPlayerVersion);
Wei Jia53692fa2017-12-11 10:33:46 -0800150
Wei Jia12b9f4a2017-12-13 15:24:13 -0800151 mNuPlayer2Looper->start(
Wei Jia53692fa2017-12-11 10:33:46 -0800152 false, /* runOnCallingThread */
153 true, /* canCallJava */
154 PRIORITY_AUDIO);
155
Wei Jia12b9f4a2017-12-13 15:24:13 -0800156 mNuPlayer2Looper->registerHandler(mPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800157
158 mPlayer->setDriver(this);
159}
160
161NuPlayer2Driver::~NuPlayer2Driver() {
162 ALOGV("~NuPlayer2Driver(%p)", this);
Wei Jia12b9f4a2017-12-13 15:24:13 -0800163 mNuPlayer2Looper->stop();
Wei Jia53692fa2017-12-11 10:33:46 -0800164 mLooper->stop();
165
166 // finalize any pending metrics, usually a no-op.
167 updateMetrics("destructor");
168 logMetrics("destructor");
169
Ray Essick89269d62019-01-20 14:46:19 -0800170 mediametrics_delete(mMetricsHandle);
Wei Jia53692fa2017-12-11 10:33:46 -0800171}
172
173status_t NuPlayer2Driver::initCheck() {
Wei Jia12b9f4a2017-12-13 15:24:13 -0800174 mLooper->start(
175 false, /* runOnCallingThread */
176 true, /* canCallJava */
177 PRIORITY_AUDIO);
178
179 mLooper->registerHandler(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800180 return OK;
181}
182
Wei Jiac2636032018-02-01 09:15:25 -0800183status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jia57aeffd2018-02-15 16:01:14 -0800184 ALOGV("setDataSource(%p)", this);
Wei Jia53692fa2017-12-11 10:33:46 -0800185 Mutex::Autolock autoLock(mLock);
186
187 if (mState != STATE_IDLE) {
188 return INVALID_OPERATION;
189 }
190
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800191 mSrcId = dsd->mId;
Wei Jia53692fa2017-12-11 10:33:46 -0800192 mState = STATE_SET_DATASOURCE_PENDING;
193
Wei Jiac2636032018-02-01 09:15:25 -0800194 mPlayer->setDataSourceAsync(dsd);
Wei Jia53692fa2017-12-11 10:33:46 -0800195
196 while (mState == STATE_SET_DATASOURCE_PENDING) {
197 mCondition.wait(mLock);
198 }
199
200 return mAsyncResult;
201}
202
Wei Jia57aeffd2018-02-15 16:01:14 -0800203status_t NuPlayer2Driver::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
204 ALOGV("prepareNextDataSource(%p)", this);
205 Mutex::Autolock autoLock(mLock);
206
207 mPlayer->prepareNextDataSourceAsync(dsd);
208
209 return OK;
210}
211
212status_t NuPlayer2Driver::playNextDataSource(int64_t srcId) {
213 ALOGV("playNextDataSource(%p)", this);
214 Mutex::Autolock autoLock(mLock);
215
216 mSrcId = srcId;
217 mPlayer->playNextDataSource(srcId);
218
219 return OK;
220}
221
Wei Jia28288fb2017-12-15 13:45:29 -0800222status_t NuPlayer2Driver::setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww) {
Wei Jia53692fa2017-12-11 10:33:46 -0800223 ALOGV("setVideoSurfaceTexture(%p)", this);
224 Mutex::Autolock autoLock(mLock);
225
226 if (mSetSurfaceInProgress) {
227 return INVALID_OPERATION;
228 }
229
230 switch (mState) {
231 case STATE_SET_DATASOURCE_PENDING:
232 case STATE_RESET_IN_PROGRESS:
233 return INVALID_OPERATION;
234
235 default:
236 break;
237 }
238
239 mSetSurfaceInProgress = true;
240
Wei Jia28288fb2017-12-15 13:45:29 -0800241 mPlayer->setVideoSurfaceTextureAsync(nww);
Wei Jia53692fa2017-12-11 10:33:46 -0800242
243 while (mSetSurfaceInProgress) {
244 mCondition.wait(mLock);
245 }
246
247 return OK;
248}
249
250status_t NuPlayer2Driver::getBufferingSettings(BufferingSettings* buffering) {
251 ALOGV("getBufferingSettings(%p)", this);
252 {
253 Mutex::Autolock autoLock(mLock);
254 if (mState == STATE_IDLE) {
255 return INVALID_OPERATION;
256 }
257 }
258
259 return mPlayer->getBufferingSettings(buffering);
260}
261
262status_t NuPlayer2Driver::setBufferingSettings(const BufferingSettings& buffering) {
263 ALOGV("setBufferingSettings(%p)", this);
264 {
265 Mutex::Autolock autoLock(mLock);
266 if (mState == STATE_IDLE) {
267 return INVALID_OPERATION;
268 }
269 }
270
271 return mPlayer->setBufferingSettings(buffering);
272}
273
Wei Jia53692fa2017-12-11 10:33:46 -0800274status_t NuPlayer2Driver::prepareAsync() {
275 ALOGV("prepareAsync(%p)", this);
276 Mutex::Autolock autoLock(mLock);
277
278 switch (mState) {
279 case STATE_UNPREPARED:
280 mState = STATE_PREPARING;
Wei Jia53692fa2017-12-11 10:33:46 -0800281 mPlayer->prepareAsync();
282 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800283 default:
284 return INVALID_OPERATION;
285 };
286}
287
288status_t NuPlayer2Driver::start() {
289 ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
290 Mutex::Autolock autoLock(mLock);
291 return start_l();
292}
293
294status_t NuPlayer2Driver::start_l() {
295 switch (mState) {
Wei Jia53692fa2017-12-11 10:33:46 -0800296 case STATE_PAUSED:
Wei Jia53692fa2017-12-11 10:33:46 -0800297 case STATE_PREPARED:
298 {
299 mPlayer->start();
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700300 FALLTHROUGH_INTENDED;
Wei Jia53692fa2017-12-11 10:33:46 -0800301 }
302
303 case STATE_RUNNING:
304 {
305 if (mAtEOS) {
Wei Jiad1864f92018-10-19 12:34:56 -0700306 mPlayer->rewind();
Wei Jia53692fa2017-12-11 10:33:46 -0800307 mAtEOS = false;
308 mPositionUs = -1;
309 }
310 break;
311 }
312
313 default:
314 return INVALID_OPERATION;
315 }
316
317 mState = STATE_RUNNING;
318
319 return OK;
320}
321
Wei Jia53692fa2017-12-11 10:33:46 -0800322status_t NuPlayer2Driver::pause() {
323 ALOGD("pause(%p)", this);
324 // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
325 // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
326 // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
327 // getCurrentPosition here.
Wei Jia800fe372018-02-20 15:00:45 -0800328 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800329 getCurrentPosition(&unused);
330
331 Mutex::Autolock autoLock(mLock);
332
333 switch (mState) {
334 case STATE_PAUSED:
Wei Jia53692fa2017-12-11 10:33:46 -0800335 return OK;
336
Wei Jia6376cd52018-09-26 11:42:55 -0700337 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800338 case STATE_RUNNING:
339 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800340 mPlayer->pause();
341 break;
342
343 default:
344 return INVALID_OPERATION;
345 }
346
347 return OK;
348}
349
350bool NuPlayer2Driver::isPlaying() {
351 return mState == STATE_RUNNING && !mAtEOS;
352}
353
354status_t NuPlayer2Driver::setPlaybackSettings(const AudioPlaybackRate &rate) {
355 status_t err = mPlayer->setPlaybackSettings(rate);
356 if (err == OK) {
357 // try to update position
Wei Jia800fe372018-02-20 15:00:45 -0800358 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800359 getCurrentPosition(&unused);
Wei Jia53692fa2017-12-11 10:33:46 -0800360 }
361 return err;
362}
363
364status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
365 return mPlayer->getPlaybackSettings(rate);
366}
367
368status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
369 return mPlayer->setSyncSettings(sync, videoFpsHint);
370}
371
372status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
373 return mPlayer->getSyncSettings(sync, videoFps);
374}
375
Wei Jia800fe372018-02-20 15:00:45 -0800376status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
377 ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
Wei Jia53692fa2017-12-11 10:33:46 -0800378 Mutex::Autolock autoLock(mLock);
379
Chih-Hung Hsiehd42529d2018-12-11 13:53:10 -0800380 int64_t seekTimeUs = msec * 1000LL;
Wei Jia53692fa2017-12-11 10:33:46 -0800381
382 switch (mState) {
383 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800384 case STATE_PAUSED:
385 case STATE_RUNNING:
386 {
387 mAtEOS = false;
388 mSeekInProgress = true;
Wei Jia53692fa2017-12-11 10:33:46 -0800389 mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
390 break;
391 }
392
393 default:
394 return INVALID_OPERATION;
395 }
396
397 mPositionUs = seekTimeUs;
398 return OK;
399}
400
Wei Jia800fe372018-02-20 15:00:45 -0800401status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800402 int64_t tempUs = 0;
403 {
404 Mutex::Autolock autoLock(mLock);
405 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
406 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
Wei Jia800fe372018-02-20 15:00:45 -0800407 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800408 return OK;
409 }
410 }
411
412 status_t ret = mPlayer->getCurrentPosition(&tempUs);
413
414 Mutex::Autolock autoLock(mLock);
415 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
416 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
417 // position value that's different the seek to position.
418 if (ret != OK) {
419 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
420 } else {
421 mPositionUs = tempUs;
422 }
Wei Jia800fe372018-02-20 15:00:45 -0800423 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800424 return OK;
425}
426
Wei Jia800fe372018-02-20 15:00:45 -0800427status_t NuPlayer2Driver::getDuration(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800428 Mutex::Autolock autoLock(mLock);
429
430 if (mDurationUs < 0) {
431 return UNKNOWN_ERROR;
432 }
433
Chih-Hung Hsiehd42529d2018-12-11 13:53:10 -0800434 *msec = (mDurationUs + 500LL) / 1000;
Wei Jia53692fa2017-12-11 10:33:46 -0800435
436 return OK;
437}
438
439void NuPlayer2Driver::updateMetrics(const char *where) {
440 if (where == NULL) {
441 where = "unknown";
442 }
443 ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
444
445 // gather the final stats for this record
446 Vector<sp<AMessage>> trackStats;
447 mPlayer->getStats(&trackStats);
448
449 if (trackStats.size() > 0) {
450 for (size_t i = 0; i < trackStats.size(); ++i) {
451 const sp<AMessage> &stats = trackStats.itemAt(i);
452
453 AString mime;
454 stats->findString("mime", &mime);
455
456 AString name;
457 stats->findString("component-name", &name);
458
459 if (mime.startsWith("video/")) {
460 int32_t width, height;
Ray Essick89269d62019-01-20 14:46:19 -0800461 mediametrics_setCString(mMetricsHandle, kPlayerVMime, mime.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800462 if (!name.empty()) {
Ray Essick89269d62019-01-20 14:46:19 -0800463 mediametrics_setCString(mMetricsHandle, kPlayerVCodec, name.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800464 }
465
466 if (stats->findInt32("width", &width)
467 && stats->findInt32("height", &height)) {
Ray Essick89269d62019-01-20 14:46:19 -0800468 mediametrics_setInt32(mMetricsHandle, kPlayerWidth, width);
469 mediametrics_setInt32(mMetricsHandle, kPlayerHeight, height);
Wei Jia53692fa2017-12-11 10:33:46 -0800470 }
471
472 int64_t numFramesTotal = 0;
473 int64_t numFramesDropped = 0;
474 stats->findInt64("frames-total", &numFramesTotal);
475 stats->findInt64("frames-dropped-output", &numFramesDropped);
476
Ray Essick89269d62019-01-20 14:46:19 -0800477 mediametrics_setInt64(mMetricsHandle, kPlayerFrames, numFramesTotal);
478 mediametrics_setInt64(mMetricsHandle, kPlayerFramesDropped, numFramesDropped);
Wei Jia53692fa2017-12-11 10:33:46 -0800479
Ray Essick89269d62019-01-20 14:46:19 -0800480 float frameRate = 0;
481 if (stats->findFloat("frame-rate-output", &frameRate)) {
482 mediametrics_setInt64(mMetricsHandle, kPlayerFrameRate, frameRate);
Ray Essick06278042019-02-12 12:20:02 -0800483 }
Wei Jia53692fa2017-12-11 10:33:46 -0800484
485 } else if (mime.startsWith("audio/")) {
Ray Essick89269d62019-01-20 14:46:19 -0800486 mediametrics_setCString(mMetricsHandle, kPlayerAMime, mime.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800487 if (!name.empty()) {
Ray Essick89269d62019-01-20 14:46:19 -0800488 mediametrics_setCString(mMetricsHandle, kPlayerACodec, name.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800489 }
490 }
491 }
492 }
493
494 // always provide duration and playing time, even if they have 0/unknown values.
495
496 // getDuration() uses mLock for mutex -- careful where we use it.
Wei Jia800fe372018-02-20 15:00:45 -0800497 int64_t duration_ms = -1;
Wei Jia53692fa2017-12-11 10:33:46 -0800498 getDuration(&duration_ms);
Ray Essick89269d62019-01-20 14:46:19 -0800499 mediametrics_setInt64(mMetricsHandle, kPlayerDuration, duration_ms);
Wei Jia53692fa2017-12-11 10:33:46 -0800500
Ray Essick89269d62019-01-20 14:46:19 -0800501 mediametrics_setInt64(mMetricsHandle, kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
Wei Jia53692fa2017-12-11 10:33:46 -0800502
503 if (mRebufferingEvents != 0) {
Ray Essick89269d62019-01-20 14:46:19 -0800504 mediametrics_setInt64(mMetricsHandle, kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
505 mediametrics_setInt32(mMetricsHandle, kPlayerRebufferingCount, mRebufferingEvents);
506 mediametrics_setInt32(mMetricsHandle, kPlayerRebufferingAtExit, mRebufferingAtExit);
Wei Jia53692fa2017-12-11 10:33:46 -0800507 }
508
Ray Essick89269d62019-01-20 14:46:19 -0800509 mediametrics_setCString(mMetricsHandle, kPlayerDataSourceType, mPlayer->getDataSourceType());
Wei Jia53692fa2017-12-11 10:33:46 -0800510}
511
512
513void NuPlayer2Driver::logMetrics(const char *where) {
514 if (where == NULL) {
515 where = "unknown";
516 }
517 ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
518
Ray Essick89269d62019-01-20 14:46:19 -0800519 if (mMetricsHandle == 0 || mediametrics_isEnabled() == false) {
Wei Jia53692fa2017-12-11 10:33:46 -0800520 return;
521 }
522
523 // log only non-empty records
524 // we always updateMetrics() before we get here
525 // and that always injects 3 fields (duration, playing time, and
526 // datasource) into the record.
527 // So the canonical "empty" record has 3 elements in it.
Ray Essick89269d62019-01-20 14:46:19 -0800528 if (mediametrics_count(mMetricsHandle) > 3) {
529 mediametrics_selfRecord(mMetricsHandle);
Wei Jia53692fa2017-12-11 10:33:46 -0800530 // re-init in case we prepare() and start() again.
Ray Essick89269d62019-01-20 14:46:19 -0800531 mediametrics_delete(mMetricsHandle);
532 mMetricsHandle = mediametrics_create(kKeyPlayer);
533 mediametrics_setUid(mMetricsHandle, mClientUid);
Ray Essick06278042019-02-12 12:20:02 -0800534 mediametrics_setInt64(mMetricsHandle, kPlayerVersion, mPlayerVersion);
Wei Jia53692fa2017-12-11 10:33:46 -0800535 } else {
536 ALOGV("did not have anything to record");
537 }
538}
539
540status_t NuPlayer2Driver::reset() {
541 ALOGD("reset(%p) at state %d", this, mState);
542
543 updateMetrics("reset");
544 logMetrics("reset");
545
546 Mutex::Autolock autoLock(mLock);
547
548 switch (mState) {
549 case STATE_IDLE:
550 return OK;
551
552 case STATE_SET_DATASOURCE_PENDING:
553 case STATE_RESET_IN_PROGRESS:
554 return INVALID_OPERATION;
555
556 case STATE_PREPARING:
557 {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800558 notifyListener_l(mSrcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800559 break;
560 }
561
562 default:
563 break;
564 }
565
Wei Jia53692fa2017-12-11 10:33:46 -0800566 mState = STATE_RESET_IN_PROGRESS;
567 mPlayer->resetAsync();
568
569 while (mState == STATE_RESET_IN_PROGRESS) {
570 mCondition.wait(mLock);
571 }
572
573 mDurationUs = -1;
574 mPositionUs = -1;
575 mLooping = false;
576 mPlayingTimeUs = 0;
577 mRebufferingTimeUs = 0;
578 mRebufferingEvents = 0;
579 mRebufferingAtExit = false;
580
581 return OK;
582}
583
584status_t NuPlayer2Driver::notifyAt(int64_t mediaTimeUs) {
585 ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
586 return mPlayer->notifyAt(mediaTimeUs);
587}
588
589status_t NuPlayer2Driver::setLooping(int loop) {
590 mLooping = loop != 0;
591 return OK;
592}
593
Dongwon Kang9f631982018-07-10 12:34:41 -0700594status_t NuPlayer2Driver::invoke(const PlayerMessage &request, PlayerMessage *response) {
595 if (response == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800596 ALOGE("reply is a NULL pointer");
597 return BAD_VALUE;
598 }
599
Dongwon Kang9f631982018-07-10 12:34:41 -0700600 RepeatedPtrField<const Value>::const_iterator it = request.values().cbegin();
601 int32_t methodId = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800602
603 switch (methodId) {
604 case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
605 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700606 int mode = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800607 return mPlayer->setVideoScalingMode(mode);
608 }
609
610 case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
611 {
Wei Jia17944af2018-12-13 18:13:10 -0800612 int64_t srcId = (it++)->int64_value();
613 return mPlayer->getTrackInfo(srcId, response);
Wei Jia53692fa2017-12-11 10:33:46 -0800614 }
615
616 case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
617 {
Wei Jia17944af2018-12-13 18:13:10 -0800618 int64_t srcId = (it++)->int64_value();
Dongwon Kang9f631982018-07-10 12:34:41 -0700619 int trackIndex = (it++)->int32_value();
Wei Jia800fe372018-02-20 15:00:45 -0800620 int64_t msec = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800621 // getCurrentPosition should always return OK
622 getCurrentPosition(&msec);
Wei Jia17944af2018-12-13 18:13:10 -0800623 return mPlayer->selectTrack(srcId, trackIndex, true /* select */, msec * 1000LL);
Wei Jia53692fa2017-12-11 10:33:46 -0800624 }
625
626 case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
627 {
Wei Jia17944af2018-12-13 18:13:10 -0800628 int64_t srcId = (it++)->int64_value();
Dongwon Kang9f631982018-07-10 12:34:41 -0700629 int trackIndex = (it++)->int32_value();
Wei Jia17944af2018-12-13 18:13:10 -0800630 return mPlayer->selectTrack(
631 srcId, trackIndex, false /* select */, 0xdeadbeef /* not used */);
Wei Jia53692fa2017-12-11 10:33:46 -0800632 }
633
634 case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
635 {
Wei Jia17944af2018-12-13 18:13:10 -0800636 int64_t srcId = (it++)->int64_value();
Dongwon Kang9f631982018-07-10 12:34:41 -0700637 int32_t type = (it++)->int32_value();
Wei Jia17944af2018-12-13 18:13:10 -0800638 return mPlayer->getSelectedTrack(srcId, type, response);
Wei Jia53692fa2017-12-11 10:33:46 -0800639 }
640
641 default:
642 {
643 return INVALID_OPERATION;
644 }
645 }
646}
647
648void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
649 mPlayer->setAudioSink(audioSink);
650 mAudioSink = audioSink;
651}
652
653status_t NuPlayer2Driver::setParameter(
654 int /* key */, const Parcel & /* request */) {
655 return INVALID_OPERATION;
656}
657
Ray Essick89269d62019-01-20 14:46:19 -0800658status_t NuPlayer2Driver::getParameter(int key __unused, Parcel *reply __unused) {
Wei Jia53692fa2017-12-11 10:33:46 -0800659 return INVALID_OPERATION;
660}
661
Ray Essick89269d62019-01-20 14:46:19 -0800662status_t NuPlayer2Driver::getMetrics(char **buffer, size_t *length) {
663 updateMetrics("api");
664 if (mediametrics_getAttributes(mMetricsHandle, buffer, length))
665 return OK;
666 else
667 return FAILED_TRANSACTION;
668}
669
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800670void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800671 ALOGD("notifyResetComplete(%p)", this);
672 Mutex::Autolock autoLock(mLock);
673
674 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
675 mState = STATE_IDLE;
676 mCondition.broadcast();
677}
678
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800679void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800680 ALOGV("notifySetSurfaceComplete(%p)", this);
681 Mutex::Autolock autoLock(mLock);
682
683 CHECK(mSetSurfaceInProgress);
684 mSetSurfaceInProgress = false;
685
686 mCondition.broadcast();
687}
688
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800689void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800690 Mutex::Autolock autoLock(mLock);
691 mDurationUs = durationUs;
692}
693
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800694void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800695 Mutex::Autolock autoLock(mLock);
696 mPlayingTimeUs += playingUs;
697}
698
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800699void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800700 Mutex::Autolock autoLock(mLock);
701 mRebufferingTimeUs += rebufferingUs;
702 mRebufferingEvents++;
703}
704
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800705void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
Wei Jia53692fa2017-12-11 10:33:46 -0800706 Mutex::Autolock autoLock(mLock);
707 mRebufferingAtExit = status;
708}
709
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800710void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800711 ALOGV("notifySeekComplete(%p)", this);
712 Mutex::Autolock autoLock(mLock);
713 mSeekInProgress = false;
Wei Jia0151ef42018-08-24 16:40:21 -0700714 notifyListener_l(srcId, MEDIA2_SEEK_COMPLETE);
Wei Jia53692fa2017-12-11 10:33:46 -0800715}
716
717status_t NuPlayer2Driver::dump(
718 int fd, const Vector<String16> & /* args */) const {
719
720 Vector<sp<AMessage> > trackStats;
721 mPlayer->getStats(&trackStats);
722
723 AString logString(" NuPlayer2\n");
724 char buf[256] = {0};
725
726 bool locked = false;
727 for (int i = 0; i < kDumpLockRetries; ++i) {
728 if (mLock.tryLock() == NO_ERROR) {
729 locked = true;
730 break;
731 }
732 usleep(kDumpLockSleepUs);
733 }
734
735 if (locked) {
736 snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
737 mState, mAtEOS, mLooping, mAutoLoop);
738 mLock.unlock();
739 } else {
740 snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
741 }
742 logString.append(buf);
743
744 for (size_t i = 0; i < trackStats.size(); ++i) {
745 const sp<AMessage> &stats = trackStats.itemAt(i);
746
747 AString mime;
748 if (stats->findString("mime", &mime)) {
749 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
750 logString.append(buf);
751 }
752
753 AString name;
754 if (stats->findString("component-name", &name)) {
755 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
756 logString.append(buf);
757 }
758
759 if (mime.startsWith("video/")) {
760 int32_t width, height;
761 if (stats->findInt32("width", &width)
762 && stats->findInt32("height", &height)) {
763 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
764 logString.append(buf);
765 }
766
767 int64_t numFramesTotal = 0;
768 int64_t numFramesDropped = 0;
769
770 stats->findInt64("frames-total", &numFramesTotal);
771 stats->findInt64("frames-dropped-output", &numFramesDropped);
772 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
773 "percentageDropped(%.2f%%)\n",
774 (long long)numFramesTotal,
775 (long long)numFramesDropped,
776 numFramesTotal == 0
777 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
778 logString.append(buf);
779 }
780 }
781
782 ALOGI("%s", logString.c_str());
783
784 if (fd >= 0) {
785 FILE *out = fdopen(dup(fd), "w");
786 fprintf(out, "%s", logString.c_str());
787 fclose(out);
788 out = NULL;
789 }
790
791 return OK;
792}
793
Wei Jia12b9f4a2017-12-13 15:24:13 -0800794void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
795 switch (msg->what()) {
796 case kWhatNotifyListener: {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800797 int64_t srcId;
Wei Jia12b9f4a2017-12-13 15:24:13 -0800798 int32_t msgId;
Wei Jiac5c79da2017-12-21 18:03:05 -0800799 int32_t ext1 = 0;
800 int32_t ext2 = 0;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800801 CHECK(msg->findInt64("srcId", &srcId));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800802 CHECK(msg->findInt32("messageId", &msgId));
Wei Jiac5c79da2017-12-21 18:03:05 -0800803 msg->findInt32("ext1", &ext1);
804 msg->findInt32("ext2", &ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700805 sp<PlayerMessageWrapper> in;
Wei Jiac5c79da2017-12-21 18:03:05 -0800806 sp<RefBase> obj;
Dongwon Kang41929fb2018-09-09 08:29:56 -0700807 if (msg->findObject("obj", &obj) && obj != NULL) {
808 in = static_cast<PlayerMessageWrapper *>(obj.get());
Wei Jiac5c79da2017-12-21 18:03:05 -0800809 }
Dongwon Kang41929fb2018-09-09 08:29:56 -0700810 sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getPlayerMessage()));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800811 break;
812 }
813 default:
814 break;
815 }
816}
817
Wei Jia53692fa2017-12-11 10:33:46 -0800818void NuPlayer2Driver::notifyListener(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700819 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jia53692fa2017-12-11 10:33:46 -0800820 Mutex::Autolock autoLock(mLock);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800821 notifyListener_l(srcId, msg, ext1, ext2, in);
Wei Jia53692fa2017-12-11 10:33:46 -0800822}
823
824void NuPlayer2Driver::notifyListener_l(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700825 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800826 ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
827 this, (long long)srcId, msg, ext1, ext2,
Dongwon Kang41929fb2018-09-09 08:29:56 -0700828 (in == NULL ? -1 : (int)in->ByteSize()), mAutoLoop, mLooping);
Wei Jia57aeffd2018-02-15 16:01:14 -0800829 if (srcId == mSrcId) {
830 switch (msg) {
831 case MEDIA2_PLAYBACK_COMPLETE:
832 {
833 if (mState != STATE_RESET_IN_PROGRESS) {
834 if (mAutoLoop) {
835 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
836 if (mAudioSink != NULL) {
837 streamType = mAudioSink->getAudioStreamType();
838 }
839 if (streamType == AUDIO_STREAM_NOTIFICATION) {
840 ALOGW("disabling auto-loop for notification");
841 mAutoLoop = false;
842 }
Wei Jia53692fa2017-12-11 10:33:46 -0800843 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800844 if (mLooping || mAutoLoop) {
Wei Jiad1864f92018-10-19 12:34:56 -0700845 mPlayer->rewind();
Wei Jia57aeffd2018-02-15 16:01:14 -0800846 if (mAudioSink != NULL) {
847 // The renderer has stopped the sink at the end in order to play out
848 // the last little bit of audio. In looping mode, we need to restart it.
849 mAudioSink->start();
850 }
Wei Jia9af566a2018-08-10 16:36:35 -0700851
852 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
853 notify->setInt64("srcId", srcId);
854 notify->setInt32("messageId", MEDIA2_INFO);
855 notify->setInt32("ext1", MEDIA2_INFO_DATA_SOURCE_REPEAT);
856 notify->post();
Wei Jia57aeffd2018-02-15 16:01:14 -0800857 return;
Wei Jia53692fa2017-12-11 10:33:46 -0800858 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800859 if (property_get_bool("persist.debug.sf.stats", false)) {
860 Vector<String16> args;
861 dump(-1, args);
Wei Jia53692fa2017-12-11 10:33:46 -0800862 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800863 mPlayer->pause();
864 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800865 }
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700866 FALLTHROUGH_INTENDED;
Wei Jia53692fa2017-12-11 10:33:46 -0800867 }
Wei Jia53692fa2017-12-11 10:33:46 -0800868
Wei Jia57aeffd2018-02-15 16:01:14 -0800869 case MEDIA2_ERROR:
870 {
871 // when we have an error, add it to the analytics for this playback.
872 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
873 // [test against msg is due to fall through from previous switch value]
874 if (msg == MEDIA2_ERROR) {
Ray Essick89269d62019-01-20 14:46:19 -0800875 mediametrics_setInt32(mMetricsHandle, kPlayerError, ext1);
Wei Jia57aeffd2018-02-15 16:01:14 -0800876 if (ext2 != 0) {
Ray Essick89269d62019-01-20 14:46:19 -0800877 mediametrics_setInt32(mMetricsHandle, kPlayerErrorCode, ext2);
Wei Jia57aeffd2018-02-15 16:01:14 -0800878 }
Ray Essick89269d62019-01-20 14:46:19 -0800879 mediametrics_setCString(mMetricsHandle, kPlayerErrorState, stateString(mState).c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800880 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800881 mAtEOS = true;
882 break;
Wei Jia53692fa2017-12-11 10:33:46 -0800883 }
Wei Jia53692fa2017-12-11 10:33:46 -0800884
Wei Jia57aeffd2018-02-15 16:01:14 -0800885 default:
886 break;
887 }
Wei Jia53692fa2017-12-11 10:33:46 -0800888 }
889
Wei Jiac5c79da2017-12-21 18:03:05 -0800890 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800891 notify->setInt64("srcId", srcId);
Wei Jiac5c79da2017-12-21 18:03:05 -0800892 notify->setInt32("messageId", msg);
893 notify->setInt32("ext1", ext1);
894 notify->setInt32("ext2", ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700895 notify->setObject("obj", PlayerMessageWrapper::Create((PlayerMessage*)in));
Wei Jiac5c79da2017-12-21 18:03:05 -0800896 notify->post();
Wei Jia12b9f4a2017-12-13 15:24:13 -0800897}
898
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800899void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800900 Mutex::Autolock autoLock(mLock);
901
902 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
903
904 mAsyncResult = err;
905 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
906 mCondition.broadcast();
907}
908
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800909void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800910 ALOGV("notifyPrepareCompleted %d", err);
911
912 Mutex::Autolock autoLock(mLock);
913
Wei Jia57aeffd2018-02-15 16:01:14 -0800914 if (srcId != mSrcId) {
915 if (err == OK) {
916 notifyListener_l(srcId, MEDIA2_PREPARED);
917 } else {
918 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
919 }
920 return;
921 }
922
Wei Jia53692fa2017-12-11 10:33:46 -0800923 if (mState != STATE_PREPARING) {
924 // We were preparing asynchronously when the client called
925 // reset(), we sent a premature "prepared" notification and
926 // then initiated the reset. This notification is stale.
927 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
928 return;
929 }
930
931 CHECK_EQ(mState, STATE_PREPARING);
932
933 mAsyncResult = err;
934
935 if (err == OK) {
936 // update state before notifying client, so that if client calls back into NuPlayer2Driver
937 // in response, NuPlayer2Driver has the right state
938 mState = STATE_PREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800939 notifyListener_l(srcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800940 } else {
941 mState = STATE_UNPREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800942 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
Wei Jia53692fa2017-12-11 10:33:46 -0800943 }
944
945 sp<MetaData> meta = mPlayer->getFileMeta();
946 int32_t loop;
947 if (meta != NULL
948 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
949 mAutoLoop = true;
950 }
951
952 mCondition.broadcast();
953}
954
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800955void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
Wei Jia53692fa2017-12-11 10:33:46 -0800956 Mutex::Autolock autoLock(mLock);
957
958 mPlayerFlags = flags;
959}
960
961// Modular DRM
Robert Shih3c3728d2018-12-04 17:06:36 -0800962status_t NuPlayer2Driver::prepareDrm(
963 int64_t srcId, const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
Wei Jia53692fa2017-12-11 10:33:46 -0800964{
965 ALOGV("prepareDrm(%p) state: %d", this, mState);
966
967 // leaving the state verification for mediaplayer.cpp
Robert Shih3c3728d2018-12-04 17:06:36 -0800968 status_t ret = mPlayer->prepareDrm(srcId, uuid, drmSessionId);
Wei Jia53692fa2017-12-11 10:33:46 -0800969
970 ALOGV("prepareDrm ret: %d", ret);
971
972 return ret;
973}
974
Robert Shih3c3728d2018-12-04 17:06:36 -0800975status_t NuPlayer2Driver::releaseDrm(int64_t srcId)
Wei Jia53692fa2017-12-11 10:33:46 -0800976{
977 ALOGV("releaseDrm(%p) state: %d", this, mState);
978
979 // leaving the state verification for mediaplayer.cpp
Robert Shih3c3728d2018-12-04 17:06:36 -0800980 status_t ret = mPlayer->releaseDrm(srcId);
Wei Jia53692fa2017-12-11 10:33:46 -0800981
982 ALOGV("releaseDrm ret: %d", ret);
983
984 return ret;
985}
986
Ray Essick51f4c872017-12-15 12:27:56 -0800987std::string NuPlayer2Driver::stateString(State state) {
988 const char *rval = NULL;
989 char rawbuffer[16]; // allows "%d"
990
991 switch (state) {
992 case STATE_IDLE: rval = "IDLE"; break;
993 case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
994 case STATE_UNPREPARED: rval = "UNPREPARED"; break;
995 case STATE_PREPARING: rval = "PREPARING"; break;
996 case STATE_PREPARED: rval = "PREPARED"; break;
997 case STATE_RUNNING: rval = "RUNNING"; break;
998 case STATE_PAUSED: rval = "PAUSED"; break;
999 case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
Ray Essick51f4c872017-12-15 12:27:56 -08001000 default:
1001 // yes, this buffer is shared and vulnerable to races
1002 snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1003 rval = rawbuffer;
1004 break;
1005 }
1006
1007 return rval;
1008}
1009
Wei Jia53692fa2017-12-11 10:33:46 -08001010} // namespace android