blob: 03d17a52620f78d6b4e6a773afcca25c8e3c0440 [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;
275 case STATE_STOPPED:
276 // this is really just paused. handle as seek to start
277 mAtEOS = false;
278 mState = STATE_STOPPED_AND_PREPARING;
Wei Jia53692fa2017-12-11 10:33:46 -0800279 mPlayer->seekToAsync(0, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */,
280 true /* needNotify */);
281 return OK;
282 default:
283 return INVALID_OPERATION;
284 };
285}
286
287status_t NuPlayer2Driver::start() {
288 ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
289 Mutex::Autolock autoLock(mLock);
290 return start_l();
291}
292
293status_t NuPlayer2Driver::start_l() {
294 switch (mState) {
Wei Jia53692fa2017-12-11 10:33:46 -0800295 case STATE_PAUSED:
296 case STATE_STOPPED_AND_PREPARED:
297 case STATE_PREPARED:
298 {
299 mPlayer->start();
300
301 // fall through
302 }
303
304 case STATE_RUNNING:
305 {
306 if (mAtEOS) {
307 mPlayer->seekToAsync(0);
308 mAtEOS = false;
309 mPositionUs = -1;
310 }
311 break;
312 }
313
314 default:
315 return INVALID_OPERATION;
316 }
317
318 mState = STATE_RUNNING;
319
320 return OK;
321}
322
323status_t NuPlayer2Driver::stop() {
324 ALOGD("stop(%p)", this);
325 Mutex::Autolock autoLock(mLock);
326
327 switch (mState) {
328 case STATE_RUNNING:
329 mPlayer->pause();
330 // fall through
331
332 case STATE_PAUSED:
333 mState = STATE_STOPPED;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800334 //notifyListener_l(MEDIA2_STOPPED);
Wei Jia53692fa2017-12-11 10:33:46 -0800335 break;
336
337 case STATE_PREPARED:
338 case STATE_STOPPED:
339 case STATE_STOPPED_AND_PREPARING:
340 case STATE_STOPPED_AND_PREPARED:
341 mState = STATE_STOPPED;
342 break;
343
344 default:
345 return INVALID_OPERATION;
346 }
347
348 return OK;
349}
350
351status_t NuPlayer2Driver::pause() {
352 ALOGD("pause(%p)", this);
353 // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
354 // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
355 // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
356 // getCurrentPosition here.
Wei Jia800fe372018-02-20 15:00:45 -0800357 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800358 getCurrentPosition(&unused);
359
360 Mutex::Autolock autoLock(mLock);
361
362 switch (mState) {
363 case STATE_PAUSED:
364 case STATE_PREPARED:
365 return OK;
366
367 case STATE_RUNNING:
368 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800369 mPlayer->pause();
370 break;
371
372 default:
373 return INVALID_OPERATION;
374 }
375
376 return OK;
377}
378
379bool NuPlayer2Driver::isPlaying() {
380 return mState == STATE_RUNNING && !mAtEOS;
381}
382
383status_t NuPlayer2Driver::setPlaybackSettings(const AudioPlaybackRate &rate) {
384 status_t err = mPlayer->setPlaybackSettings(rate);
385 if (err == OK) {
386 // try to update position
Wei Jia800fe372018-02-20 15:00:45 -0800387 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800388 getCurrentPosition(&unused);
389 Mutex::Autolock autoLock(mLock);
390 if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
391 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800392 } else if (rate.mSpeed != 0.f
393 && (mState == STATE_PAUSED
394 || mState == STATE_STOPPED_AND_PREPARED
395 || mState == STATE_PREPARED)) {
396 err = start_l();
397 }
398 }
399 return err;
400}
401
402status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
403 return mPlayer->getPlaybackSettings(rate);
404}
405
406status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
407 return mPlayer->setSyncSettings(sync, videoFpsHint);
408}
409
410status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
411 return mPlayer->getSyncSettings(sync, videoFps);
412}
413
Wei Jia800fe372018-02-20 15:00:45 -0800414status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
415 ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
Wei Jia53692fa2017-12-11 10:33:46 -0800416 Mutex::Autolock autoLock(mLock);
417
418 int64_t seekTimeUs = msec * 1000ll;
419
420 switch (mState) {
421 case STATE_PREPARED:
422 case STATE_STOPPED_AND_PREPARED:
423 case STATE_PAUSED:
424 case STATE_RUNNING:
425 {
426 mAtEOS = false;
427 mSeekInProgress = true;
Wei Jia53692fa2017-12-11 10:33:46 -0800428 mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
429 break;
430 }
431
432 default:
433 return INVALID_OPERATION;
434 }
435
436 mPositionUs = seekTimeUs;
437 return OK;
438}
439
Wei Jia800fe372018-02-20 15:00:45 -0800440status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800441 int64_t tempUs = 0;
442 {
443 Mutex::Autolock autoLock(mLock);
444 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
445 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
Wei Jia800fe372018-02-20 15:00:45 -0800446 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800447 return OK;
448 }
449 }
450
451 status_t ret = mPlayer->getCurrentPosition(&tempUs);
452
453 Mutex::Autolock autoLock(mLock);
454 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
455 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
456 // position value that's different the seek to position.
457 if (ret != OK) {
458 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
459 } else {
460 mPositionUs = tempUs;
461 }
Wei Jia800fe372018-02-20 15:00:45 -0800462 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800463 return OK;
464}
465
Wei Jia800fe372018-02-20 15:00:45 -0800466status_t NuPlayer2Driver::getDuration(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800467 Mutex::Autolock autoLock(mLock);
468
469 if (mDurationUs < 0) {
470 return UNKNOWN_ERROR;
471 }
472
473 *msec = (mDurationUs + 500ll) / 1000;
474
475 return OK;
476}
477
478void NuPlayer2Driver::updateMetrics(const char *where) {
479 if (where == NULL) {
480 where = "unknown";
481 }
482 ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
483
484 // gather the final stats for this record
485 Vector<sp<AMessage>> trackStats;
486 mPlayer->getStats(&trackStats);
487
488 if (trackStats.size() > 0) {
489 for (size_t i = 0; i < trackStats.size(); ++i) {
490 const sp<AMessage> &stats = trackStats.itemAt(i);
491
492 AString mime;
493 stats->findString("mime", &mime);
494
495 AString name;
496 stats->findString("component-name", &name);
497
498 if (mime.startsWith("video/")) {
499 int32_t width, height;
500 mAnalyticsItem->setCString(kPlayerVMime, mime.c_str());
501 if (!name.empty()) {
502 mAnalyticsItem->setCString(kPlayerVCodec, name.c_str());
503 }
504
505 if (stats->findInt32("width", &width)
506 && stats->findInt32("height", &height)) {
507 mAnalyticsItem->setInt32(kPlayerWidth, width);
508 mAnalyticsItem->setInt32(kPlayerHeight, height);
509 }
510
511 int64_t numFramesTotal = 0;
512 int64_t numFramesDropped = 0;
513 stats->findInt64("frames-total", &numFramesTotal);
514 stats->findInt64("frames-dropped-output", &numFramesDropped);
515
516 mAnalyticsItem->setInt64(kPlayerFrames, numFramesTotal);
517 mAnalyticsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
518
519
520 } else if (mime.startsWith("audio/")) {
521 mAnalyticsItem->setCString(kPlayerAMime, mime.c_str());
522 if (!name.empty()) {
523 mAnalyticsItem->setCString(kPlayerACodec, name.c_str());
524 }
525 }
526 }
527 }
528
529 // always provide duration and playing time, even if they have 0/unknown values.
530
531 // getDuration() uses mLock for mutex -- careful where we use it.
Wei Jia800fe372018-02-20 15:00:45 -0800532 int64_t duration_ms = -1;
Wei Jia53692fa2017-12-11 10:33:46 -0800533 getDuration(&duration_ms);
534 mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
535
536 mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
537
538 if (mRebufferingEvents != 0) {
539 mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
540 mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents);
541 mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit);
542 }
543
544 mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
545}
546
547
548void NuPlayer2Driver::logMetrics(const char *where) {
549 if (where == NULL) {
550 where = "unknown";
551 }
552 ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
553
554 if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
555 return;
556 }
557
558 // log only non-empty records
559 // we always updateMetrics() before we get here
560 // and that always injects 3 fields (duration, playing time, and
561 // datasource) into the record.
562 // So the canonical "empty" record has 3 elements in it.
563 if (mAnalyticsItem->count() > 3) {
564
Wei Jia53692fa2017-12-11 10:33:46 -0800565 mAnalyticsItem->selfrecord();
566
567 // re-init in case we prepare() and start() again.
568 delete mAnalyticsItem ;
Ray Essickee54eef2018-01-24 11:16:54 -0800569 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800570 if (mAnalyticsItem) {
Wei Jia53692fa2017-12-11 10:33:46 -0800571 mAnalyticsItem->setUid(mClientUid);
572 }
573 } else {
574 ALOGV("did not have anything to record");
575 }
576}
577
578status_t NuPlayer2Driver::reset() {
579 ALOGD("reset(%p) at state %d", this, mState);
580
581 updateMetrics("reset");
582 logMetrics("reset");
583
584 Mutex::Autolock autoLock(mLock);
585
586 switch (mState) {
587 case STATE_IDLE:
588 return OK;
589
590 case STATE_SET_DATASOURCE_PENDING:
591 case STATE_RESET_IN_PROGRESS:
592 return INVALID_OPERATION;
593
594 case STATE_PREPARING:
595 {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800596 notifyListener_l(mSrcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800597 break;
598 }
599
600 default:
601 break;
602 }
603
604 if (mState != STATE_STOPPED) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800605 // notifyListener_l(MEDIA2_STOPPED);
Wei Jia53692fa2017-12-11 10:33:46 -0800606 }
607
608 mState = STATE_RESET_IN_PROGRESS;
609 mPlayer->resetAsync();
610
611 while (mState == STATE_RESET_IN_PROGRESS) {
612 mCondition.wait(mLock);
613 }
614
615 mDurationUs = -1;
616 mPositionUs = -1;
617 mLooping = false;
618 mPlayingTimeUs = 0;
619 mRebufferingTimeUs = 0;
620 mRebufferingEvents = 0;
621 mRebufferingAtExit = false;
622
623 return OK;
624}
625
626status_t NuPlayer2Driver::notifyAt(int64_t mediaTimeUs) {
627 ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
628 return mPlayer->notifyAt(mediaTimeUs);
629}
630
631status_t NuPlayer2Driver::setLooping(int loop) {
632 mLooping = loop != 0;
633 return OK;
634}
635
Wei Jia53692fa2017-12-11 10:33:46 -0800636status_t NuPlayer2Driver::invoke(const Parcel &request, Parcel *reply) {
637 if (reply == NULL) {
638 ALOGE("reply is a NULL pointer");
639 return BAD_VALUE;
640 }
641
642 int32_t methodId;
643 status_t ret = request.readInt32(&methodId);
644 if (ret != OK) {
Wei Jia12b9f4a2017-12-13 15:24:13 -0800645 ALOGE("Failed to retrieve the requested method to invoke, err(%d)", ret);
Wei Jia53692fa2017-12-11 10:33:46 -0800646 return ret;
647 }
648
649 switch (methodId) {
650 case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
651 {
652 int mode = request.readInt32();
653 return mPlayer->setVideoScalingMode(mode);
654 }
655
656 case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
657 {
658 return mPlayer->getTrackInfo(reply);
659 }
660
661 case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
662 {
663 int trackIndex = request.readInt32();
Wei Jia800fe372018-02-20 15:00:45 -0800664 int64_t msec = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800665 // getCurrentPosition should always return OK
666 getCurrentPosition(&msec);
667 return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll);
668 }
669
670 case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
671 {
672 int trackIndex = request.readInt32();
673 return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
674 }
675
676 case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
677 {
678 int32_t type = request.readInt32();
679 return mPlayer->getSelectedTrack(type, reply);
680 }
681
682 default:
683 {
684 return INVALID_OPERATION;
685 }
686 }
687}
688
689void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
690 mPlayer->setAudioSink(audioSink);
691 mAudioSink = audioSink;
692}
693
694status_t NuPlayer2Driver::setParameter(
695 int /* key */, const Parcel & /* request */) {
696 return INVALID_OPERATION;
697}
698
699status_t NuPlayer2Driver::getParameter(int key, Parcel *reply) {
700
701 if (key == FOURCC('m','t','r','X')) {
702 // mtrX -- a play on 'metrics' (not matrix)
703 // gather current info all together, parcel it, and send it back
704 updateMetrics("api");
705 mAnalyticsItem->writeToParcel(reply);
706 return OK;
707 }
708
709 return INVALID_OPERATION;
710}
711
712status_t NuPlayer2Driver::getMetadata(
713 const media::Metadata::Filter& /* ids */, Parcel *records) {
714 Mutex::Autolock autoLock(mLock);
715
716 using media::Metadata;
717
718 Metadata meta(records);
719
720 meta.appendBool(
721 Metadata::kPauseAvailable,
722 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
723
724 meta.appendBool(
725 Metadata::kSeekBackwardAvailable,
726 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
727
728 meta.appendBool(
729 Metadata::kSeekForwardAvailable,
730 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
731
732 meta.appendBool(
733 Metadata::kSeekAvailable,
734 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
735
736 return OK;
737}
738
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800739void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800740 ALOGD("notifyResetComplete(%p)", this);
741 Mutex::Autolock autoLock(mLock);
742
743 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
744 mState = STATE_IDLE;
745 mCondition.broadcast();
746}
747
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800748void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800749 ALOGV("notifySetSurfaceComplete(%p)", this);
750 Mutex::Autolock autoLock(mLock);
751
752 CHECK(mSetSurfaceInProgress);
753 mSetSurfaceInProgress = false;
754
755 mCondition.broadcast();
756}
757
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800758void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800759 Mutex::Autolock autoLock(mLock);
760 mDurationUs = durationUs;
761}
762
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800763void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800764 Mutex::Autolock autoLock(mLock);
765 mPlayingTimeUs += playingUs;
766}
767
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800768void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800769 Mutex::Autolock autoLock(mLock);
770 mRebufferingTimeUs += rebufferingUs;
771 mRebufferingEvents++;
772}
773
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800774void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
Wei Jia53692fa2017-12-11 10:33:46 -0800775 Mutex::Autolock autoLock(mLock);
776 mRebufferingAtExit = status;
777}
778
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800779void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800780 ALOGV("notifySeekComplete(%p)", this);
781 Mutex::Autolock autoLock(mLock);
782 mSeekInProgress = false;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800783 notifySeekComplete_l(srcId);
Wei Jia53692fa2017-12-11 10:33:46 -0800784}
785
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800786void NuPlayer2Driver::notifySeekComplete_l(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800787 bool wasSeeking = true;
788 if (mState == STATE_STOPPED_AND_PREPARING) {
789 wasSeeking = false;
790 mState = STATE_STOPPED_AND_PREPARED;
791 mCondition.broadcast();
Wei Jia53692fa2017-12-11 10:33:46 -0800792 } else if (mState == STATE_STOPPED) {
793 // no need to notify listener
794 return;
795 }
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800796 notifyListener_l(srcId, wasSeeking ? MEDIA2_SEEK_COMPLETE : MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800797}
798
799status_t NuPlayer2Driver::dump(
800 int fd, const Vector<String16> & /* args */) const {
801
802 Vector<sp<AMessage> > trackStats;
803 mPlayer->getStats(&trackStats);
804
805 AString logString(" NuPlayer2\n");
806 char buf[256] = {0};
807
808 bool locked = false;
809 for (int i = 0; i < kDumpLockRetries; ++i) {
810 if (mLock.tryLock() == NO_ERROR) {
811 locked = true;
812 break;
813 }
814 usleep(kDumpLockSleepUs);
815 }
816
817 if (locked) {
818 snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
819 mState, mAtEOS, mLooping, mAutoLoop);
820 mLock.unlock();
821 } else {
822 snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
823 }
824 logString.append(buf);
825
826 for (size_t i = 0; i < trackStats.size(); ++i) {
827 const sp<AMessage> &stats = trackStats.itemAt(i);
828
829 AString mime;
830 if (stats->findString("mime", &mime)) {
831 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
832 logString.append(buf);
833 }
834
835 AString name;
836 if (stats->findString("component-name", &name)) {
837 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
838 logString.append(buf);
839 }
840
841 if (mime.startsWith("video/")) {
842 int32_t width, height;
843 if (stats->findInt32("width", &width)
844 && stats->findInt32("height", &height)) {
845 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
846 logString.append(buf);
847 }
848
849 int64_t numFramesTotal = 0;
850 int64_t numFramesDropped = 0;
851
852 stats->findInt64("frames-total", &numFramesTotal);
853 stats->findInt64("frames-dropped-output", &numFramesDropped);
854 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
855 "percentageDropped(%.2f%%)\n",
856 (long long)numFramesTotal,
857 (long long)numFramesDropped,
858 numFramesTotal == 0
859 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
860 logString.append(buf);
861 }
862 }
863
864 ALOGI("%s", logString.c_str());
865
866 if (fd >= 0) {
867 FILE *out = fdopen(dup(fd), "w");
868 fprintf(out, "%s", logString.c_str());
869 fclose(out);
870 out = NULL;
871 }
872
873 return OK;
874}
875
Wei Jia12b9f4a2017-12-13 15:24:13 -0800876void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
877 switch (msg->what()) {
878 case kWhatNotifyListener: {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800879 int64_t srcId;
Wei Jia12b9f4a2017-12-13 15:24:13 -0800880 int32_t msgId;
Wei Jiac5c79da2017-12-21 18:03:05 -0800881 int32_t ext1 = 0;
882 int32_t ext2 = 0;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800883 CHECK(msg->findInt64("srcId", &srcId));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800884 CHECK(msg->findInt32("messageId", &msgId));
Wei Jiac5c79da2017-12-21 18:03:05 -0800885 msg->findInt32("ext1", &ext1);
886 msg->findInt32("ext2", &ext2);
887 sp<ParcelWrapper> in;
888 sp<RefBase> obj;
889 if (msg->findObject("parcel", &obj) && obj != NULL) {
890 in = static_cast<ParcelWrapper *>(obj.get());
891 }
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800892 sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getParcel()));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800893 break;
894 }
895 default:
896 break;
897 }
898}
899
Wei Jia53692fa2017-12-11 10:33:46 -0800900void NuPlayer2Driver::notifyListener(
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800901 int64_t srcId, int msg, int ext1, int ext2, const Parcel *in) {
Wei Jia53692fa2017-12-11 10:33:46 -0800902 Mutex::Autolock autoLock(mLock);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800903 notifyListener_l(srcId, msg, ext1, ext2, in);
Wei Jia53692fa2017-12-11 10:33:46 -0800904}
905
906void NuPlayer2Driver::notifyListener_l(
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800907 int64_t srcId, int msg, int ext1, int ext2, const Parcel *in) {
908 ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
909 this, (long long)srcId, msg, ext1, ext2,
910 (in == NULL ? -1 : (int)in->dataSize()), mAutoLoop, mLooping);
Wei Jia57aeffd2018-02-15 16:01:14 -0800911 if (srcId == mSrcId) {
912 switch (msg) {
913 case MEDIA2_PLAYBACK_COMPLETE:
914 {
915 if (mState != STATE_RESET_IN_PROGRESS) {
916 if (mAutoLoop) {
917 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
918 if (mAudioSink != NULL) {
919 streamType = mAudioSink->getAudioStreamType();
920 }
921 if (streamType == AUDIO_STREAM_NOTIFICATION) {
922 ALOGW("disabling auto-loop for notification");
923 mAutoLoop = false;
924 }
Wei Jia53692fa2017-12-11 10:33:46 -0800925 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800926 if (mLooping || mAutoLoop) {
927 mPlayer->seekToAsync(0);
928 if (mAudioSink != NULL) {
929 // The renderer has stopped the sink at the end in order to play out
930 // the last little bit of audio. In looping mode, we need to restart it.
931 mAudioSink->start();
932 }
933 // don't send completion event when looping
934 return;
Wei Jia53692fa2017-12-11 10:33:46 -0800935 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800936 if (property_get_bool("persist.debug.sf.stats", false)) {
937 Vector<String16> args;
938 dump(-1, args);
Wei Jia53692fa2017-12-11 10:33:46 -0800939 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800940 mPlayer->pause();
941 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800942 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800943 // fall through
Wei Jia53692fa2017-12-11 10:33:46 -0800944 }
Wei Jia53692fa2017-12-11 10:33:46 -0800945
Wei Jia57aeffd2018-02-15 16:01:14 -0800946 case MEDIA2_ERROR:
947 {
948 // when we have an error, add it to the analytics for this playback.
949 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
950 // [test against msg is due to fall through from previous switch value]
951 if (msg == MEDIA2_ERROR) {
952 mAnalyticsItem->setInt32(kPlayerError, ext1);
953 if (ext2 != 0) {
954 mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
955 }
956 mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800957 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800958 mAtEOS = true;
959 break;
Wei Jia53692fa2017-12-11 10:33:46 -0800960 }
Wei Jia53692fa2017-12-11 10:33:46 -0800961
Wei Jia57aeffd2018-02-15 16:01:14 -0800962 default:
963 break;
964 }
Wei Jia53692fa2017-12-11 10:33:46 -0800965 }
966
Wei Jiac5c79da2017-12-21 18:03:05 -0800967 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800968 notify->setInt64("srcId", srcId);
Wei Jiac5c79da2017-12-21 18:03:05 -0800969 notify->setInt32("messageId", msg);
970 notify->setInt32("ext1", ext1);
971 notify->setInt32("ext2", ext2);
972 notify->setObject("parcel", ParcelWrapper::Create(in));
973 notify->post();
Wei Jia12b9f4a2017-12-13 15:24:13 -0800974}
975
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800976void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800977 Mutex::Autolock autoLock(mLock);
978
979 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
980
981 mAsyncResult = err;
982 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
983 mCondition.broadcast();
984}
985
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800986void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800987 ALOGV("notifyPrepareCompleted %d", err);
988
989 Mutex::Autolock autoLock(mLock);
990
Wei Jia57aeffd2018-02-15 16:01:14 -0800991 if (srcId != mSrcId) {
992 if (err == OK) {
993 notifyListener_l(srcId, MEDIA2_PREPARED);
994 } else {
995 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
996 }
997 return;
998 }
999
Wei Jia53692fa2017-12-11 10:33:46 -08001000 if (mState != STATE_PREPARING) {
1001 // We were preparing asynchronously when the client called
1002 // reset(), we sent a premature "prepared" notification and
1003 // then initiated the reset. This notification is stale.
1004 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
1005 return;
1006 }
1007
1008 CHECK_EQ(mState, STATE_PREPARING);
1009
1010 mAsyncResult = err;
1011
1012 if (err == OK) {
1013 // update state before notifying client, so that if client calls back into NuPlayer2Driver
1014 // in response, NuPlayer2Driver has the right state
1015 mState = STATE_PREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -08001016 notifyListener_l(srcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -08001017 } else {
1018 mState = STATE_UNPREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -08001019 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
Wei Jia53692fa2017-12-11 10:33:46 -08001020 }
1021
1022 sp<MetaData> meta = mPlayer->getFileMeta();
1023 int32_t loop;
1024 if (meta != NULL
1025 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
1026 mAutoLoop = true;
1027 }
1028
1029 mCondition.broadcast();
1030}
1031
Wei Jiad2bb1bd2018-02-08 09:47:37 -08001032void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
Wei Jia53692fa2017-12-11 10:33:46 -08001033 Mutex::Autolock autoLock(mLock);
1034
1035 mPlayerFlags = flags;
1036}
1037
1038// Modular DRM
1039status_t NuPlayer2Driver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
1040{
1041 ALOGV("prepareDrm(%p) state: %d", this, mState);
1042
1043 // leaving the state verification for mediaplayer.cpp
1044 status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
1045
1046 ALOGV("prepareDrm ret: %d", ret);
1047
1048 return ret;
1049}
1050
1051status_t NuPlayer2Driver::releaseDrm()
1052{
1053 ALOGV("releaseDrm(%p) state: %d", this, mState);
1054
1055 // leaving the state verification for mediaplayer.cpp
1056 status_t ret = mPlayer->releaseDrm();
1057
1058 ALOGV("releaseDrm ret: %d", ret);
1059
1060 return ret;
1061}
1062
Ray Essick51f4c872017-12-15 12:27:56 -08001063std::string NuPlayer2Driver::stateString(State state) {
1064 const char *rval = NULL;
1065 char rawbuffer[16]; // allows "%d"
1066
1067 switch (state) {
1068 case STATE_IDLE: rval = "IDLE"; break;
1069 case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1070 case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1071 case STATE_PREPARING: rval = "PREPARING"; break;
1072 case STATE_PREPARED: rval = "PREPARED"; break;
1073 case STATE_RUNNING: rval = "RUNNING"; break;
1074 case STATE_PAUSED: rval = "PAUSED"; break;
1075 case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
1076 case STATE_STOPPED: rval = "STOPPED"; break;
1077 case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
1078 case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
1079 default:
1080 // yes, this buffer is shared and vulnerable to races
1081 snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1082 rval = rawbuffer;
1083 break;
1084 }
1085
1086 return rval;
1087}
1088
Wei Jia53692fa2017-12-11 10:33:46 -08001089} // namespace android