blob: 4d799b815e4a8e4b450a78802b76d0f9b491202f [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>
20#include <utils/Log.h>
21#include <cutils/properties.h>
22
23#include "NuPlayer2Driver.h"
24
25#include "NuPlayer2.h"
26#include "NuPlayer2Source.h"
27
Wei Jiad2bb1bd2018-02-08 09:47:37 -080028#include <media/DataSourceDesc.h>
Wei Jia53692fa2017-12-11 10:33:46 -080029#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/foundation/ALooper.h>
31#include <media/stagefright/foundation/AUtils.h>
32#include <media/stagefright/foundation/ByteUtils.h>
33#include <media/stagefright/MediaClock.h>
34#include <media/stagefright/MetaData.h>
35#include <media/stagefright/Utils.h>
36
37#include <media/IMediaAnalyticsService.h>
38
Dongwon Kang9f631982018-07-10 12:34:41 -070039using google::protobuf::RepeatedPtrField;
40using android::media::MediaPlayer2Proto::Value;
41
Wei Jia53692fa2017-12-11 10:33:46 -080042static const int kDumpLockRetries = 50;
43static const int kDumpLockSleepUs = 20000;
44
45namespace android {
46
Dongwon Kang41929fb2018-09-09 08:29:56 -070047struct PlayerMessageWrapper : public RefBase {
48 static sp<PlayerMessageWrapper> Create(const PlayerMessage *p) {
Wei Jiac5c79da2017-12-21 18:03:05 -080049 if (p != NULL) {
Dongwon Kang41929fb2018-09-09 08:29:56 -070050 sp<PlayerMessageWrapper> pw = new PlayerMessageWrapper();
51 pw->copyFrom(p);
52 return pw;
Wei Jiac5c79da2017-12-21 18:03:05 -080053 }
54 return NULL;
55 }
56
Dongwon Kang41929fb2018-09-09 08:29:56 -070057 const PlayerMessage *getPlayerMessage() {
58 return mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080059 }
60
61protected:
Dongwon Kang41929fb2018-09-09 08:29:56 -070062 virtual ~PlayerMessageWrapper() {
63 if (mPlayerMessage != NULL) {
64 delete mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080065 }
66 }
67
68private:
Dongwon Kang41929fb2018-09-09 08:29:56 -070069 PlayerMessageWrapper()
70 : mPlayerMessage(NULL) { }
Wei Jiac5c79da2017-12-21 18:03:05 -080071
Dongwon Kang41929fb2018-09-09 08:29:56 -070072 void copyFrom(const PlayerMessage *p) {
73 if (mPlayerMessage == NULL) {
74 mPlayerMessage = new PlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080075 }
Dongwon Kang41929fb2018-09-09 08:29:56 -070076 mPlayerMessage->CopyFrom(*p);
Wei Jiac5c79da2017-12-21 18:03:05 -080077 }
78
Dongwon Kang41929fb2018-09-09 08:29:56 -070079 PlayerMessage *mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080080};
81
Wei Jia53692fa2017-12-11 10:33:46 -080082// key for media statistics
Ray Essickee54eef2018-01-24 11:16:54 -080083static const char *kKeyPlayer = "nuplayer";
Wei Jia53692fa2017-12-11 10:33:46 -080084// attrs for media statistics
Ray Essickde15b8c2018-01-30 16:35:56 -080085 // NB: these are matched with public Java API constants defined
86 // in frameworks/base/media/java/android/media/MediaPlayer2.java
87 // These must be kept synchronized with the constants there.
Wei Jia53692fa2017-12-11 10:33:46 -080088static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
89static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
90static const char *kPlayerWidth = "android.media.mediaplayer.width";
91static const char *kPlayerHeight = "android.media.mediaplayer.height";
92static const char *kPlayerFrames = "android.media.mediaplayer.frames";
93static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
94static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
95static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
96static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
97static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
98static const char *kPlayerError = "android.media.mediaplayer.err";
99static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
Ray Essickde15b8c2018-01-30 16:35:56 -0800100
101// NB: These are not yet exposed as public Java API constants.
Ray Essick51f4c872017-12-15 12:27:56 -0800102static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
Wei Jia53692fa2017-12-11 10:33:46 -0800103static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
104//
105static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
106static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
107static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
108
109
Wei Jia003fdb52018-02-06 14:44:32 -0800110NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid)
Wei Jia53692fa2017-12-11 10:33:46 -0800111 : mState(STATE_IDLE),
Wei Jia53692fa2017-12-11 10:33:46 -0800112 mAsyncResult(UNKNOWN_ERROR),
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800113 mSrcId(0),
Wei Jia53692fa2017-12-11 10:33:46 -0800114 mSetSurfaceInProgress(false),
115 mDurationUs(-1),
116 mPositionUs(-1),
117 mSeekInProgress(false),
118 mPlayingTimeUs(0),
119 mRebufferingTimeUs(0),
120 mRebufferingEvents(0),
121 mRebufferingAtExit(false),
122 mLooper(new ALooper),
Wei Jia12b9f4a2017-12-13 15:24:13 -0800123 mNuPlayer2Looper(new ALooper),
Wei Jia53692fa2017-12-11 10:33:46 -0800124 mMediaClock(new MediaClock),
Wei Jia003fdb52018-02-06 14:44:32 -0800125 mPlayer(new NuPlayer2(pid, uid, mMediaClock)),
Wei Jia53692fa2017-12-11 10:33:46 -0800126 mPlayerFlags(0),
127 mAnalyticsItem(NULL),
Wei Jia003fdb52018-02-06 14:44:32 -0800128 mClientUid(uid),
Wei Jia53692fa2017-12-11 10:33:46 -0800129 mAtEOS(false),
130 mLooping(false),
131 mAutoLoop(false) {
132 ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
133 mLooper->setName("NuPlayer2Driver Looper");
Wei Jia12b9f4a2017-12-13 15:24:13 -0800134 mNuPlayer2Looper->setName("NuPlayer2 Looper");
Wei Jia53692fa2017-12-11 10:33:46 -0800135
136 mMediaClock->init();
137
138 // set up an analytics record
139 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
Wei Jia003fdb52018-02-06 14:44:32 -0800140 mAnalyticsItem->setUid(mClientUid);
Wei Jia53692fa2017-12-11 10:33:46 -0800141
Wei Jia12b9f4a2017-12-13 15:24:13 -0800142 mNuPlayer2Looper->start(
Wei Jia53692fa2017-12-11 10:33:46 -0800143 false, /* runOnCallingThread */
144 true, /* canCallJava */
145 PRIORITY_AUDIO);
146
Wei Jia12b9f4a2017-12-13 15:24:13 -0800147 mNuPlayer2Looper->registerHandler(mPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800148
149 mPlayer->setDriver(this);
150}
151
152NuPlayer2Driver::~NuPlayer2Driver() {
153 ALOGV("~NuPlayer2Driver(%p)", this);
Wei Jia12b9f4a2017-12-13 15:24:13 -0800154 mNuPlayer2Looper->stop();
Wei Jia53692fa2017-12-11 10:33:46 -0800155 mLooper->stop();
156
157 // finalize any pending metrics, usually a no-op.
158 updateMetrics("destructor");
159 logMetrics("destructor");
160
161 if (mAnalyticsItem != NULL) {
162 delete mAnalyticsItem;
163 mAnalyticsItem = NULL;
164 }
165}
166
167status_t NuPlayer2Driver::initCheck() {
Wei Jia12b9f4a2017-12-13 15:24:13 -0800168 mLooper->start(
169 false, /* runOnCallingThread */
170 true, /* canCallJava */
171 PRIORITY_AUDIO);
172
173 mLooper->registerHandler(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800174 return OK;
175}
176
Wei Jiac2636032018-02-01 09:15:25 -0800177status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jia57aeffd2018-02-15 16:01:14 -0800178 ALOGV("setDataSource(%p)", this);
Wei Jia53692fa2017-12-11 10:33:46 -0800179 Mutex::Autolock autoLock(mLock);
180
181 if (mState != STATE_IDLE) {
182 return INVALID_OPERATION;
183 }
184
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800185 mSrcId = dsd->mId;
Wei Jia53692fa2017-12-11 10:33:46 -0800186 mState = STATE_SET_DATASOURCE_PENDING;
187
Wei Jiac2636032018-02-01 09:15:25 -0800188 mPlayer->setDataSourceAsync(dsd);
Wei Jia53692fa2017-12-11 10:33:46 -0800189
190 while (mState == STATE_SET_DATASOURCE_PENDING) {
191 mCondition.wait(mLock);
192 }
193
194 return mAsyncResult;
195}
196
Wei Jia57aeffd2018-02-15 16:01:14 -0800197status_t NuPlayer2Driver::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
198 ALOGV("prepareNextDataSource(%p)", this);
199 Mutex::Autolock autoLock(mLock);
200
201 mPlayer->prepareNextDataSourceAsync(dsd);
202
203 return OK;
204}
205
206status_t NuPlayer2Driver::playNextDataSource(int64_t srcId) {
207 ALOGV("playNextDataSource(%p)", this);
208 Mutex::Autolock autoLock(mLock);
209
210 mSrcId = srcId;
211 mPlayer->playNextDataSource(srcId);
212
213 return OK;
214}
215
Wei Jia28288fb2017-12-15 13:45:29 -0800216status_t NuPlayer2Driver::setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww) {
Wei Jia53692fa2017-12-11 10:33:46 -0800217 ALOGV("setVideoSurfaceTexture(%p)", this);
218 Mutex::Autolock autoLock(mLock);
219
220 if (mSetSurfaceInProgress) {
221 return INVALID_OPERATION;
222 }
223
224 switch (mState) {
225 case STATE_SET_DATASOURCE_PENDING:
226 case STATE_RESET_IN_PROGRESS:
227 return INVALID_OPERATION;
228
229 default:
230 break;
231 }
232
233 mSetSurfaceInProgress = true;
234
Wei Jia28288fb2017-12-15 13:45:29 -0800235 mPlayer->setVideoSurfaceTextureAsync(nww);
Wei Jia53692fa2017-12-11 10:33:46 -0800236
237 while (mSetSurfaceInProgress) {
238 mCondition.wait(mLock);
239 }
240
241 return OK;
242}
243
244status_t NuPlayer2Driver::getBufferingSettings(BufferingSettings* buffering) {
245 ALOGV("getBufferingSettings(%p)", this);
246 {
247 Mutex::Autolock autoLock(mLock);
248 if (mState == STATE_IDLE) {
249 return INVALID_OPERATION;
250 }
251 }
252
253 return mPlayer->getBufferingSettings(buffering);
254}
255
256status_t NuPlayer2Driver::setBufferingSettings(const BufferingSettings& buffering) {
257 ALOGV("setBufferingSettings(%p)", this);
258 {
259 Mutex::Autolock autoLock(mLock);
260 if (mState == STATE_IDLE) {
261 return INVALID_OPERATION;
262 }
263 }
264
265 return mPlayer->setBufferingSettings(buffering);
266}
267
Wei Jia53692fa2017-12-11 10:33:46 -0800268status_t NuPlayer2Driver::prepareAsync() {
269 ALOGV("prepareAsync(%p)", this);
270 Mutex::Autolock autoLock(mLock);
271
272 switch (mState) {
273 case STATE_UNPREPARED:
274 mState = STATE_PREPARING;
Wei Jia53692fa2017-12-11 10:33:46 -0800275 mPlayer->prepareAsync();
276 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800277 default:
278 return INVALID_OPERATION;
279 };
280}
281
282status_t NuPlayer2Driver::start() {
283 ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
284 Mutex::Autolock autoLock(mLock);
285 return start_l();
286}
287
288status_t NuPlayer2Driver::start_l() {
289 switch (mState) {
Wei Jia53692fa2017-12-11 10:33:46 -0800290 case STATE_PAUSED:
Wei Jia53692fa2017-12-11 10:33:46 -0800291 case STATE_PREPARED:
292 {
293 mPlayer->start();
294
295 // fall through
296 }
297
298 case STATE_RUNNING:
299 {
300 if (mAtEOS) {
301 mPlayer->seekToAsync(0);
302 mAtEOS = false;
303 mPositionUs = -1;
304 }
305 break;
306 }
307
308 default:
309 return INVALID_OPERATION;
310 }
311
312 mState = STATE_RUNNING;
313
314 return OK;
315}
316
Wei Jia53692fa2017-12-11 10:33:46 -0800317status_t NuPlayer2Driver::pause() {
318 ALOGD("pause(%p)", this);
319 // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
320 // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
321 // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
322 // getCurrentPosition here.
Wei Jia800fe372018-02-20 15:00:45 -0800323 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800324 getCurrentPosition(&unused);
325
326 Mutex::Autolock autoLock(mLock);
327
328 switch (mState) {
329 case STATE_PAUSED:
330 case STATE_PREPARED:
331 return OK;
332
333 case STATE_RUNNING:
334 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800335 mPlayer->pause();
336 break;
337
338 default:
339 return INVALID_OPERATION;
340 }
341
342 return OK;
343}
344
345bool NuPlayer2Driver::isPlaying() {
346 return mState == STATE_RUNNING && !mAtEOS;
347}
348
349status_t NuPlayer2Driver::setPlaybackSettings(const AudioPlaybackRate &rate) {
350 status_t err = mPlayer->setPlaybackSettings(rate);
351 if (err == OK) {
352 // try to update position
Wei Jia800fe372018-02-20 15:00:45 -0800353 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800354 getCurrentPosition(&unused);
355 Mutex::Autolock autoLock(mLock);
356 if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
357 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800358 } else if (rate.mSpeed != 0.f
359 && (mState == STATE_PAUSED
Wei Jia53692fa2017-12-11 10:33:46 -0800360 || mState == STATE_PREPARED)) {
361 err = start_l();
362 }
363 }
364 return err;
365}
366
367status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
368 return mPlayer->getPlaybackSettings(rate);
369}
370
371status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
372 return mPlayer->setSyncSettings(sync, videoFpsHint);
373}
374
375status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
376 return mPlayer->getSyncSettings(sync, videoFps);
377}
378
Wei Jia800fe372018-02-20 15:00:45 -0800379status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
380 ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
Wei Jia53692fa2017-12-11 10:33:46 -0800381 Mutex::Autolock autoLock(mLock);
382
383 int64_t seekTimeUs = msec * 1000ll;
384
385 switch (mState) {
386 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800387 case STATE_PAUSED:
388 case STATE_RUNNING:
389 {
390 mAtEOS = false;
391 mSeekInProgress = true;
Wei Jia53692fa2017-12-11 10:33:46 -0800392 mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
393 break;
394 }
395
396 default:
397 return INVALID_OPERATION;
398 }
399
400 mPositionUs = seekTimeUs;
401 return OK;
402}
403
Wei Jia800fe372018-02-20 15:00:45 -0800404status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800405 int64_t tempUs = 0;
406 {
407 Mutex::Autolock autoLock(mLock);
408 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
409 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
Wei Jia800fe372018-02-20 15:00:45 -0800410 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800411 return OK;
412 }
413 }
414
415 status_t ret = mPlayer->getCurrentPosition(&tempUs);
416
417 Mutex::Autolock autoLock(mLock);
418 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
419 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
420 // position value that's different the seek to position.
421 if (ret != OK) {
422 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
423 } else {
424 mPositionUs = tempUs;
425 }
Wei Jia800fe372018-02-20 15:00:45 -0800426 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800427 return OK;
428}
429
Wei Jia800fe372018-02-20 15:00:45 -0800430status_t NuPlayer2Driver::getDuration(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800431 Mutex::Autolock autoLock(mLock);
432
433 if (mDurationUs < 0) {
434 return UNKNOWN_ERROR;
435 }
436
437 *msec = (mDurationUs + 500ll) / 1000;
438
439 return OK;
440}
441
442void NuPlayer2Driver::updateMetrics(const char *where) {
443 if (where == NULL) {
444 where = "unknown";
445 }
446 ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
447
448 // gather the final stats for this record
449 Vector<sp<AMessage>> trackStats;
450 mPlayer->getStats(&trackStats);
451
452 if (trackStats.size() > 0) {
453 for (size_t i = 0; i < trackStats.size(); ++i) {
454 const sp<AMessage> &stats = trackStats.itemAt(i);
455
456 AString mime;
457 stats->findString("mime", &mime);
458
459 AString name;
460 stats->findString("component-name", &name);
461
462 if (mime.startsWith("video/")) {
463 int32_t width, height;
464 mAnalyticsItem->setCString(kPlayerVMime, mime.c_str());
465 if (!name.empty()) {
466 mAnalyticsItem->setCString(kPlayerVCodec, name.c_str());
467 }
468
469 if (stats->findInt32("width", &width)
470 && stats->findInt32("height", &height)) {
471 mAnalyticsItem->setInt32(kPlayerWidth, width);
472 mAnalyticsItem->setInt32(kPlayerHeight, height);
473 }
474
475 int64_t numFramesTotal = 0;
476 int64_t numFramesDropped = 0;
477 stats->findInt64("frames-total", &numFramesTotal);
478 stats->findInt64("frames-dropped-output", &numFramesDropped);
479
480 mAnalyticsItem->setInt64(kPlayerFrames, numFramesTotal);
481 mAnalyticsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
482
483
484 } else if (mime.startsWith("audio/")) {
485 mAnalyticsItem->setCString(kPlayerAMime, mime.c_str());
486 if (!name.empty()) {
487 mAnalyticsItem->setCString(kPlayerACodec, name.c_str());
488 }
489 }
490 }
491 }
492
493 // always provide duration and playing time, even if they have 0/unknown values.
494
495 // getDuration() uses mLock for mutex -- careful where we use it.
Wei Jia800fe372018-02-20 15:00:45 -0800496 int64_t duration_ms = -1;
Wei Jia53692fa2017-12-11 10:33:46 -0800497 getDuration(&duration_ms);
498 mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
499
500 mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
501
502 if (mRebufferingEvents != 0) {
503 mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
504 mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents);
505 mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit);
506 }
507
508 mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
509}
510
511
512void NuPlayer2Driver::logMetrics(const char *where) {
513 if (where == NULL) {
514 where = "unknown";
515 }
516 ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
517
518 if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
519 return;
520 }
521
522 // log only non-empty records
523 // we always updateMetrics() before we get here
524 // and that always injects 3 fields (duration, playing time, and
525 // datasource) into the record.
526 // So the canonical "empty" record has 3 elements in it.
527 if (mAnalyticsItem->count() > 3) {
528
Wei Jia53692fa2017-12-11 10:33:46 -0800529 mAnalyticsItem->selfrecord();
530
531 // re-init in case we prepare() and start() again.
532 delete mAnalyticsItem ;
Ray Essickee54eef2018-01-24 11:16:54 -0800533 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800534 if (mAnalyticsItem) {
Wei Jia53692fa2017-12-11 10:33:46 -0800535 mAnalyticsItem->setUid(mClientUid);
536 }
537 } else {
538 ALOGV("did not have anything to record");
539 }
540}
541
542status_t NuPlayer2Driver::reset() {
543 ALOGD("reset(%p) at state %d", this, mState);
544
545 updateMetrics("reset");
546 logMetrics("reset");
547
548 Mutex::Autolock autoLock(mLock);
549
550 switch (mState) {
551 case STATE_IDLE:
552 return OK;
553
554 case STATE_SET_DATASOURCE_PENDING:
555 case STATE_RESET_IN_PROGRESS:
556 return INVALID_OPERATION;
557
558 case STATE_PREPARING:
559 {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800560 notifyListener_l(mSrcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800561 break;
562 }
563
564 default:
565 break;
566 }
567
Wei Jia53692fa2017-12-11 10:33:46 -0800568 mState = STATE_RESET_IN_PROGRESS;
569 mPlayer->resetAsync();
570
571 while (mState == STATE_RESET_IN_PROGRESS) {
572 mCondition.wait(mLock);
573 }
574
575 mDurationUs = -1;
576 mPositionUs = -1;
577 mLooping = false;
578 mPlayingTimeUs = 0;
579 mRebufferingTimeUs = 0;
580 mRebufferingEvents = 0;
581 mRebufferingAtExit = false;
582
583 return OK;
584}
585
586status_t NuPlayer2Driver::notifyAt(int64_t mediaTimeUs) {
587 ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
588 return mPlayer->notifyAt(mediaTimeUs);
589}
590
591status_t NuPlayer2Driver::setLooping(int loop) {
592 mLooping = loop != 0;
593 return OK;
594}
595
Dongwon Kang9f631982018-07-10 12:34:41 -0700596status_t NuPlayer2Driver::invoke(const PlayerMessage &request, PlayerMessage *response) {
597 if (response == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800598 ALOGE("reply is a NULL pointer");
599 return BAD_VALUE;
600 }
601
Dongwon Kang9f631982018-07-10 12:34:41 -0700602 RepeatedPtrField<const Value>::const_iterator it = request.values().cbegin();
603 int32_t methodId = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800604
605 switch (methodId) {
606 case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
607 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700608 int mode = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800609 return mPlayer->setVideoScalingMode(mode);
610 }
611
612 case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
613 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700614 return mPlayer->getTrackInfo(response);
Wei Jia53692fa2017-12-11 10:33:46 -0800615 }
616
617 case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
618 {
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);
623 return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll);
624 }
625
626 case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
627 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700628 int trackIndex = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800629 return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
630 }
631
632 case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
633 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700634 int32_t type = (it++)->int32_value();
635 return mPlayer->getSelectedTrack(type, response);
Wei Jia53692fa2017-12-11 10:33:46 -0800636 }
637
638 default:
639 {
640 return INVALID_OPERATION;
641 }
642 }
643}
644
645void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
646 mPlayer->setAudioSink(audioSink);
647 mAudioSink = audioSink;
648}
649
650status_t NuPlayer2Driver::setParameter(
651 int /* key */, const Parcel & /* request */) {
652 return INVALID_OPERATION;
653}
654
655status_t NuPlayer2Driver::getParameter(int key, Parcel *reply) {
656
657 if (key == FOURCC('m','t','r','X')) {
658 // mtrX -- a play on 'metrics' (not matrix)
659 // gather current info all together, parcel it, and send it back
660 updateMetrics("api");
661 mAnalyticsItem->writeToParcel(reply);
662 return OK;
663 }
664
665 return INVALID_OPERATION;
666}
667
668status_t NuPlayer2Driver::getMetadata(
669 const media::Metadata::Filter& /* ids */, Parcel *records) {
670 Mutex::Autolock autoLock(mLock);
671
672 using media::Metadata;
673
674 Metadata meta(records);
675
676 meta.appendBool(
677 Metadata::kPauseAvailable,
678 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
679
680 meta.appendBool(
681 Metadata::kSeekBackwardAvailable,
682 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
683
684 meta.appendBool(
685 Metadata::kSeekForwardAvailable,
686 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
687
688 meta.appendBool(
689 Metadata::kSeekAvailable,
690 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
691
692 return OK;
693}
694
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800695void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800696 ALOGD("notifyResetComplete(%p)", this);
697 Mutex::Autolock autoLock(mLock);
698
699 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
700 mState = STATE_IDLE;
701 mCondition.broadcast();
702}
703
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800704void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800705 ALOGV("notifySetSurfaceComplete(%p)", this);
706 Mutex::Autolock autoLock(mLock);
707
708 CHECK(mSetSurfaceInProgress);
709 mSetSurfaceInProgress = false;
710
711 mCondition.broadcast();
712}
713
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800714void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800715 Mutex::Autolock autoLock(mLock);
716 mDurationUs = durationUs;
717}
718
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800719void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800720 Mutex::Autolock autoLock(mLock);
721 mPlayingTimeUs += playingUs;
722}
723
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800724void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800725 Mutex::Autolock autoLock(mLock);
726 mRebufferingTimeUs += rebufferingUs;
727 mRebufferingEvents++;
728}
729
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800730void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
Wei Jia53692fa2017-12-11 10:33:46 -0800731 Mutex::Autolock autoLock(mLock);
732 mRebufferingAtExit = status;
733}
734
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800735void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800736 ALOGV("notifySeekComplete(%p)", this);
737 Mutex::Autolock autoLock(mLock);
738 mSeekInProgress = false;
Wei Jia0151ef42018-08-24 16:40:21 -0700739 notifyListener_l(srcId, MEDIA2_SEEK_COMPLETE);
Wei Jia53692fa2017-12-11 10:33:46 -0800740}
741
742status_t NuPlayer2Driver::dump(
743 int fd, const Vector<String16> & /* args */) const {
744
745 Vector<sp<AMessage> > trackStats;
746 mPlayer->getStats(&trackStats);
747
748 AString logString(" NuPlayer2\n");
749 char buf[256] = {0};
750
751 bool locked = false;
752 for (int i = 0; i < kDumpLockRetries; ++i) {
753 if (mLock.tryLock() == NO_ERROR) {
754 locked = true;
755 break;
756 }
757 usleep(kDumpLockSleepUs);
758 }
759
760 if (locked) {
761 snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
762 mState, mAtEOS, mLooping, mAutoLoop);
763 mLock.unlock();
764 } else {
765 snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
766 }
767 logString.append(buf);
768
769 for (size_t i = 0; i < trackStats.size(); ++i) {
770 const sp<AMessage> &stats = trackStats.itemAt(i);
771
772 AString mime;
773 if (stats->findString("mime", &mime)) {
774 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
775 logString.append(buf);
776 }
777
778 AString name;
779 if (stats->findString("component-name", &name)) {
780 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
781 logString.append(buf);
782 }
783
784 if (mime.startsWith("video/")) {
785 int32_t width, height;
786 if (stats->findInt32("width", &width)
787 && stats->findInt32("height", &height)) {
788 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
789 logString.append(buf);
790 }
791
792 int64_t numFramesTotal = 0;
793 int64_t numFramesDropped = 0;
794
795 stats->findInt64("frames-total", &numFramesTotal);
796 stats->findInt64("frames-dropped-output", &numFramesDropped);
797 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
798 "percentageDropped(%.2f%%)\n",
799 (long long)numFramesTotal,
800 (long long)numFramesDropped,
801 numFramesTotal == 0
802 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
803 logString.append(buf);
804 }
805 }
806
807 ALOGI("%s", logString.c_str());
808
809 if (fd >= 0) {
810 FILE *out = fdopen(dup(fd), "w");
811 fprintf(out, "%s", logString.c_str());
812 fclose(out);
813 out = NULL;
814 }
815
816 return OK;
817}
818
Wei Jia12b9f4a2017-12-13 15:24:13 -0800819void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
820 switch (msg->what()) {
821 case kWhatNotifyListener: {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800822 int64_t srcId;
Wei Jia12b9f4a2017-12-13 15:24:13 -0800823 int32_t msgId;
Wei Jiac5c79da2017-12-21 18:03:05 -0800824 int32_t ext1 = 0;
825 int32_t ext2 = 0;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800826 CHECK(msg->findInt64("srcId", &srcId));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800827 CHECK(msg->findInt32("messageId", &msgId));
Wei Jiac5c79da2017-12-21 18:03:05 -0800828 msg->findInt32("ext1", &ext1);
829 msg->findInt32("ext2", &ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700830 sp<PlayerMessageWrapper> in;
Wei Jiac5c79da2017-12-21 18:03:05 -0800831 sp<RefBase> obj;
Dongwon Kang41929fb2018-09-09 08:29:56 -0700832 if (msg->findObject("obj", &obj) && obj != NULL) {
833 in = static_cast<PlayerMessageWrapper *>(obj.get());
Wei Jiac5c79da2017-12-21 18:03:05 -0800834 }
Dongwon Kang41929fb2018-09-09 08:29:56 -0700835 sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getPlayerMessage()));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800836 break;
837 }
838 default:
839 break;
840 }
841}
842
Wei Jia53692fa2017-12-11 10:33:46 -0800843void NuPlayer2Driver::notifyListener(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700844 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jia53692fa2017-12-11 10:33:46 -0800845 Mutex::Autolock autoLock(mLock);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800846 notifyListener_l(srcId, msg, ext1, ext2, in);
Wei Jia53692fa2017-12-11 10:33:46 -0800847}
848
849void NuPlayer2Driver::notifyListener_l(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700850 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800851 ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
852 this, (long long)srcId, msg, ext1, ext2,
Dongwon Kang41929fb2018-09-09 08:29:56 -0700853 (in == NULL ? -1 : (int)in->ByteSize()), mAutoLoop, mLooping);
Wei Jia57aeffd2018-02-15 16:01:14 -0800854 if (srcId == mSrcId) {
855 switch (msg) {
856 case MEDIA2_PLAYBACK_COMPLETE:
857 {
858 if (mState != STATE_RESET_IN_PROGRESS) {
859 if (mAutoLoop) {
860 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
861 if (mAudioSink != NULL) {
862 streamType = mAudioSink->getAudioStreamType();
863 }
864 if (streamType == AUDIO_STREAM_NOTIFICATION) {
865 ALOGW("disabling auto-loop for notification");
866 mAutoLoop = false;
867 }
Wei Jia53692fa2017-12-11 10:33:46 -0800868 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800869 if (mLooping || mAutoLoop) {
870 mPlayer->seekToAsync(0);
871 if (mAudioSink != NULL) {
872 // The renderer has stopped the sink at the end in order to play out
873 // the last little bit of audio. In looping mode, we need to restart it.
874 mAudioSink->start();
875 }
Wei Jia9af566a2018-08-10 16:36:35 -0700876
877 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
878 notify->setInt64("srcId", srcId);
879 notify->setInt32("messageId", MEDIA2_INFO);
880 notify->setInt32("ext1", MEDIA2_INFO_DATA_SOURCE_REPEAT);
881 notify->post();
Wei Jia57aeffd2018-02-15 16:01:14 -0800882 return;
Wei Jia53692fa2017-12-11 10:33:46 -0800883 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800884 if (property_get_bool("persist.debug.sf.stats", false)) {
885 Vector<String16> args;
886 dump(-1, args);
Wei Jia53692fa2017-12-11 10:33:46 -0800887 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800888 mPlayer->pause();
889 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800890 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800891 // fall through
Wei Jia53692fa2017-12-11 10:33:46 -0800892 }
Wei Jia53692fa2017-12-11 10:33:46 -0800893
Wei Jia57aeffd2018-02-15 16:01:14 -0800894 case MEDIA2_ERROR:
895 {
896 // when we have an error, add it to the analytics for this playback.
897 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
898 // [test against msg is due to fall through from previous switch value]
899 if (msg == MEDIA2_ERROR) {
900 mAnalyticsItem->setInt32(kPlayerError, ext1);
901 if (ext2 != 0) {
902 mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
903 }
904 mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800905 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800906 mAtEOS = true;
907 break;
Wei Jia53692fa2017-12-11 10:33:46 -0800908 }
Wei Jia53692fa2017-12-11 10:33:46 -0800909
Wei Jia57aeffd2018-02-15 16:01:14 -0800910 default:
911 break;
912 }
Wei Jia53692fa2017-12-11 10:33:46 -0800913 }
914
Wei Jiac5c79da2017-12-21 18:03:05 -0800915 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800916 notify->setInt64("srcId", srcId);
Wei Jiac5c79da2017-12-21 18:03:05 -0800917 notify->setInt32("messageId", msg);
918 notify->setInt32("ext1", ext1);
919 notify->setInt32("ext2", ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700920 notify->setObject("obj", PlayerMessageWrapper::Create((PlayerMessage*)in));
Wei Jiac5c79da2017-12-21 18:03:05 -0800921 notify->post();
Wei Jia12b9f4a2017-12-13 15:24:13 -0800922}
923
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800924void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800925 Mutex::Autolock autoLock(mLock);
926
927 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
928
929 mAsyncResult = err;
930 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
931 mCondition.broadcast();
932}
933
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800934void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800935 ALOGV("notifyPrepareCompleted %d", err);
936
937 Mutex::Autolock autoLock(mLock);
938
Wei Jia57aeffd2018-02-15 16:01:14 -0800939 if (srcId != mSrcId) {
940 if (err == OK) {
941 notifyListener_l(srcId, MEDIA2_PREPARED);
942 } else {
943 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
944 }
945 return;
946 }
947
Wei Jia53692fa2017-12-11 10:33:46 -0800948 if (mState != STATE_PREPARING) {
949 // We were preparing asynchronously when the client called
950 // reset(), we sent a premature "prepared" notification and
951 // then initiated the reset. This notification is stale.
952 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
953 return;
954 }
955
956 CHECK_EQ(mState, STATE_PREPARING);
957
958 mAsyncResult = err;
959
960 if (err == OK) {
961 // update state before notifying client, so that if client calls back into NuPlayer2Driver
962 // in response, NuPlayer2Driver has the right state
963 mState = STATE_PREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800964 notifyListener_l(srcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800965 } else {
966 mState = STATE_UNPREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800967 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
Wei Jia53692fa2017-12-11 10:33:46 -0800968 }
969
970 sp<MetaData> meta = mPlayer->getFileMeta();
971 int32_t loop;
972 if (meta != NULL
973 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
974 mAutoLoop = true;
975 }
976
977 mCondition.broadcast();
978}
979
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800980void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
Wei Jia53692fa2017-12-11 10:33:46 -0800981 Mutex::Autolock autoLock(mLock);
982
983 mPlayerFlags = flags;
984}
985
986// Modular DRM
987status_t NuPlayer2Driver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
988{
989 ALOGV("prepareDrm(%p) state: %d", this, mState);
990
991 // leaving the state verification for mediaplayer.cpp
992 status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
993
994 ALOGV("prepareDrm ret: %d", ret);
995
996 return ret;
997}
998
999status_t NuPlayer2Driver::releaseDrm()
1000{
1001 ALOGV("releaseDrm(%p) state: %d", this, mState);
1002
1003 // leaving the state verification for mediaplayer.cpp
1004 status_t ret = mPlayer->releaseDrm();
1005
1006 ALOGV("releaseDrm ret: %d", ret);
1007
1008 return ret;
1009}
1010
Ray Essick51f4c872017-12-15 12:27:56 -08001011std::string NuPlayer2Driver::stateString(State state) {
1012 const char *rval = NULL;
1013 char rawbuffer[16]; // allows "%d"
1014
1015 switch (state) {
1016 case STATE_IDLE: rval = "IDLE"; break;
1017 case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1018 case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1019 case STATE_PREPARING: rval = "PREPARING"; break;
1020 case STATE_PREPARED: rval = "PREPARED"; break;
1021 case STATE_RUNNING: rval = "RUNNING"; break;
1022 case STATE_PAUSED: rval = "PAUSED"; break;
1023 case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
Ray Essick51f4c872017-12-15 12:27:56 -08001024 default:
1025 // yes, this buffer is shared and vulnerable to races
1026 snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1027 rval = rawbuffer;
1028 break;
1029 }
1030
1031 return rval;
1032}
1033
Wei Jia53692fa2017-12-11 10:33:46 -08001034} // namespace android