blob: 821dc9f22dab2a2030dfa6ca48f6435864132f05 [file] [log] [blame]
Wei Jia53692fa2017-12-11 10:33:46 -08001/*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "NuPlayer2Driver"
19#include <inttypes.h>
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -070020#include <android-base/macros.h>
Wei Jia53692fa2017-12-11 10:33:46 -080021#include <utils/Log.h>
22#include <cutils/properties.h>
23
24#include "NuPlayer2Driver.h"
25
26#include "NuPlayer2.h"
27#include "NuPlayer2Source.h"
28
Wei Jiad2bb1bd2018-02-08 09:47:37 -080029#include <media/DataSourceDesc.h>
Wei Jia53692fa2017-12-11 10:33:46 -080030#include <media/stagefright/foundation/ADebug.h>
31#include <media/stagefright/foundation/ALooper.h>
32#include <media/stagefright/foundation/AUtils.h>
33#include <media/stagefright/foundation/ByteUtils.h>
34#include <media/stagefright/MediaClock.h>
35#include <media/stagefright/MetaData.h>
36#include <media/stagefright/Utils.h>
37
38#include <media/IMediaAnalyticsService.h>
39
Dongwon Kang9f631982018-07-10 12:34:41 -070040using google::protobuf::RepeatedPtrField;
41using android::media::MediaPlayer2Proto::Value;
42
Wei Jia53692fa2017-12-11 10:33:46 -080043static const int kDumpLockRetries = 50;
44static const int kDumpLockSleepUs = 20000;
45
46namespace android {
47
Dongwon Kang41929fb2018-09-09 08:29:56 -070048struct PlayerMessageWrapper : public RefBase {
49 static sp<PlayerMessageWrapper> Create(const PlayerMessage *p) {
Wei Jiac5c79da2017-12-21 18:03:05 -080050 if (p != NULL) {
Dongwon Kang41929fb2018-09-09 08:29:56 -070051 sp<PlayerMessageWrapper> pw = new PlayerMessageWrapper();
52 pw->copyFrom(p);
53 return pw;
Wei Jiac5c79da2017-12-21 18:03:05 -080054 }
55 return NULL;
56 }
57
Dongwon Kang41929fb2018-09-09 08:29:56 -070058 const PlayerMessage *getPlayerMessage() {
59 return mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080060 }
61
62protected:
Dongwon Kang41929fb2018-09-09 08:29:56 -070063 virtual ~PlayerMessageWrapper() {
64 if (mPlayerMessage != NULL) {
65 delete mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080066 }
67 }
68
69private:
Dongwon Kang41929fb2018-09-09 08:29:56 -070070 PlayerMessageWrapper()
71 : mPlayerMessage(NULL) { }
Wei Jiac5c79da2017-12-21 18:03:05 -080072
Dongwon Kang41929fb2018-09-09 08:29:56 -070073 void copyFrom(const PlayerMessage *p) {
74 if (mPlayerMessage == NULL) {
75 mPlayerMessage = new PlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080076 }
Dongwon Kang41929fb2018-09-09 08:29:56 -070077 mPlayerMessage->CopyFrom(*p);
Wei Jiac5c79da2017-12-21 18:03:05 -080078 }
79
Dongwon Kang41929fb2018-09-09 08:29:56 -070080 PlayerMessage *mPlayerMessage;
Wei Jiac5c79da2017-12-21 18:03:05 -080081};
82
Wei Jia53692fa2017-12-11 10:33:46 -080083// key for media statistics
Ray Essickee54eef2018-01-24 11:16:54 -080084static const char *kKeyPlayer = "nuplayer";
Wei Jia53692fa2017-12-11 10:33:46 -080085// attrs for media statistics
Ray Essickde15b8c2018-01-30 16:35:56 -080086 // NB: these are matched with public Java API constants defined
87 // in frameworks/base/media/java/android/media/MediaPlayer2.java
88 // These must be kept synchronized with the constants there.
Wei Jia53692fa2017-12-11 10:33:46 -080089static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
90static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
91static const char *kPlayerWidth = "android.media.mediaplayer.width";
92static const char *kPlayerHeight = "android.media.mediaplayer.height";
93static const char *kPlayerFrames = "android.media.mediaplayer.frames";
94static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
95static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
96static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
97static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
98static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
99static const char *kPlayerError = "android.media.mediaplayer.err";
100static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
Ray Essickde15b8c2018-01-30 16:35:56 -0800101
102// NB: These are not yet exposed as public Java API constants.
Ray Essick51f4c872017-12-15 12:27:56 -0800103static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
Wei Jia53692fa2017-12-11 10:33:46 -0800104static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
105//
106static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
107static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
108static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
109
110
Wei Jia003fdb52018-02-06 14:44:32 -0800111NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid)
Wei Jia53692fa2017-12-11 10:33:46 -0800112 : mState(STATE_IDLE),
Wei Jia53692fa2017-12-11 10:33:46 -0800113 mAsyncResult(UNKNOWN_ERROR),
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800114 mSrcId(0),
Wei Jia53692fa2017-12-11 10:33:46 -0800115 mSetSurfaceInProgress(false),
116 mDurationUs(-1),
117 mPositionUs(-1),
118 mSeekInProgress(false),
119 mPlayingTimeUs(0),
120 mRebufferingTimeUs(0),
121 mRebufferingEvents(0),
122 mRebufferingAtExit(false),
123 mLooper(new ALooper),
Wei Jia12b9f4a2017-12-13 15:24:13 -0800124 mNuPlayer2Looper(new ALooper),
Wei Jia53692fa2017-12-11 10:33:46 -0800125 mMediaClock(new MediaClock),
Wei Jia003fdb52018-02-06 14:44:32 -0800126 mPlayer(new NuPlayer2(pid, uid, mMediaClock)),
Wei Jia53692fa2017-12-11 10:33:46 -0800127 mPlayerFlags(0),
128 mAnalyticsItem(NULL),
Wei Jia003fdb52018-02-06 14:44:32 -0800129 mClientUid(uid),
Wei Jia53692fa2017-12-11 10:33:46 -0800130 mAtEOS(false),
131 mLooping(false),
132 mAutoLoop(false) {
133 ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
134 mLooper->setName("NuPlayer2Driver Looper");
Wei Jia12b9f4a2017-12-13 15:24:13 -0800135 mNuPlayer2Looper->setName("NuPlayer2 Looper");
Wei Jia53692fa2017-12-11 10:33:46 -0800136
137 mMediaClock->init();
138
139 // set up an analytics record
140 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
Wei Jia003fdb52018-02-06 14:44:32 -0800141 mAnalyticsItem->setUid(mClientUid);
Wei Jia53692fa2017-12-11 10:33:46 -0800142
Wei Jia12b9f4a2017-12-13 15:24:13 -0800143 mNuPlayer2Looper->start(
Wei Jia53692fa2017-12-11 10:33:46 -0800144 false, /* runOnCallingThread */
145 true, /* canCallJava */
146 PRIORITY_AUDIO);
147
Wei Jia12b9f4a2017-12-13 15:24:13 -0800148 mNuPlayer2Looper->registerHandler(mPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800149
150 mPlayer->setDriver(this);
151}
152
153NuPlayer2Driver::~NuPlayer2Driver() {
154 ALOGV("~NuPlayer2Driver(%p)", this);
Wei Jia12b9f4a2017-12-13 15:24:13 -0800155 mNuPlayer2Looper->stop();
Wei Jia53692fa2017-12-11 10:33:46 -0800156 mLooper->stop();
157
158 // finalize any pending metrics, usually a no-op.
159 updateMetrics("destructor");
160 logMetrics("destructor");
161
162 if (mAnalyticsItem != NULL) {
163 delete mAnalyticsItem;
164 mAnalyticsItem = NULL;
165 }
166}
167
168status_t NuPlayer2Driver::initCheck() {
Wei Jia12b9f4a2017-12-13 15:24:13 -0800169 mLooper->start(
170 false, /* runOnCallingThread */
171 true, /* canCallJava */
172 PRIORITY_AUDIO);
173
174 mLooper->registerHandler(this);
Wei Jia53692fa2017-12-11 10:33:46 -0800175 return OK;
176}
177
Wei Jiac2636032018-02-01 09:15:25 -0800178status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
Wei Jia57aeffd2018-02-15 16:01:14 -0800179 ALOGV("setDataSource(%p)", this);
Wei Jia53692fa2017-12-11 10:33:46 -0800180 Mutex::Autolock autoLock(mLock);
181
182 if (mState != STATE_IDLE) {
183 return INVALID_OPERATION;
184 }
185
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800186 mSrcId = dsd->mId;
Wei Jia53692fa2017-12-11 10:33:46 -0800187 mState = STATE_SET_DATASOURCE_PENDING;
188
Wei Jiac2636032018-02-01 09:15:25 -0800189 mPlayer->setDataSourceAsync(dsd);
Wei Jia53692fa2017-12-11 10:33:46 -0800190
191 while (mState == STATE_SET_DATASOURCE_PENDING) {
192 mCondition.wait(mLock);
193 }
194
195 return mAsyncResult;
196}
197
Wei Jia57aeffd2018-02-15 16:01:14 -0800198status_t NuPlayer2Driver::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
199 ALOGV("prepareNextDataSource(%p)", this);
200 Mutex::Autolock autoLock(mLock);
201
202 mPlayer->prepareNextDataSourceAsync(dsd);
203
204 return OK;
205}
206
207status_t NuPlayer2Driver::playNextDataSource(int64_t srcId) {
208 ALOGV("playNextDataSource(%p)", this);
209 Mutex::Autolock autoLock(mLock);
210
211 mSrcId = srcId;
212 mPlayer->playNextDataSource(srcId);
213
214 return OK;
215}
216
Wei Jia28288fb2017-12-15 13:45:29 -0800217status_t NuPlayer2Driver::setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww) {
Wei Jia53692fa2017-12-11 10:33:46 -0800218 ALOGV("setVideoSurfaceTexture(%p)", this);
219 Mutex::Autolock autoLock(mLock);
220
221 if (mSetSurfaceInProgress) {
222 return INVALID_OPERATION;
223 }
224
225 switch (mState) {
226 case STATE_SET_DATASOURCE_PENDING:
227 case STATE_RESET_IN_PROGRESS:
228 return INVALID_OPERATION;
229
230 default:
231 break;
232 }
233
234 mSetSurfaceInProgress = true;
235
Wei Jia28288fb2017-12-15 13:45:29 -0800236 mPlayer->setVideoSurfaceTextureAsync(nww);
Wei Jia53692fa2017-12-11 10:33:46 -0800237
238 while (mSetSurfaceInProgress) {
239 mCondition.wait(mLock);
240 }
241
242 return OK;
243}
244
245status_t NuPlayer2Driver::getBufferingSettings(BufferingSettings* buffering) {
246 ALOGV("getBufferingSettings(%p)", this);
247 {
248 Mutex::Autolock autoLock(mLock);
249 if (mState == STATE_IDLE) {
250 return INVALID_OPERATION;
251 }
252 }
253
254 return mPlayer->getBufferingSettings(buffering);
255}
256
257status_t NuPlayer2Driver::setBufferingSettings(const BufferingSettings& buffering) {
258 ALOGV("setBufferingSettings(%p)", this);
259 {
260 Mutex::Autolock autoLock(mLock);
261 if (mState == STATE_IDLE) {
262 return INVALID_OPERATION;
263 }
264 }
265
266 return mPlayer->setBufferingSettings(buffering);
267}
268
Wei Jia53692fa2017-12-11 10:33:46 -0800269status_t NuPlayer2Driver::prepareAsync() {
270 ALOGV("prepareAsync(%p)", this);
271 Mutex::Autolock autoLock(mLock);
272
273 switch (mState) {
274 case STATE_UNPREPARED:
275 mState = STATE_PREPARING;
Wei Jia53692fa2017-12-11 10:33:46 -0800276 mPlayer->prepareAsync();
277 return OK;
Wei Jia53692fa2017-12-11 10:33:46 -0800278 default:
279 return INVALID_OPERATION;
280 };
281}
282
283status_t NuPlayer2Driver::start() {
284 ALOGD("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
285 Mutex::Autolock autoLock(mLock);
286 return start_l();
287}
288
289status_t NuPlayer2Driver::start_l() {
290 switch (mState) {
Wei Jia53692fa2017-12-11 10:33:46 -0800291 case STATE_PAUSED:
Wei Jia53692fa2017-12-11 10:33:46 -0800292 case STATE_PREPARED:
293 {
294 mPlayer->start();
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700295 FALLTHROUGH_INTENDED;
Wei Jia53692fa2017-12-11 10:33:46 -0800296 }
297
298 case STATE_RUNNING:
299 {
300 if (mAtEOS) {
Wei Jiad1864f92018-10-19 12:34:56 -0700301 mPlayer->rewind();
Wei Jia53692fa2017-12-11 10:33:46 -0800302 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:
Wei Jia53692fa2017-12-11 10:33:46 -0800330 return OK;
331
Wei Jia6376cd52018-09-26 11:42:55 -0700332 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800333 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);
Wei Jia53692fa2017-12-11 10:33:46 -0800355 }
356 return err;
357}
358
359status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
360 return mPlayer->getPlaybackSettings(rate);
361}
362
363status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
364 return mPlayer->setSyncSettings(sync, videoFpsHint);
365}
366
367status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
368 return mPlayer->getSyncSettings(sync, videoFps);
369}
370
Wei Jia800fe372018-02-20 15:00:45 -0800371status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
372 ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
Wei Jia53692fa2017-12-11 10:33:46 -0800373 Mutex::Autolock autoLock(mLock);
374
375 int64_t seekTimeUs = msec * 1000ll;
376
377 switch (mState) {
378 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800379 case STATE_PAUSED:
380 case STATE_RUNNING:
381 {
382 mAtEOS = false;
383 mSeekInProgress = true;
Wei Jia53692fa2017-12-11 10:33:46 -0800384 mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
385 break;
386 }
387
388 default:
389 return INVALID_OPERATION;
390 }
391
392 mPositionUs = seekTimeUs;
393 return OK;
394}
395
Wei Jia800fe372018-02-20 15:00:45 -0800396status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800397 int64_t tempUs = 0;
398 {
399 Mutex::Autolock autoLock(mLock);
400 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
401 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
Wei Jia800fe372018-02-20 15:00:45 -0800402 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800403 return OK;
404 }
405 }
406
407 status_t ret = mPlayer->getCurrentPosition(&tempUs);
408
409 Mutex::Autolock autoLock(mLock);
410 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
411 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
412 // position value that's different the seek to position.
413 if (ret != OK) {
414 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
415 } else {
416 mPositionUs = tempUs;
417 }
Wei Jia800fe372018-02-20 15:00:45 -0800418 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800419 return OK;
420}
421
Wei Jia800fe372018-02-20 15:00:45 -0800422status_t NuPlayer2Driver::getDuration(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800423 Mutex::Autolock autoLock(mLock);
424
425 if (mDurationUs < 0) {
426 return UNKNOWN_ERROR;
427 }
428
429 *msec = (mDurationUs + 500ll) / 1000;
430
431 return OK;
432}
433
434void NuPlayer2Driver::updateMetrics(const char *where) {
435 if (where == NULL) {
436 where = "unknown";
437 }
438 ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
439
440 // gather the final stats for this record
441 Vector<sp<AMessage>> trackStats;
442 mPlayer->getStats(&trackStats);
443
444 if (trackStats.size() > 0) {
445 for (size_t i = 0; i < trackStats.size(); ++i) {
446 const sp<AMessage> &stats = trackStats.itemAt(i);
447
448 AString mime;
449 stats->findString("mime", &mime);
450
451 AString name;
452 stats->findString("component-name", &name);
453
454 if (mime.startsWith("video/")) {
455 int32_t width, height;
456 mAnalyticsItem->setCString(kPlayerVMime, mime.c_str());
457 if (!name.empty()) {
458 mAnalyticsItem->setCString(kPlayerVCodec, name.c_str());
459 }
460
461 if (stats->findInt32("width", &width)
462 && stats->findInt32("height", &height)) {
463 mAnalyticsItem->setInt32(kPlayerWidth, width);
464 mAnalyticsItem->setInt32(kPlayerHeight, height);
465 }
466
467 int64_t numFramesTotal = 0;
468 int64_t numFramesDropped = 0;
469 stats->findInt64("frames-total", &numFramesTotal);
470 stats->findInt64("frames-dropped-output", &numFramesDropped);
471
472 mAnalyticsItem->setInt64(kPlayerFrames, numFramesTotal);
473 mAnalyticsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
474
475
476 } else if (mime.startsWith("audio/")) {
477 mAnalyticsItem->setCString(kPlayerAMime, mime.c_str());
478 if (!name.empty()) {
479 mAnalyticsItem->setCString(kPlayerACodec, name.c_str());
480 }
481 }
482 }
483 }
484
485 // always provide duration and playing time, even if they have 0/unknown values.
486
487 // getDuration() uses mLock for mutex -- careful where we use it.
Wei Jia800fe372018-02-20 15:00:45 -0800488 int64_t duration_ms = -1;
Wei Jia53692fa2017-12-11 10:33:46 -0800489 getDuration(&duration_ms);
490 mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
491
492 mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
493
494 if (mRebufferingEvents != 0) {
495 mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
496 mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents);
497 mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit);
498 }
499
500 mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
501}
502
503
504void NuPlayer2Driver::logMetrics(const char *where) {
505 if (where == NULL) {
506 where = "unknown";
507 }
508 ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
509
510 if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
511 return;
512 }
513
514 // log only non-empty records
515 // we always updateMetrics() before we get here
516 // and that always injects 3 fields (duration, playing time, and
517 // datasource) into the record.
518 // So the canonical "empty" record has 3 elements in it.
519 if (mAnalyticsItem->count() > 3) {
520
Wei Jia53692fa2017-12-11 10:33:46 -0800521 mAnalyticsItem->selfrecord();
522
523 // re-init in case we prepare() and start() again.
524 delete mAnalyticsItem ;
Ray Essickee54eef2018-01-24 11:16:54 -0800525 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800526 if (mAnalyticsItem) {
Wei Jia53692fa2017-12-11 10:33:46 -0800527 mAnalyticsItem->setUid(mClientUid);
528 }
529 } else {
530 ALOGV("did not have anything to record");
531 }
532}
533
534status_t NuPlayer2Driver::reset() {
535 ALOGD("reset(%p) at state %d", this, mState);
536
537 updateMetrics("reset");
538 logMetrics("reset");
539
540 Mutex::Autolock autoLock(mLock);
541
542 switch (mState) {
543 case STATE_IDLE:
544 return OK;
545
546 case STATE_SET_DATASOURCE_PENDING:
547 case STATE_RESET_IN_PROGRESS:
548 return INVALID_OPERATION;
549
550 case STATE_PREPARING:
551 {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800552 notifyListener_l(mSrcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800553 break;
554 }
555
556 default:
557 break;
558 }
559
Wei Jia53692fa2017-12-11 10:33:46 -0800560 mState = STATE_RESET_IN_PROGRESS;
561 mPlayer->resetAsync();
562
563 while (mState == STATE_RESET_IN_PROGRESS) {
564 mCondition.wait(mLock);
565 }
566
567 mDurationUs = -1;
568 mPositionUs = -1;
569 mLooping = false;
570 mPlayingTimeUs = 0;
571 mRebufferingTimeUs = 0;
572 mRebufferingEvents = 0;
573 mRebufferingAtExit = false;
574
575 return OK;
576}
577
578status_t NuPlayer2Driver::notifyAt(int64_t mediaTimeUs) {
579 ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
580 return mPlayer->notifyAt(mediaTimeUs);
581}
582
583status_t NuPlayer2Driver::setLooping(int loop) {
584 mLooping = loop != 0;
585 return OK;
586}
587
Dongwon Kang9f631982018-07-10 12:34:41 -0700588status_t NuPlayer2Driver::invoke(const PlayerMessage &request, PlayerMessage *response) {
589 if (response == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800590 ALOGE("reply is a NULL pointer");
591 return BAD_VALUE;
592 }
593
Dongwon Kang9f631982018-07-10 12:34:41 -0700594 RepeatedPtrField<const Value>::const_iterator it = request.values().cbegin();
595 int32_t methodId = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800596
597 switch (methodId) {
598 case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
599 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700600 int mode = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800601 return mPlayer->setVideoScalingMode(mode);
602 }
603
604 case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
605 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700606 return mPlayer->getTrackInfo(response);
Wei Jia53692fa2017-12-11 10:33:46 -0800607 }
608
609 case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
610 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700611 int trackIndex = (it++)->int32_value();
Wei Jia800fe372018-02-20 15:00:45 -0800612 int64_t msec = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800613 // getCurrentPosition should always return OK
614 getCurrentPosition(&msec);
615 return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll);
616 }
617
618 case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
619 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700620 int trackIndex = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800621 return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
622 }
623
624 case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
625 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700626 int32_t type = (it++)->int32_value();
627 return mPlayer->getSelectedTrack(type, response);
Wei Jia53692fa2017-12-11 10:33:46 -0800628 }
629
630 default:
631 {
632 return INVALID_OPERATION;
633 }
634 }
635}
636
637void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
638 mPlayer->setAudioSink(audioSink);
639 mAudioSink = audioSink;
640}
641
642status_t NuPlayer2Driver::setParameter(
643 int /* key */, const Parcel & /* request */) {
644 return INVALID_OPERATION;
645}
646
647status_t NuPlayer2Driver::getParameter(int key, Parcel *reply) {
648
649 if (key == FOURCC('m','t','r','X')) {
650 // mtrX -- a play on 'metrics' (not matrix)
651 // gather current info all together, parcel it, and send it back
652 updateMetrics("api");
653 mAnalyticsItem->writeToParcel(reply);
654 return OK;
655 }
656
657 return INVALID_OPERATION;
658}
659
660status_t NuPlayer2Driver::getMetadata(
661 const media::Metadata::Filter& /* ids */, Parcel *records) {
662 Mutex::Autolock autoLock(mLock);
663
664 using media::Metadata;
665
666 Metadata meta(records);
667
668 meta.appendBool(
669 Metadata::kPauseAvailable,
670 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
671
672 meta.appendBool(
673 Metadata::kSeekBackwardAvailable,
674 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
675
676 meta.appendBool(
677 Metadata::kSeekForwardAvailable,
678 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
679
680 meta.appendBool(
681 Metadata::kSeekAvailable,
682 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
683
684 return OK;
685}
686
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800687void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800688 ALOGD("notifyResetComplete(%p)", this);
689 Mutex::Autolock autoLock(mLock);
690
691 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
692 mState = STATE_IDLE;
693 mCondition.broadcast();
694}
695
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800696void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800697 ALOGV("notifySetSurfaceComplete(%p)", this);
698 Mutex::Autolock autoLock(mLock);
699
700 CHECK(mSetSurfaceInProgress);
701 mSetSurfaceInProgress = false;
702
703 mCondition.broadcast();
704}
705
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800706void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800707 Mutex::Autolock autoLock(mLock);
708 mDurationUs = durationUs;
709}
710
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800711void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800712 Mutex::Autolock autoLock(mLock);
713 mPlayingTimeUs += playingUs;
714}
715
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800716void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800717 Mutex::Autolock autoLock(mLock);
718 mRebufferingTimeUs += rebufferingUs;
719 mRebufferingEvents++;
720}
721
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800722void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
Wei Jia53692fa2017-12-11 10:33:46 -0800723 Mutex::Autolock autoLock(mLock);
724 mRebufferingAtExit = status;
725}
726
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800727void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800728 ALOGV("notifySeekComplete(%p)", this);
729 Mutex::Autolock autoLock(mLock);
730 mSeekInProgress = false;
Wei Jia0151ef42018-08-24 16:40:21 -0700731 notifyListener_l(srcId, MEDIA2_SEEK_COMPLETE);
Wei Jia53692fa2017-12-11 10:33:46 -0800732}
733
734status_t NuPlayer2Driver::dump(
735 int fd, const Vector<String16> & /* args */) const {
736
737 Vector<sp<AMessage> > trackStats;
738 mPlayer->getStats(&trackStats);
739
740 AString logString(" NuPlayer2\n");
741 char buf[256] = {0};
742
743 bool locked = false;
744 for (int i = 0; i < kDumpLockRetries; ++i) {
745 if (mLock.tryLock() == NO_ERROR) {
746 locked = true;
747 break;
748 }
749 usleep(kDumpLockSleepUs);
750 }
751
752 if (locked) {
753 snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
754 mState, mAtEOS, mLooping, mAutoLoop);
755 mLock.unlock();
756 } else {
757 snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
758 }
759 logString.append(buf);
760
761 for (size_t i = 0; i < trackStats.size(); ++i) {
762 const sp<AMessage> &stats = trackStats.itemAt(i);
763
764 AString mime;
765 if (stats->findString("mime", &mime)) {
766 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
767 logString.append(buf);
768 }
769
770 AString name;
771 if (stats->findString("component-name", &name)) {
772 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
773 logString.append(buf);
774 }
775
776 if (mime.startsWith("video/")) {
777 int32_t width, height;
778 if (stats->findInt32("width", &width)
779 && stats->findInt32("height", &height)) {
780 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
781 logString.append(buf);
782 }
783
784 int64_t numFramesTotal = 0;
785 int64_t numFramesDropped = 0;
786
787 stats->findInt64("frames-total", &numFramesTotal);
788 stats->findInt64("frames-dropped-output", &numFramesDropped);
789 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
790 "percentageDropped(%.2f%%)\n",
791 (long long)numFramesTotal,
792 (long long)numFramesDropped,
793 numFramesTotal == 0
794 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
795 logString.append(buf);
796 }
797 }
798
799 ALOGI("%s", logString.c_str());
800
801 if (fd >= 0) {
802 FILE *out = fdopen(dup(fd), "w");
803 fprintf(out, "%s", logString.c_str());
804 fclose(out);
805 out = NULL;
806 }
807
808 return OK;
809}
810
Wei Jia12b9f4a2017-12-13 15:24:13 -0800811void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
812 switch (msg->what()) {
813 case kWhatNotifyListener: {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800814 int64_t srcId;
Wei Jia12b9f4a2017-12-13 15:24:13 -0800815 int32_t msgId;
Wei Jiac5c79da2017-12-21 18:03:05 -0800816 int32_t ext1 = 0;
817 int32_t ext2 = 0;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800818 CHECK(msg->findInt64("srcId", &srcId));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800819 CHECK(msg->findInt32("messageId", &msgId));
Wei Jiac5c79da2017-12-21 18:03:05 -0800820 msg->findInt32("ext1", &ext1);
821 msg->findInt32("ext2", &ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700822 sp<PlayerMessageWrapper> in;
Wei Jiac5c79da2017-12-21 18:03:05 -0800823 sp<RefBase> obj;
Dongwon Kang41929fb2018-09-09 08:29:56 -0700824 if (msg->findObject("obj", &obj) && obj != NULL) {
825 in = static_cast<PlayerMessageWrapper *>(obj.get());
Wei Jiac5c79da2017-12-21 18:03:05 -0800826 }
Dongwon Kang41929fb2018-09-09 08:29:56 -0700827 sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getPlayerMessage()));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800828 break;
829 }
830 default:
831 break;
832 }
833}
834
Wei Jia53692fa2017-12-11 10:33:46 -0800835void NuPlayer2Driver::notifyListener(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700836 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jia53692fa2017-12-11 10:33:46 -0800837 Mutex::Autolock autoLock(mLock);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800838 notifyListener_l(srcId, msg, ext1, ext2, in);
Wei Jia53692fa2017-12-11 10:33:46 -0800839}
840
841void NuPlayer2Driver::notifyListener_l(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700842 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800843 ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
844 this, (long long)srcId, msg, ext1, ext2,
Dongwon Kang41929fb2018-09-09 08:29:56 -0700845 (in == NULL ? -1 : (int)in->ByteSize()), mAutoLoop, mLooping);
Wei Jia57aeffd2018-02-15 16:01:14 -0800846 if (srcId == mSrcId) {
847 switch (msg) {
848 case MEDIA2_PLAYBACK_COMPLETE:
849 {
850 if (mState != STATE_RESET_IN_PROGRESS) {
851 if (mAutoLoop) {
852 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
853 if (mAudioSink != NULL) {
854 streamType = mAudioSink->getAudioStreamType();
855 }
856 if (streamType == AUDIO_STREAM_NOTIFICATION) {
857 ALOGW("disabling auto-loop for notification");
858 mAutoLoop = false;
859 }
Wei Jia53692fa2017-12-11 10:33:46 -0800860 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800861 if (mLooping || mAutoLoop) {
Wei Jiad1864f92018-10-19 12:34:56 -0700862 mPlayer->rewind();
Wei Jia57aeffd2018-02-15 16:01:14 -0800863 if (mAudioSink != NULL) {
864 // The renderer has stopped the sink at the end in order to play out
865 // the last little bit of audio. In looping mode, we need to restart it.
866 mAudioSink->start();
867 }
Wei Jia9af566a2018-08-10 16:36:35 -0700868
869 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
870 notify->setInt64("srcId", srcId);
871 notify->setInt32("messageId", MEDIA2_INFO);
872 notify->setInt32("ext1", MEDIA2_INFO_DATA_SOURCE_REPEAT);
873 notify->post();
Wei Jia57aeffd2018-02-15 16:01:14 -0800874 return;
Wei Jia53692fa2017-12-11 10:33:46 -0800875 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800876 if (property_get_bool("persist.debug.sf.stats", false)) {
877 Vector<String16> args;
878 dump(-1, args);
Wei Jia53692fa2017-12-11 10:33:46 -0800879 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800880 mPlayer->pause();
881 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800882 }
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700883 FALLTHROUGH_INTENDED;
Wei Jia53692fa2017-12-11 10:33:46 -0800884 }
Wei Jia53692fa2017-12-11 10:33:46 -0800885
Wei Jia57aeffd2018-02-15 16:01:14 -0800886 case MEDIA2_ERROR:
887 {
888 // when we have an error, add it to the analytics for this playback.
889 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
890 // [test against msg is due to fall through from previous switch value]
891 if (msg == MEDIA2_ERROR) {
892 mAnalyticsItem->setInt32(kPlayerError, ext1);
893 if (ext2 != 0) {
894 mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
895 }
896 mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800897 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800898 mAtEOS = true;
899 break;
Wei Jia53692fa2017-12-11 10:33:46 -0800900 }
Wei Jia53692fa2017-12-11 10:33:46 -0800901
Wei Jia57aeffd2018-02-15 16:01:14 -0800902 default:
903 break;
904 }
Wei Jia53692fa2017-12-11 10:33:46 -0800905 }
906
Wei Jiac5c79da2017-12-21 18:03:05 -0800907 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800908 notify->setInt64("srcId", srcId);
Wei Jiac5c79da2017-12-21 18:03:05 -0800909 notify->setInt32("messageId", msg);
910 notify->setInt32("ext1", ext1);
911 notify->setInt32("ext2", ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700912 notify->setObject("obj", PlayerMessageWrapper::Create((PlayerMessage*)in));
Wei Jiac5c79da2017-12-21 18:03:05 -0800913 notify->post();
Wei Jia12b9f4a2017-12-13 15:24:13 -0800914}
915
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800916void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800917 Mutex::Autolock autoLock(mLock);
918
919 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
920
921 mAsyncResult = err;
922 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
923 mCondition.broadcast();
924}
925
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800926void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800927 ALOGV("notifyPrepareCompleted %d", err);
928
929 Mutex::Autolock autoLock(mLock);
930
Wei Jia57aeffd2018-02-15 16:01:14 -0800931 if (srcId != mSrcId) {
932 if (err == OK) {
933 notifyListener_l(srcId, MEDIA2_PREPARED);
934 } else {
935 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
936 }
937 return;
938 }
939
Wei Jia53692fa2017-12-11 10:33:46 -0800940 if (mState != STATE_PREPARING) {
941 // We were preparing asynchronously when the client called
942 // reset(), we sent a premature "prepared" notification and
943 // then initiated the reset. This notification is stale.
944 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
945 return;
946 }
947
948 CHECK_EQ(mState, STATE_PREPARING);
949
950 mAsyncResult = err;
951
952 if (err == OK) {
953 // update state before notifying client, so that if client calls back into NuPlayer2Driver
954 // in response, NuPlayer2Driver has the right state
955 mState = STATE_PREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800956 notifyListener_l(srcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800957 } else {
958 mState = STATE_UNPREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800959 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
Wei Jia53692fa2017-12-11 10:33:46 -0800960 }
961
962 sp<MetaData> meta = mPlayer->getFileMeta();
963 int32_t loop;
964 if (meta != NULL
965 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
966 mAutoLoop = true;
967 }
968
969 mCondition.broadcast();
970}
971
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800972void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
Wei Jia53692fa2017-12-11 10:33:46 -0800973 Mutex::Autolock autoLock(mLock);
974
975 mPlayerFlags = flags;
976}
977
978// Modular DRM
979status_t NuPlayer2Driver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
980{
981 ALOGV("prepareDrm(%p) state: %d", this, mState);
982
983 // leaving the state verification for mediaplayer.cpp
984 status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
985
986 ALOGV("prepareDrm ret: %d", ret);
987
988 return ret;
989}
990
991status_t NuPlayer2Driver::releaseDrm()
992{
993 ALOGV("releaseDrm(%p) state: %d", this, mState);
994
995 // leaving the state verification for mediaplayer.cpp
996 status_t ret = mPlayer->releaseDrm();
997
998 ALOGV("releaseDrm ret: %d", ret);
999
1000 return ret;
1001}
1002
Ray Essick51f4c872017-12-15 12:27:56 -08001003std::string NuPlayer2Driver::stateString(State state) {
1004 const char *rval = NULL;
1005 char rawbuffer[16]; // allows "%d"
1006
1007 switch (state) {
1008 case STATE_IDLE: rval = "IDLE"; break;
1009 case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1010 case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1011 case STATE_PREPARING: rval = "PREPARING"; break;
1012 case STATE_PREPARED: rval = "PREPARED"; break;
1013 case STATE_RUNNING: rval = "RUNNING"; break;
1014 case STATE_PAUSED: rval = "PAUSED"; break;
1015 case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
Ray Essick51f4c872017-12-15 12:27:56 -08001016 default:
1017 // yes, this buffer is shared and vulnerable to races
1018 snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1019 rval = rawbuffer;
1020 break;
1021 }
1022
1023 return rval;
1024}
1025
Wei Jia53692fa2017-12-11 10:33:46 -08001026} // namespace android