blob: d3be53ab325f61b94af18ce19aa37200aebf97d1 [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) {
301 mPlayer->seekToAsync(0);
302 mAtEOS = false;
303 mPositionUs = -1;
304 }
305 break;
306 }
307
308 default:
309 return INVALID_OPERATION;
310 }
311
312 mState = STATE_RUNNING;
313
314 return OK;
315}
316
Wei Jia53692fa2017-12-11 10:33:46 -0800317status_t NuPlayer2Driver::pause() {
318 ALOGD("pause(%p)", this);
319 // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
320 // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
321 // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
322 // getCurrentPosition here.
Wei Jia800fe372018-02-20 15:00:45 -0800323 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800324 getCurrentPosition(&unused);
325
326 Mutex::Autolock autoLock(mLock);
327
328 switch (mState) {
329 case STATE_PAUSED:
330 case STATE_PREPARED:
331 return OK;
332
333 case STATE_RUNNING:
334 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800335 mPlayer->pause();
336 break;
337
338 default:
339 return INVALID_OPERATION;
340 }
341
342 return OK;
343}
344
345bool NuPlayer2Driver::isPlaying() {
346 return mState == STATE_RUNNING && !mAtEOS;
347}
348
349status_t NuPlayer2Driver::setPlaybackSettings(const AudioPlaybackRate &rate) {
350 status_t err = mPlayer->setPlaybackSettings(rate);
351 if (err == OK) {
352 // try to update position
Wei Jia800fe372018-02-20 15:00:45 -0800353 int64_t unused;
Wei Jia53692fa2017-12-11 10:33:46 -0800354 getCurrentPosition(&unused);
355 Mutex::Autolock autoLock(mLock);
356 if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
357 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800358 } else if (rate.mSpeed != 0.f
359 && (mState == STATE_PAUSED
Wei Jia53692fa2017-12-11 10:33:46 -0800360 || mState == STATE_PREPARED)) {
361 err = start_l();
362 }
363 }
364 return err;
365}
366
367status_t NuPlayer2Driver::getPlaybackSettings(AudioPlaybackRate *rate) {
368 return mPlayer->getPlaybackSettings(rate);
369}
370
371status_t NuPlayer2Driver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
372 return mPlayer->setSyncSettings(sync, videoFpsHint);
373}
374
375status_t NuPlayer2Driver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
376 return mPlayer->getSyncSettings(sync, videoFps);
377}
378
Wei Jia800fe372018-02-20 15:00:45 -0800379status_t NuPlayer2Driver::seekTo(int64_t msec, MediaPlayer2SeekMode mode) {
380 ALOGD("seekTo(%p) (%lld ms, %d) at state %d", this, (long long)msec, mode, mState);
Wei Jia53692fa2017-12-11 10:33:46 -0800381 Mutex::Autolock autoLock(mLock);
382
383 int64_t seekTimeUs = msec * 1000ll;
384
385 switch (mState) {
386 case STATE_PREPARED:
Wei Jia53692fa2017-12-11 10:33:46 -0800387 case STATE_PAUSED:
388 case STATE_RUNNING:
389 {
390 mAtEOS = false;
391 mSeekInProgress = true;
Wei Jia53692fa2017-12-11 10:33:46 -0800392 mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
393 break;
394 }
395
396 default:
397 return INVALID_OPERATION;
398 }
399
400 mPositionUs = seekTimeUs;
401 return OK;
402}
403
Wei Jia800fe372018-02-20 15:00:45 -0800404status_t NuPlayer2Driver::getCurrentPosition(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800405 int64_t tempUs = 0;
406 {
407 Mutex::Autolock autoLock(mLock);
408 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
409 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
Wei Jia800fe372018-02-20 15:00:45 -0800410 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800411 return OK;
412 }
413 }
414
415 status_t ret = mPlayer->getCurrentPosition(&tempUs);
416
417 Mutex::Autolock autoLock(mLock);
418 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
419 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
420 // position value that's different the seek to position.
421 if (ret != OK) {
422 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
423 } else {
424 mPositionUs = tempUs;
425 }
Wei Jia800fe372018-02-20 15:00:45 -0800426 *msec = divRound(tempUs, (int64_t)(1000));
Wei Jia53692fa2017-12-11 10:33:46 -0800427 return OK;
428}
429
Wei Jia800fe372018-02-20 15:00:45 -0800430status_t NuPlayer2Driver::getDuration(int64_t *msec) {
Wei Jia53692fa2017-12-11 10:33:46 -0800431 Mutex::Autolock autoLock(mLock);
432
433 if (mDurationUs < 0) {
434 return UNKNOWN_ERROR;
435 }
436
437 *msec = (mDurationUs + 500ll) / 1000;
438
439 return OK;
440}
441
442void NuPlayer2Driver::updateMetrics(const char *where) {
443 if (where == NULL) {
444 where = "unknown";
445 }
446 ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
447
448 // gather the final stats for this record
449 Vector<sp<AMessage>> trackStats;
450 mPlayer->getStats(&trackStats);
451
452 if (trackStats.size() > 0) {
453 for (size_t i = 0; i < trackStats.size(); ++i) {
454 const sp<AMessage> &stats = trackStats.itemAt(i);
455
456 AString mime;
457 stats->findString("mime", &mime);
458
459 AString name;
460 stats->findString("component-name", &name);
461
462 if (mime.startsWith("video/")) {
463 int32_t width, height;
464 mAnalyticsItem->setCString(kPlayerVMime, mime.c_str());
465 if (!name.empty()) {
466 mAnalyticsItem->setCString(kPlayerVCodec, name.c_str());
467 }
468
469 if (stats->findInt32("width", &width)
470 && stats->findInt32("height", &height)) {
471 mAnalyticsItem->setInt32(kPlayerWidth, width);
472 mAnalyticsItem->setInt32(kPlayerHeight, height);
473 }
474
475 int64_t numFramesTotal = 0;
476 int64_t numFramesDropped = 0;
477 stats->findInt64("frames-total", &numFramesTotal);
478 stats->findInt64("frames-dropped-output", &numFramesDropped);
479
480 mAnalyticsItem->setInt64(kPlayerFrames, numFramesTotal);
481 mAnalyticsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
482
483
484 } else if (mime.startsWith("audio/")) {
485 mAnalyticsItem->setCString(kPlayerAMime, mime.c_str());
486 if (!name.empty()) {
487 mAnalyticsItem->setCString(kPlayerACodec, name.c_str());
488 }
489 }
490 }
491 }
492
493 // always provide duration and playing time, even if they have 0/unknown values.
494
495 // getDuration() uses mLock for mutex -- careful where we use it.
Wei Jia800fe372018-02-20 15:00:45 -0800496 int64_t duration_ms = -1;
Wei Jia53692fa2017-12-11 10:33:46 -0800497 getDuration(&duration_ms);
498 mAnalyticsItem->setInt64(kPlayerDuration, duration_ms);
499
500 mAnalyticsItem->setInt64(kPlayerPlaying, (mPlayingTimeUs+500)/1000 );
501
502 if (mRebufferingEvents != 0) {
503 mAnalyticsItem->setInt64(kPlayerRebuffering, (mRebufferingTimeUs+500)/1000 );
504 mAnalyticsItem->setInt32(kPlayerRebufferingCount, mRebufferingEvents);
505 mAnalyticsItem->setInt32(kPlayerRebufferingAtExit, mRebufferingAtExit);
506 }
507
508 mAnalyticsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
509}
510
511
512void NuPlayer2Driver::logMetrics(const char *where) {
513 if (where == NULL) {
514 where = "unknown";
515 }
516 ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
517
518 if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
519 return;
520 }
521
522 // log only non-empty records
523 // we always updateMetrics() before we get here
524 // and that always injects 3 fields (duration, playing time, and
525 // datasource) into the record.
526 // So the canonical "empty" record has 3 elements in it.
527 if (mAnalyticsItem->count() > 3) {
528
Wei Jia53692fa2017-12-11 10:33:46 -0800529 mAnalyticsItem->selfrecord();
530
531 // re-init in case we prepare() and start() again.
532 delete mAnalyticsItem ;
Ray Essickee54eef2018-01-24 11:16:54 -0800533 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
Wei Jia53692fa2017-12-11 10:33:46 -0800534 if (mAnalyticsItem) {
Wei Jia53692fa2017-12-11 10:33:46 -0800535 mAnalyticsItem->setUid(mClientUid);
536 }
537 } else {
538 ALOGV("did not have anything to record");
539 }
540}
541
542status_t NuPlayer2Driver::reset() {
543 ALOGD("reset(%p) at state %d", this, mState);
544
545 updateMetrics("reset");
546 logMetrics("reset");
547
548 Mutex::Autolock autoLock(mLock);
549
550 switch (mState) {
551 case STATE_IDLE:
552 return OK;
553
554 case STATE_SET_DATASOURCE_PENDING:
555 case STATE_RESET_IN_PROGRESS:
556 return INVALID_OPERATION;
557
558 case STATE_PREPARING:
559 {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800560 notifyListener_l(mSrcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800561 break;
562 }
563
564 default:
565 break;
566 }
567
Wei Jia53692fa2017-12-11 10:33:46 -0800568 mState = STATE_RESET_IN_PROGRESS;
569 mPlayer->resetAsync();
570
571 while (mState == STATE_RESET_IN_PROGRESS) {
572 mCondition.wait(mLock);
573 }
574
575 mDurationUs = -1;
576 mPositionUs = -1;
577 mLooping = false;
578 mPlayingTimeUs = 0;
579 mRebufferingTimeUs = 0;
580 mRebufferingEvents = 0;
581 mRebufferingAtExit = false;
582
583 return OK;
584}
585
586status_t NuPlayer2Driver::notifyAt(int64_t mediaTimeUs) {
587 ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
588 return mPlayer->notifyAt(mediaTimeUs);
589}
590
591status_t NuPlayer2Driver::setLooping(int loop) {
592 mLooping = loop != 0;
593 return OK;
594}
595
Dongwon Kang9f631982018-07-10 12:34:41 -0700596status_t NuPlayer2Driver::invoke(const PlayerMessage &request, PlayerMessage *response) {
597 if (response == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800598 ALOGE("reply is a NULL pointer");
599 return BAD_VALUE;
600 }
601
Dongwon Kang9f631982018-07-10 12:34:41 -0700602 RepeatedPtrField<const Value>::const_iterator it = request.values().cbegin();
603 int32_t methodId = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800604
605 switch (methodId) {
606 case MEDIA_PLAYER2_INVOKE_ID_SET_VIDEO_SCALING_MODE:
607 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700608 int mode = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800609 return mPlayer->setVideoScalingMode(mode);
610 }
611
612 case MEDIA_PLAYER2_INVOKE_ID_GET_TRACK_INFO:
613 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700614 return mPlayer->getTrackInfo(response);
Wei Jia53692fa2017-12-11 10:33:46 -0800615 }
616
617 case MEDIA_PLAYER2_INVOKE_ID_SELECT_TRACK:
618 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700619 int trackIndex = (it++)->int32_value();
Wei Jia800fe372018-02-20 15:00:45 -0800620 int64_t msec = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800621 // getCurrentPosition should always return OK
622 getCurrentPosition(&msec);
623 return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll);
624 }
625
626 case MEDIA_PLAYER2_INVOKE_ID_UNSELECT_TRACK:
627 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700628 int trackIndex = (it++)->int32_value();
Wei Jia53692fa2017-12-11 10:33:46 -0800629 return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
630 }
631
632 case MEDIA_PLAYER2_INVOKE_ID_GET_SELECTED_TRACK:
633 {
Dongwon Kang9f631982018-07-10 12:34:41 -0700634 int32_t type = (it++)->int32_value();
635 return mPlayer->getSelectedTrack(type, response);
Wei Jia53692fa2017-12-11 10:33:46 -0800636 }
637
638 default:
639 {
640 return INVALID_OPERATION;
641 }
642 }
643}
644
645void NuPlayer2Driver::setAudioSink(const sp<AudioSink> &audioSink) {
646 mPlayer->setAudioSink(audioSink);
647 mAudioSink = audioSink;
648}
649
650status_t NuPlayer2Driver::setParameter(
651 int /* key */, const Parcel & /* request */) {
652 return INVALID_OPERATION;
653}
654
655status_t NuPlayer2Driver::getParameter(int key, Parcel *reply) {
656
657 if (key == FOURCC('m','t','r','X')) {
658 // mtrX -- a play on 'metrics' (not matrix)
659 // gather current info all together, parcel it, and send it back
660 updateMetrics("api");
661 mAnalyticsItem->writeToParcel(reply);
662 return OK;
663 }
664
665 return INVALID_OPERATION;
666}
667
668status_t NuPlayer2Driver::getMetadata(
669 const media::Metadata::Filter& /* ids */, Parcel *records) {
670 Mutex::Autolock autoLock(mLock);
671
672 using media::Metadata;
673
674 Metadata meta(records);
675
676 meta.appendBool(
677 Metadata::kPauseAvailable,
678 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
679
680 meta.appendBool(
681 Metadata::kSeekBackwardAvailable,
682 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
683
684 meta.appendBool(
685 Metadata::kSeekForwardAvailable,
686 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
687
688 meta.appendBool(
689 Metadata::kSeekAvailable,
690 mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
691
692 return OK;
693}
694
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800695void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800696 ALOGD("notifyResetComplete(%p)", this);
697 Mutex::Autolock autoLock(mLock);
698
699 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
700 mState = STATE_IDLE;
701 mCondition.broadcast();
702}
703
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800704void NuPlayer2Driver::notifySetSurfaceComplete(int64_t /* srcId */) {
Wei Jia53692fa2017-12-11 10:33:46 -0800705 ALOGV("notifySetSurfaceComplete(%p)", this);
706 Mutex::Autolock autoLock(mLock);
707
708 CHECK(mSetSurfaceInProgress);
709 mSetSurfaceInProgress = false;
710
711 mCondition.broadcast();
712}
713
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800714void NuPlayer2Driver::notifyDuration(int64_t /* srcId */, int64_t durationUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800715 Mutex::Autolock autoLock(mLock);
716 mDurationUs = durationUs;
717}
718
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800719void NuPlayer2Driver::notifyMorePlayingTimeUs(int64_t /* srcId */, int64_t playingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800720 Mutex::Autolock autoLock(mLock);
721 mPlayingTimeUs += playingUs;
722}
723
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800724void NuPlayer2Driver::notifyMoreRebufferingTimeUs(int64_t /* srcId */, int64_t rebufferingUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800725 Mutex::Autolock autoLock(mLock);
726 mRebufferingTimeUs += rebufferingUs;
727 mRebufferingEvents++;
728}
729
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800730void NuPlayer2Driver::notifyRebufferingWhenExit(int64_t /* srcId */, bool status) {
Wei Jia53692fa2017-12-11 10:33:46 -0800731 Mutex::Autolock autoLock(mLock);
732 mRebufferingAtExit = status;
733}
734
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800735void NuPlayer2Driver::notifySeekComplete(int64_t srcId) {
Wei Jia53692fa2017-12-11 10:33:46 -0800736 ALOGV("notifySeekComplete(%p)", this);
737 Mutex::Autolock autoLock(mLock);
738 mSeekInProgress = false;
Wei Jia0151ef42018-08-24 16:40:21 -0700739 notifyListener_l(srcId, MEDIA2_SEEK_COMPLETE);
Wei Jia53692fa2017-12-11 10:33:46 -0800740}
741
742status_t NuPlayer2Driver::dump(
743 int fd, const Vector<String16> & /* args */) const {
744
745 Vector<sp<AMessage> > trackStats;
746 mPlayer->getStats(&trackStats);
747
748 AString logString(" NuPlayer2\n");
749 char buf[256] = {0};
750
751 bool locked = false;
752 for (int i = 0; i < kDumpLockRetries; ++i) {
753 if (mLock.tryLock() == NO_ERROR) {
754 locked = true;
755 break;
756 }
757 usleep(kDumpLockSleepUs);
758 }
759
760 if (locked) {
761 snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
762 mState, mAtEOS, mLooping, mAutoLoop);
763 mLock.unlock();
764 } else {
765 snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
766 }
767 logString.append(buf);
768
769 for (size_t i = 0; i < trackStats.size(); ++i) {
770 const sp<AMessage> &stats = trackStats.itemAt(i);
771
772 AString mime;
773 if (stats->findString("mime", &mime)) {
774 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
775 logString.append(buf);
776 }
777
778 AString name;
779 if (stats->findString("component-name", &name)) {
780 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
781 logString.append(buf);
782 }
783
784 if (mime.startsWith("video/")) {
785 int32_t width, height;
786 if (stats->findInt32("width", &width)
787 && stats->findInt32("height", &height)) {
788 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
789 logString.append(buf);
790 }
791
792 int64_t numFramesTotal = 0;
793 int64_t numFramesDropped = 0;
794
795 stats->findInt64("frames-total", &numFramesTotal);
796 stats->findInt64("frames-dropped-output", &numFramesDropped);
797 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
798 "percentageDropped(%.2f%%)\n",
799 (long long)numFramesTotal,
800 (long long)numFramesDropped,
801 numFramesTotal == 0
802 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
803 logString.append(buf);
804 }
805 }
806
807 ALOGI("%s", logString.c_str());
808
809 if (fd >= 0) {
810 FILE *out = fdopen(dup(fd), "w");
811 fprintf(out, "%s", logString.c_str());
812 fclose(out);
813 out = NULL;
814 }
815
816 return OK;
817}
818
Wei Jia12b9f4a2017-12-13 15:24:13 -0800819void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
820 switch (msg->what()) {
821 case kWhatNotifyListener: {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800822 int64_t srcId;
Wei Jia12b9f4a2017-12-13 15:24:13 -0800823 int32_t msgId;
Wei Jiac5c79da2017-12-21 18:03:05 -0800824 int32_t ext1 = 0;
825 int32_t ext2 = 0;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800826 CHECK(msg->findInt64("srcId", &srcId));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800827 CHECK(msg->findInt32("messageId", &msgId));
Wei Jiac5c79da2017-12-21 18:03:05 -0800828 msg->findInt32("ext1", &ext1);
829 msg->findInt32("ext2", &ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700830 sp<PlayerMessageWrapper> in;
Wei Jiac5c79da2017-12-21 18:03:05 -0800831 sp<RefBase> obj;
Dongwon Kang41929fb2018-09-09 08:29:56 -0700832 if (msg->findObject("obj", &obj) && obj != NULL) {
833 in = static_cast<PlayerMessageWrapper *>(obj.get());
Wei Jiac5c79da2017-12-21 18:03:05 -0800834 }
Dongwon Kang41929fb2018-09-09 08:29:56 -0700835 sendEvent(srcId, msgId, ext1, ext2, (in == NULL ? NULL : in->getPlayerMessage()));
Wei Jia12b9f4a2017-12-13 15:24:13 -0800836 break;
837 }
838 default:
839 break;
840 }
841}
842
Wei Jia53692fa2017-12-11 10:33:46 -0800843void NuPlayer2Driver::notifyListener(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700844 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jia53692fa2017-12-11 10:33:46 -0800845 Mutex::Autolock autoLock(mLock);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800846 notifyListener_l(srcId, msg, ext1, ext2, in);
Wei Jia53692fa2017-12-11 10:33:46 -0800847}
848
849void NuPlayer2Driver::notifyListener_l(
Dongwon Kang41929fb2018-09-09 08:29:56 -0700850 int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800851 ALOGD("notifyListener_l(%p), (%lld, %d, %d, %d, %d), loop setting(%d, %d)",
852 this, (long long)srcId, msg, ext1, ext2,
Dongwon Kang41929fb2018-09-09 08:29:56 -0700853 (in == NULL ? -1 : (int)in->ByteSize()), mAutoLoop, mLooping);
Wei Jia57aeffd2018-02-15 16:01:14 -0800854 if (srcId == mSrcId) {
855 switch (msg) {
856 case MEDIA2_PLAYBACK_COMPLETE:
857 {
858 if (mState != STATE_RESET_IN_PROGRESS) {
859 if (mAutoLoop) {
860 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
861 if (mAudioSink != NULL) {
862 streamType = mAudioSink->getAudioStreamType();
863 }
864 if (streamType == AUDIO_STREAM_NOTIFICATION) {
865 ALOGW("disabling auto-loop for notification");
866 mAutoLoop = false;
867 }
Wei Jia53692fa2017-12-11 10:33:46 -0800868 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800869 if (mLooping || mAutoLoop) {
870 mPlayer->seekToAsync(0);
871 if (mAudioSink != NULL) {
872 // The renderer has stopped the sink at the end in order to play out
873 // the last little bit of audio. In looping mode, we need to restart it.
874 mAudioSink->start();
875 }
Wei Jia9af566a2018-08-10 16:36:35 -0700876
877 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
878 notify->setInt64("srcId", srcId);
879 notify->setInt32("messageId", MEDIA2_INFO);
880 notify->setInt32("ext1", MEDIA2_INFO_DATA_SOURCE_REPEAT);
881 notify->post();
Wei Jia57aeffd2018-02-15 16:01:14 -0800882 return;
Wei Jia53692fa2017-12-11 10:33:46 -0800883 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800884 if (property_get_bool("persist.debug.sf.stats", false)) {
885 Vector<String16> args;
886 dump(-1, args);
Wei Jia53692fa2017-12-11 10:33:46 -0800887 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800888 mPlayer->pause();
889 mState = STATE_PAUSED;
Wei Jia53692fa2017-12-11 10:33:46 -0800890 }
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700891 FALLTHROUGH_INTENDED;
Wei Jia53692fa2017-12-11 10:33:46 -0800892 }
Wei Jia53692fa2017-12-11 10:33:46 -0800893
Wei Jia57aeffd2018-02-15 16:01:14 -0800894 case MEDIA2_ERROR:
895 {
896 // when we have an error, add it to the analytics for this playback.
897 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
898 // [test against msg is due to fall through from previous switch value]
899 if (msg == MEDIA2_ERROR) {
900 mAnalyticsItem->setInt32(kPlayerError, ext1);
901 if (ext2 != 0) {
902 mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
903 }
904 mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
Wei Jia53692fa2017-12-11 10:33:46 -0800905 }
Wei Jia57aeffd2018-02-15 16:01:14 -0800906 mAtEOS = true;
907 break;
Wei Jia53692fa2017-12-11 10:33:46 -0800908 }
Wei Jia53692fa2017-12-11 10:33:46 -0800909
Wei Jia57aeffd2018-02-15 16:01:14 -0800910 default:
911 break;
912 }
Wei Jia53692fa2017-12-11 10:33:46 -0800913 }
914
Wei Jiac5c79da2017-12-21 18:03:05 -0800915 sp<AMessage> notify = new AMessage(kWhatNotifyListener, this);
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800916 notify->setInt64("srcId", srcId);
Wei Jiac5c79da2017-12-21 18:03:05 -0800917 notify->setInt32("messageId", msg);
918 notify->setInt32("ext1", ext1);
919 notify->setInt32("ext2", ext2);
Dongwon Kang41929fb2018-09-09 08:29:56 -0700920 notify->setObject("obj", PlayerMessageWrapper::Create((PlayerMessage*)in));
Wei Jiac5c79da2017-12-21 18:03:05 -0800921 notify->post();
Wei Jia12b9f4a2017-12-13 15:24:13 -0800922}
923
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800924void NuPlayer2Driver::notifySetDataSourceCompleted(int64_t /* srcId */, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800925 Mutex::Autolock autoLock(mLock);
926
927 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
928
929 mAsyncResult = err;
930 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
931 mCondition.broadcast();
932}
933
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800934void NuPlayer2Driver::notifyPrepareCompleted(int64_t srcId, status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800935 ALOGV("notifyPrepareCompleted %d", err);
936
937 Mutex::Autolock autoLock(mLock);
938
Wei Jia57aeffd2018-02-15 16:01:14 -0800939 if (srcId != mSrcId) {
940 if (err == OK) {
941 notifyListener_l(srcId, MEDIA2_PREPARED);
942 } else {
943 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
944 }
945 return;
946 }
947
Wei Jia53692fa2017-12-11 10:33:46 -0800948 if (mState != STATE_PREPARING) {
949 // We were preparing asynchronously when the client called
950 // reset(), we sent a premature "prepared" notification and
951 // then initiated the reset. This notification is stale.
952 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
953 return;
954 }
955
956 CHECK_EQ(mState, STATE_PREPARING);
957
958 mAsyncResult = err;
959
960 if (err == OK) {
961 // update state before notifying client, so that if client calls back into NuPlayer2Driver
962 // in response, NuPlayer2Driver has the right state
963 mState = STATE_PREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800964 notifyListener_l(srcId, MEDIA2_PREPARED);
Wei Jia53692fa2017-12-11 10:33:46 -0800965 } else {
966 mState = STATE_UNPREPARED;
Wei Jia57aeffd2018-02-15 16:01:14 -0800967 notifyListener_l(srcId, MEDIA2_ERROR, MEDIA2_ERROR_UNKNOWN, err);
Wei Jia53692fa2017-12-11 10:33:46 -0800968 }
969
970 sp<MetaData> meta = mPlayer->getFileMeta();
971 int32_t loop;
972 if (meta != NULL
973 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
974 mAutoLoop = true;
975 }
976
977 mCondition.broadcast();
978}
979
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800980void NuPlayer2Driver::notifyFlagsChanged(int64_t /* srcId */, uint32_t flags) {
Wei Jia53692fa2017-12-11 10:33:46 -0800981 Mutex::Autolock autoLock(mLock);
982
983 mPlayerFlags = flags;
984}
985
986// Modular DRM
987status_t NuPlayer2Driver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
988{
989 ALOGV("prepareDrm(%p) state: %d", this, mState);
990
991 // leaving the state verification for mediaplayer.cpp
992 status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
993
994 ALOGV("prepareDrm ret: %d", ret);
995
996 return ret;
997}
998
999status_t NuPlayer2Driver::releaseDrm()
1000{
1001 ALOGV("releaseDrm(%p) state: %d", this, mState);
1002
1003 // leaving the state verification for mediaplayer.cpp
1004 status_t ret = mPlayer->releaseDrm();
1005
1006 ALOGV("releaseDrm ret: %d", ret);
1007
1008 return ret;
1009}
1010
Ray Essick51f4c872017-12-15 12:27:56 -08001011std::string NuPlayer2Driver::stateString(State state) {
1012 const char *rval = NULL;
1013 char rawbuffer[16]; // allows "%d"
1014
1015 switch (state) {
1016 case STATE_IDLE: rval = "IDLE"; break;
1017 case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1018 case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1019 case STATE_PREPARING: rval = "PREPARING"; break;
1020 case STATE_PREPARED: rval = "PREPARED"; break;
1021 case STATE_RUNNING: rval = "RUNNING"; break;
1022 case STATE_PAUSED: rval = "PAUSED"; break;
1023 case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
Ray Essick51f4c872017-12-15 12:27:56 -08001024 default:
1025 // yes, this buffer is shared and vulnerable to races
1026 snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1027 rval = rawbuffer;
1028 break;
1029 }
1030
1031 return rval;
1032}
1033
Wei Jia53692fa2017-12-11 10:33:46 -08001034} // namespace android