blob: f85e3a2f878d69047b5f4afe1343f3888137c6db [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
39static const int kDumpLockRetries = 50;
40static const int kDumpLockSleepUs = 20000;
41
42namespace android {
43
Wei Jiac5c79da2017-12-21 18:03:05 -080044struct ParcelWrapper : public RefBase {
45 static sp<ParcelWrapper> Create(const Parcel *p) {
46 if (p != NULL) {
47 sp<ParcelWrapper> pw = new ParcelWrapper();
48 if (pw->appendFrom(p) == OK) {
49 return pw;
50 }
51 }
52 return NULL;
53 }
54
55 const Parcel *getParcel() {
56 return mParcel;
57 }
58
59protected:
60 virtual ~ParcelWrapper() {
61 if (mParcel != NULL) {
62 delete mParcel;
63 }
64 }
65
66private:
67 ParcelWrapper()
68 : mParcel(NULL) { }
69
70 status_t appendFrom(const Parcel *p) {
71 if (mParcel == NULL) {
72 mParcel = new Parcel;
73 }
74 return mParcel->appendFrom(p, 0 /* start */, p->dataSize());
75 }
76
77 Parcel *mParcel;
78};
79
Wei Jia53692fa2017-12-11 10:33:46 -080080// key for media statistics
Ray Essickee54eef2018-01-24 11:16:54 -080081static const char *kKeyPlayer = "nuplayer";
Wei Jia53692fa2017-12-11 10:33:46 -080082// attrs for media statistics
Ray Essickde15b8c2018-01-30 16:35:56 -080083 // NB: these are matched with public Java API constants defined
84 // in frameworks/base/media/java/android/media/MediaPlayer2.java
85 // These must be kept synchronized with the constants there.
Wei Jia53692fa2017-12-11 10:33:46 -080086static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
87static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
88static const char *kPlayerWidth = "android.media.mediaplayer.width";
89static const char *kPlayerHeight = "android.media.mediaplayer.height";
90static const char *kPlayerFrames = "android.media.mediaplayer.frames";
91static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
92static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
93static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
94static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
95static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
96static const char *kPlayerError = "android.media.mediaplayer.err";
97static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
Ray Essickde15b8c2018-01-30 16:35:56 -080098
99// NB: These are not yet exposed as public Java API constants.
Ray Essick51f4c872017-12-15 12:27:56 -0800100static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
Wei Jia53692fa2017-12-11 10:33:46 -0800101static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
102//
103static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
104static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
105static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
106
107
Wei Jia003fdb52018-02-06 14:44:32 -0800108NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid)
Wei Jia53692fa2017-12-11 10:33:46 -0800109 : mState(STATE_IDLE),
Wei Jia53692fa2017-12-11 10:33:46 -0800110 mAsyncResult(UNKNOWN_ERROR),
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800111 mSrcId(0),
Wei Jia53692fa2017-12-11 10:33:46 -0800112 mSetSurfaceInProgress(false),
113 mDurationUs(-1),
114 mPositionUs(-1),
115 mSeekInProgress(false),
116 mPlayingTimeUs(0),
117 mRebufferingTimeUs(0),
118 mRebufferingEvents(0),
119 mRebufferingAtExit(false),
120 mLooper(new ALooper),
Wei Jia12b9f4a2017-12-13 15:24:13 -0800121 mNuPlayer2Looper(new ALooper),
Wei Jia53692fa2017-12-11 10:33:46 -0800122 mMediaClock(new MediaClock),
Wei Jia003fdb52018-02-06 14:44:32 -0800123 mPlayer(new NuPlayer2(pid, uid, mMediaClock)),
Wei Jia53692fa2017-12-11 10:33:46 -0800124 mPlayerFlags(0),
125 mAnalyticsItem(NULL),
Wei Jia003fdb52018-02-06 14:44:32 -0800126 mClientUid(uid),
Wei Jia53692fa2017-12-11 10:33:46 -0800127 mAtEOS(false),
128 mLooping(false),
129 mAutoLoop(false) {
130 ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
131 mLooper->setName("NuPlayer2Driver Looper");
Wei Jia12b9f4a2017-12-13 15:24:13 -0800132 mNuPlayer2Looper->setName("NuPlayer2 Looper");
Wei Jia53692fa2017-12-11 10:33:46 -0800133
134 mMediaClock->init();
135
136 // set up an analytics record
137 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
Wei Jia003fdb52018-02-06 14:44:32 -0800138 mAnalyticsItem->setUid(mClientUid);
Wei Jia53692fa2017-12-11 10:33:46 -0800139
Wei Jia12b9f4a2017-12-13 15:24:13 -0800140 mNuPlayer2Looper->start(
Wei Jia53692fa2017-12-11 10:33:46 -0800141 false, /* runOnCallingThread */
142 true, /* canCallJava */
143 PRIORITY_AUDIO);
144
Wei Jia12b9f4a2017-12-13 15:24:13 -0800145 mNuPlayer2Looper->registerHandler(mPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800146
147 mPlayer->setDriver(this);
148}
149
150NuPlayer2Driver::~NuPlayer2Driver() {
151 ALOGV("~NuPlayer2Driver(%p)", this);
Wei Jia12b9f4a2017-12-13 15:24:13 -0800152 mNuPlayer2Looper->stop();
Wei Jia53692fa2017-12-11 10:33:46 -0800153 mLooper->stop();
154
155 // finalize any pending metrics, usually a no-op.
156 updateMetrics("destructor");
157 logMetrics("destructor");
158
159 if (mAnalyticsItem != NULL) {
160 delete mAnalyticsItem;
161 mAnalyticsItem = NULL;
162 }
163}
164
165status_t NuPlayer2Driver::initCheck() {
Wei Jia12b9f4a2017-12-13 15:24:13 -0800166 mLooper->start(
167 false, /* runOnCallingThread */
168 true, /* canCallJava */
169 PRIORITY_AUDIO);
170
171 mLooper->registerHandler(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800172 return OK;
173}
174
Wei Jiac2636032018-02-01 09:15:25 -0800175status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jia57aeffd2018-02-15 16:01:14 -0800176 ALOGV("setDataSource(%p)", this);
Wei Jia53692fa2017-12-11 10:33:46 -0800177 Mutex::Autolock autoLock(mLock);
178
179 if (mState != STATE_IDLE) {
180 return INVALID_OPERATION;
181 }
182
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800183 mSrcId = dsd->mId;
Wei Jia53692fa2017-12-11 10:33:46 -0800184 mState = STATE_SET_DATASOURCE_PENDING;
185
Wei Jiac2636032018-02-01 09:15:25 -0800186 mPlayer->setDataSourceAsync(dsd);
Wei Jia53692fa2017-12-11 10:33:46 -0800187
188 while (mState == STATE_SET_DATASOURCE_PENDING) {
189 mCondition.wait(mLock);
190 }
191
192 return mAsyncResult;
193}
194
Wei Jia57aeffd2018-02-15 16:01:14 -0800195status_t NuPlayer2Driver::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
196 ALOGV("prepareNextDataSource(%p)", this);
197 Mutex::Autolock autoLock(mLock);
198
199 mPlayer->prepareNextDataSourceAsync(dsd);
200
201 return OK;
202}
203
204status_t NuPlayer2Driver::playNextDataSource(int64_t srcId) {
205 ALOGV("playNextDataSource(%p)", this);
206 Mutex::Autolock autoLock(mLock);
207
208 mSrcId = srcId;
209 mPlayer->playNextDataSource(srcId);
210
211 return OK;
212}
213
Wei Jia28288fb2017-12-15 13:45:29 -0800214status_t NuPlayer2Driver::setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww) {
Wei Jia53692fa2017-12-11 10:33:46 -0800215 ALOGV("setVideoSurfaceTexture(%p)", this);
216 Mutex::Autolock autoLock(mLock);
217
218 if (mSetSurfaceInProgress) {
219 return INVALID_OPERATION;
220 }
221
222 switch (mState) {
223 case STATE_SET_DATASOURCE_PENDING:
224 case STATE_RESET_IN_PROGRESS:
225 return INVALID_OPERATION;
226
227 default:
228 break;
229 }
230
231 mSetSurfaceInProgress = true;
232
Wei Jia28288fb2017-12-15 13:45:29 -0800233 mPlayer->setVideoSurfaceTextureAsync(nww);
Wei Jia53692fa2017-12-11 10:33:46 -0800234
235 while (mSetSurfaceInProgress) {
236 mCondition.wait(mLock);
237 }
238
239 return OK;
240}
241
242status_t NuPlayer2Driver::getBufferingSettings(BufferingSettings* buffering) {
243 ALOGV("getBufferingSettings(%p)", this);
244 {
245 Mutex::Autolock autoLock(mLock);
246 if (mState == STATE_IDLE) {
247 return INVALID_OPERATION;
248 }
249 }
250
251 return mPlayer->getBufferingSettings(buffering);
252}
253
254status_t NuPlayer2Driver::setBufferingSettings(const BufferingSettings& buffering) {
255 ALOGV("setBufferingSettings(%p)", this);
256 {
257 Mutex::Autolock autoLock(mLock);
258 if (mState == STATE_IDLE) {
259 return INVALID_OPERATION;
260 }
261 }
262
263 return mPlayer->setBufferingSettings(buffering);
264}
265
Wei Jia53692fa2017-12-11 10:33:46 -0800266status_t NuPlayer2Driver::prepareAsync() {
267 ALOGV("prepareAsync(%p)", this);
268 Mutex::Autolock autoLock(mLock);
269
270 switch (mState) {
271 case STATE_UNPREPARED:
272 mState = STATE_PREPARING;
Wei Jia53692fa2017-12-11 10:33:46 -0800273 mPlayer->prepareAsync();
274 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800275 default:
276 return INVALID_OPERATION;
277 };
278}
279
280status_t NuPlayer2Driver::start() {
281 ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
282 Mutex::Autolock autoLock(mLock);
283 return start_l();
284}
285
286status_t NuPlayer2Driver::start_l() {
287 switch (mState) {
Wei Jia53692fa2017-12-11 10:33:46 -0800288 case STATE_PAUSED:
Wei Jia53692fa2017-12-11 10:33:46 -0800289 case STATE_PREPARED:
290 {
291 mPlayer->start();
292
293 // fall through
294 }
295
296 case STATE_RUNNING:
297 {
298 if (mAtEOS) {
299 mPlayer->seekToAsync(0);
300 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:
328 case STATE_PREPARED:
329 return OK;
330
331 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);
353 Mutex::Autolock autoLock(mLock);
354 if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
355 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800356 } else if (rate.mSpeed != 0.f
357 && (mState == STATE_PAUSED
Wei Jia53692fa2017-12-11 10:33:46 -0800358 || mState == STATE_PREPARED)) {
359 err = start_l();
360 }
361 }
362 return err;
363}
364
365status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
366 return mPlayer->getPlaybackSettings(rate);
367}
368
369status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
370 return mPlayer->setSyncSettings(sync, videoFpsHint);
371}
372
373status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
374 return mPlayer->getSyncSettings(sync, videoFps);
375}
376
Wei Jia800fe372018-02-20 15:00:45 -0800377status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
378 ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
Wei Jia53692fa2017-12-11 10:33:46 -0800379 Mutex::Autolock autoLock(mLock);
380
381 int64_t seekTimeUs = msec * 1000ll;
382
383 switch (mState) {
384 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800385 case STATE_PAUSED:
386 case STATE_RUNNING:
387 {
388 mAtEOS = false;
389 mSeekInProgress = true;
Wei Jia53692fa2017-12-11 10:33:46 -0800390 mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
391 break;
392 }
393
394 default:
395 return INVALID_OPERATION;
396 }
397
398 mPositionUs = seekTimeUs;
399 return OK;
400}
401
Wei Jia800fe372018-02-20 15:00:45 -0800402status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800403 int64_t tempUs = 0;
404 {
405 Mutex::Autolock autoLock(mLock);
406 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
407 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
Wei Jia800fe372018-02-20 15:00:45 -0800408 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800409 return OK;
410 }
411 }
412
413 status_t ret = mPlayer->getCurrentPosition(&tempUs);
414
415 Mutex::Autolock autoLock(mLock);
416 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
417 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
418 // position value that's different the seek to position.
419 if (ret != OK) {
420 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
421 } else {
422 mPositionUs = tempUs;
423 }
Wei Jia800fe372018-02-20 15:00:45 -0800424 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800425 return OK;
426}
427
Wei Jia800fe372018-02-20 15:00:45 -0800428status_t NuPlayer2Driver::getDuration(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800429 Mutex::Autolock autoLock(mLock);
430
431 if (mDurationUs < 0) {
432 return UNKNOWN_ERROR;
433 }
434
435 *msec = (mDurationUs + 500ll) / 1000;
436
437 return OK;
438}
439
440void NuPlayer2Driver::updateMetrics(const char *where) {
441 if (where == NULL) {
442 where = "unknown";
443 }
444 ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
445
446 // gather the final stats for this record
447 Vector<sp<AMessage>> trackStats;
448 mPlayer->getStats(&trackStats);
449
450 if (trackStats.size() > 0) {
451 for (size_t i = 0; i < trackStats.size(); ++i) {
452 const sp<AMessage> &stats = trackStats.itemAt(i);
453
454 AString mime;
455 stats->findString("mime", &mime);
456
457 AString name;
458 stats->findString("component-name", &name);
459
460 if (mime.startsWith("video/")) {
461 int32_t width, height;
462 mAnalyticsItem->setCString(kPlayerVMime, mime.c_str());
463 if (!name.empty()) {
464 mAnalyticsItem->setCString(kPlayerVCodec, name.c_str());
465 }
466
467 if (stats->findInt32("width", &width)
468 && stats->findInt32("height", &height)) {
469 mAnalyticsItem->setInt32(kPlayerWidth, width);
470 mAnalyticsItem->setInt32(kPlayerHeight, height);
471 }
472
473 int64_t numFramesTotal = 0;
474 int64_t numFramesDropped = 0;
475 stats->findInt64("frames-total", &numFramesTotal);
476 stats->findInt64("frames-dropped-output", &numFramesDropped);
477
478 mAnalyticsItem->setInt64(kPlayerFrames, numFramesTotal);
479 mAnalyticsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
480
481
482 } else if (mime.startsWith("audio/")) {
483 mAnalyticsItem->setCString(kPlayerAMime, mime.c_str());
484 if (!name.empty()) {
485 mAnalyticsItem->setCString(kPlayerACodec, name.c_str());
486 }
487 }
488 }
489 }
490
491 // always provide duration and playing time, even if they have 0/unknown values.
492
493 // getDuration() uses mLock for mutex -- careful where we use it.
Wei Jia800fe372018-02-20 15:00:45 -0800494 int64_t duration_ms = -1;
Wei Jia53692fa2017-12-11 10:33:46 -0800495 getDuration(&duration_ms);
496 mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
497
498 mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
499
500 if (mRebufferingEvents != 0) {
501 mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
502 mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents);
503 mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit);
504 }
505
506 mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
507}
508
509
510void NuPlayer2Driver::logMetrics(const char *where) {
511 if (where == NULL) {
512 where = "unknown";
513 }
514 ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
515
516 if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
517 return;
518 }
519
520 // log only non-empty records
521 // we always updateMetrics() before we get here
522 // and that always injects 3 fields (duration, playing time, and
523 // datasource) into the record.
524 // So the canonical "empty" record has 3 elements in it.
525 if (mAnalyticsItem->count() > 3) {
526
Wei Jia53692fa2017-12-11 10:33:46 -0800527 mAnalyticsItem->selfrecord();
528
529 // re-init in case we prepare() and start() again.
530 delete mAnalyticsItem ;
Ray Essickee54eef2018-01-24 11:16:54 -0800531 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800532 if (mAnalyticsItem) {
Wei Jia53692fa2017-12-11 10:33:46 -0800533 mAnalyticsItem->setUid(mClientUid);
534 }
535 } 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
Wei Jia53692fa2017-12-11 10:33:46 -0800594status_t NuPlayer2Driver::invoke(const Parcel &request, Parcel *reply) {
595 if (reply == NULL) {
596 ALOGE("reply is a NULL pointer");
597 return BAD_VALUE;
598 }
599
600 int32_t methodId;
601 status_t ret = request.readInt32(&methodId);
602 if (ret != OK) {
Wei Jia12b9f4a2017-12-13 15:24:13 -0800603 ALOGE("Failed to retrieve the requested method to invoke, err(%d)", ret);
Wei Jia53692fa2017-12-11 10:33:46 -0800604 return ret;
605 }
606
607 switch (methodId) {
608 case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
609 {
610 int mode = request.readInt32();
611 return mPlayer->setVideoScalingMode(mode);
612 }
613
614 case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
615 {
616 return mPlayer->getTrackInfo(reply);
617 }
618
619 case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
620 {
621 int trackIndex = request.readInt32();
Wei Jia800fe372018-02-20 15:00:45 -0800622 int64_t msec = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800623 // getCurrentPosition should always return OK
624 getCurrentPosition(&msec);
625 return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll);
626 }
627
628 case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
629 {
630 int trackIndex = request.readInt32();
631 return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
632 }
633
634 case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
635 {
636 int32_t type = request.readInt32();
637 return mPlayer->getSelectedTrack(type, reply);
638 }
639
640 default:
641 {
642 return INVALID_OPERATION;
643 }
644 }
645}
646
647void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
648 mPlayer->setAudioSink(audioSink);
649 mAudioSink = audioSink;
650}
651
652status_t NuPlayer2Driver::setParameter(
653 int /* key */, const Parcel & /* request */) {
654 return INVALID_OPERATION;
655}
656
657status_t NuPlayer2Driver::getParameter(int key, Parcel *reply) {
658
659 if (key == FOURCC('m','t','r','X')) {
660 // mtrX -- a play on 'metrics' (not matrix)
661 // gather current info all together, parcel it, and send it back
662 updateMetrics("api");
663 mAnalyticsItem->writeToParcel(reply);
664 return OK;
665 }
666
667 return INVALID_OPERATION;
668}
669
670status_t NuPlayer2Driver::getMetadata(
671 const media::Metadata::Filter& /* ids */, Parcel *records) {
672 Mutex::Autolock autoLock(mLock);
673
674 using media::Metadata;
675
676 Metadata meta(records);
677
678 meta.appendBool(
679 Metadata::kPauseAvailable,
680 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
681
682 meta.appendBool(
683 Metadata::kSeekBackwardAvailable,
684 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
685
686 meta.appendBool(
687 Metadata::kSeekForwardAvailable,
688 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
689
690 meta.appendBool(
691 Metadata::kSeekAvailable,
692 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
693
694 return OK;
695}
696
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800697void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800698 ALOGD("notifyResetComplete(%p)", this);
699 Mutex::Autolock autoLock(mLock);
700
701 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
702 mState = STATE_IDLE;
703 mCondition.broadcast();
704}
705
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800706void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800707 ALOGV("notifySetSurfaceComplete(%p)", this);
708 Mutex::Autolock autoLock(mLock);
709
710 CHECK(mSetSurfaceInProgress);
711 mSetSurfaceInProgress = false;
712
713 mCondition.broadcast();
714}
715
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800716void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800717 Mutex::Autolock autoLock(mLock);
718 mDurationUs = durationUs;
719}
720
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800721void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800722 Mutex::Autolock autoLock(mLock);
723 mPlayingTimeUs += playingUs;
724}
725
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800726void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800727 Mutex::Autolock autoLock(mLock);
728 mRebufferingTimeUs += rebufferingUs;
729 mRebufferingEvents++;
730}
731
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800732void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
Wei Jia53692fa2017-12-11 10:33:46 -0800733 Mutex::Autolock autoLock(mLock);
734 mRebufferingAtExit = status;
735}
736
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800737void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800738 ALOGV("notifySeekComplete(%p)", this);
739 Mutex::Autolock autoLock(mLock);
740 mSeekInProgress = false;
Wei Jia0151ef42018-08-24 16:40:21 -0700741 notifyListener_l(srcId, MEDIA2_SEEK_COMPLETE);
Wei Jia53692fa2017-12-11 10:33:46 -0800742}
743
744status_t NuPlayer2Driver::dump(
745 int fd, const Vector<String16> & /* args */) const {
746
747 Vector<sp<AMessage> > trackStats;
748 mPlayer->getStats(&trackStats);
749
750 AString logString(" NuPlayer2\n");
751 char buf[256] = {0};
752
753 bool locked = false;
754 for (int i = 0; i < kDumpLockRetries; ++i) {
755 if (mLock.tryLock() == NO_ERROR) {
756 locked = true;
757 break;
758 }
759 usleep(kDumpLockSleepUs);
760 }
761
762 if (locked) {
763 snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
764 mState, mAtEOS, mLooping, mAutoLoop);
765 mLock.unlock();
766 } else {
767 snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
768 }
769 logString.append(buf);
770
771 for (size_t i = 0; i < trackStats.size(); ++i) {
772 const sp<AMessage> &stats = trackStats.itemAt(i);
773
774 AString mime;
775 if (stats->findString("mime", &mime)) {
776 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
777 logString.append(buf);
778 }
779
780 AString name;
781 if (stats->findString("component-name", &name)) {
782 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
783 logString.append(buf);
784 }
785
786 if (mime.startsWith("video/")) {
787 int32_t width, height;
788 if (stats->findInt32("width", &width)
789 && stats->findInt32("height", &height)) {
790 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
791 logString.append(buf);
792 }
793
794 int64_t numFramesTotal = 0;
795 int64_t numFramesDropped = 0;
796
797 stats->findInt64("frames-total", &numFramesTotal);
798 stats->findInt64("frames-dropped-output", &numFramesDropped);
799 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
800 "percentageDropped(%.2f%%)\n",
801 (long long)numFramesTotal,
802 (long long)numFramesDropped,
803 numFramesTotal == 0
804 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
805 logString.append(buf);
806 }
807 }
808
809 ALOGI("%s", logString.c_str());
810
811 if (fd >= 0) {
812 FILE *out = fdopen(dup(fd), "w");
813 fprintf(out, "%s", logString.c_str());
814 fclose(out);
815 out = NULL;
816 }
817
818 return OK;
819}
820
Wei Jia12b9f4a2017-12-13 15:24:13 -0800821void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
822 switch (msg->what()) {
823 case kWhatNotifyListener: {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800824 int64_t srcId;
Wei Jia12b9f4a2017-12-13 15:24:13 -0800825 int32_t msgId;
Wei Jiac5c79da2017-12-21 18:03:05 -0800826 int32_t ext1 = 0;
827 int32_t ext2 = 0;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800828 CHECK(msg->findInt64("srcId", &srcId));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800829 CHECK(msg->findInt32("messageId", &msgId));
Wei Jiac5c79da2017-12-21 18:03:05 -0800830 msg->findInt32("ext1", &ext1);
831 msg->findInt32("ext2", &ext2);
832 sp<ParcelWrapper> in;
833 sp<RefBase> obj;
834 if (msg->findObject("parcel", &obj) && obj != NULL) {
835 in = static_cast<ParcelWrapper *>(obj.get());
836 }
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800837 sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getParcel()));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800838 break;
839 }
840 default:
841 break;
842 }
843}
844
Wei Jia53692fa2017-12-11 10:33:46 -0800845void NuPlayer2Driver::notifyListener(
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800846 int64_t srcId, int msg, int ext1, int ext2, const Parcel *in) {
Wei Jia53692fa2017-12-11 10:33:46 -0800847 Mutex::Autolock autoLock(mLock);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800848 notifyListener_l(srcId, msg, ext1, ext2, in);
Wei Jia53692fa2017-12-11 10:33:46 -0800849}
850
851void NuPlayer2Driver::notifyListener_l(
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800852 int64_t srcId, int msg, int ext1, int ext2, const Parcel *in) {
853 ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
854 this, (long long)srcId, msg, ext1, ext2,
855 (in == NULL ? -1 : (int)in->dataSize()), mAutoLoop, mLooping);
Wei Jia57aeffd2018-02-15 16:01:14 -0800856 if (srcId == mSrcId) {
857 switch (msg) {
858 case MEDIA2_PLAYBACK_COMPLETE:
859 {
860 if (mState != STATE_RESET_IN_PROGRESS) {
861 if (mAutoLoop) {
862 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
863 if (mAudioSink != NULL) {
864 streamType = mAudioSink->getAudioStreamType();
865 }
866 if (streamType == AUDIO_STREAM_NOTIFICATION) {
867 ALOGW("disabling auto-loop for notification");
868 mAutoLoop = false;
869 }
Wei Jia53692fa2017-12-11 10:33:46 -0800870 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800871 if (mLooping || mAutoLoop) {
872 mPlayer->seekToAsync(0);
873 if (mAudioSink != NULL) {
874 // The renderer has stopped the sink at the end in order to play out
875 // the last little bit of audio. In looping mode, we need to restart it.
876 mAudioSink->start();
877 }
Wei Jia9af566a2018-08-10 16:36:35 -0700878
879 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
880 notify->setInt64("srcId", srcId);
881 notify->setInt32("messageId", MEDIA2_INFO);
882 notify->setInt32("ext1", MEDIA2_INFO_DATA_SOURCE_REPEAT);
883 notify->post();
Wei Jia57aeffd2018-02-15 16:01:14 -0800884 return;
Wei Jia53692fa2017-12-11 10:33:46 -0800885 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800886 if (property_get_bool("persist.debug.sf.stats", false)) {
887 Vector<String16> args;
888 dump(-1, args);
Wei Jia53692fa2017-12-11 10:33:46 -0800889 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800890 mPlayer->pause();
891 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800892 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800893 // fall through
Wei Jia53692fa2017-12-11 10:33:46 -0800894 }
Wei Jia53692fa2017-12-11 10:33:46 -0800895
Wei Jia57aeffd2018-02-15 16:01:14 -0800896 case MEDIA2_ERROR:
897 {
898 // when we have an error, add it to the analytics for this playback.
899 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
900 // [test against msg is due to fall through from previous switch value]
901 if (msg == MEDIA2_ERROR) {
902 mAnalyticsItem->setInt32(kPlayerError, ext1);
903 if (ext2 != 0) {
904 mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
905 }
906 mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800907 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800908 mAtEOS = true;
909 break;
Wei Jia53692fa2017-12-11 10:33:46 -0800910 }
Wei Jia53692fa2017-12-11 10:33:46 -0800911
Wei Jia57aeffd2018-02-15 16:01:14 -0800912 default:
913 break;
914 }
Wei Jia53692fa2017-12-11 10:33:46 -0800915 }
916
Wei Jiac5c79da2017-12-21 18:03:05 -0800917 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800918 notify->setInt64("srcId", srcId);
Wei Jiac5c79da2017-12-21 18:03:05 -0800919 notify->setInt32("messageId", msg);
920 notify->setInt32("ext1", ext1);
921 notify->setInt32("ext2", ext2);
922 notify->setObject("parcel", ParcelWrapper::Create(in));
923 notify->post();
Wei Jia12b9f4a2017-12-13 15:24:13 -0800924}
925
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800926void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800927 Mutex::Autolock autoLock(mLock);
928
929 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
930
931 mAsyncResult = err;
932 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
933 mCondition.broadcast();
934}
935
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800936void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800937 ALOGV("notifyPrepareCompleted %d", err);
938
939 Mutex::Autolock autoLock(mLock);
940
Wei Jia57aeffd2018-02-15 16:01:14 -0800941 if (srcId != mSrcId) {
942 if (err == OK) {
943 notifyListener_l(srcId, MEDIA2_PREPARED);
944 } else {
945 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
946 }
947 return;
948 }
949
Wei Jia53692fa2017-12-11 10:33:46 -0800950 if (mState != STATE_PREPARING) {
951 // We were preparing asynchronously when the client called
952 // reset(), we sent a premature "prepared" notification and
953 // then initiated the reset. This notification is stale.
954 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
955 return;
956 }
957
958 CHECK_EQ(mState, STATE_PREPARING);
959
960 mAsyncResult = err;
961
962 if (err == OK) {
963 // update state before notifying client, so that if client calls back into NuPlayer2Driver
964 // in response, NuPlayer2Driver has the right state
965 mState = STATE_PREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800966 notifyListener_l(srcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800967 } else {
968 mState = STATE_UNPREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800969 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
Wei Jia53692fa2017-12-11 10:33:46 -0800970 }
971
972 sp<MetaData> meta = mPlayer->getFileMeta();
973 int32_t loop;
974 if (meta != NULL
975 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
976 mAutoLoop = true;
977 }
978
979 mCondition.broadcast();
980}
981
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800982void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
Wei Jia53692fa2017-12-11 10:33:46 -0800983 Mutex::Autolock autoLock(mLock);
984
985 mPlayerFlags = flags;
986}
987
988// Modular DRM
989status_t NuPlayer2Driver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
990{
991 ALOGV("prepareDrm(%p) state: %d", this, mState);
992
993 // leaving the state verification for mediaplayer.cpp
994 status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
995
996 ALOGV("prepareDrm ret: %d", ret);
997
998 return ret;
999}
1000
1001status_t NuPlayer2Driver::releaseDrm()
1002{
1003 ALOGV("releaseDrm(%p) state: %d", this, mState);
1004
1005 // leaving the state verification for mediaplayer.cpp
1006 status_t ret = mPlayer->releaseDrm();
1007
1008 ALOGV("releaseDrm ret: %d", ret);
1009
1010 return ret;
1011}
1012
Ray Essick51f4c872017-12-15 12:27:56 -08001013std::string NuPlayer2Driver::stateString(State state) {
1014 const char *rval = NULL;
1015 char rawbuffer[16]; // allows "%d"
1016
1017 switch (state) {
1018 case STATE_IDLE: rval = "IDLE"; break;
1019 case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1020 case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1021 case STATE_PREPARING: rval = "PREPARING"; break;
1022 case STATE_PREPARED: rval = "PREPARED"; break;
1023 case STATE_RUNNING: rval = "RUNNING"; break;
1024 case STATE_PAUSED: rval = "PAUSED"; break;
1025 case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
Ray Essick51f4c872017-12-15 12:27:56 -08001026 default:
1027 // yes, this buffer is shared and vulnerable to races
1028 snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1029 rval = rawbuffer;
1030 break;
1031 }
1032
1033 return rval;
1034}
1035
Wei Jia53692fa2017-12-11 10:33:46 -08001036} // namespace android