blob: ceea2f47ea2e07d815064a29ce200d2d809a1c94 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
2 * Copyright (C) 2010 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 "NuPlayerDriver"
Kévin PETIT377b2ec2014-02-03 12:35:36 +000019#include <inttypes.h>
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -070020#include <android-base/macros.h>
Andreas Huberf9334412010-12-15 15:17:42 -080021#include <utils/Log.h>
Praveen Chavan3a20d292015-05-21 08:47:34 -070022#include <cutils/properties.h>
Andreas Huberf9334412010-12-15 15:17:42 -080023
24#include "NuPlayerDriver.h"
25
26#include "NuPlayer.h"
Andreas Huber9575c962013-02-05 13:59:56 -080027#include "NuPlayerSource.h"
Andreas Huberf9334412010-12-15 15:17:42 -080028
Vlad Popab4f5b012022-08-12 15:53:09 +020029#include <audiomanager/AudioManager.h>
Andreas Huber1aef2112011-01-04 14:01:29 -080030#include <media/stagefright/foundation/ADebug.h>
Andreas Huberf9334412010-12-15 15:17:42 -080031#include <media/stagefright/foundation/ALooper.h>
Ronghua Wua73d9e02014-10-08 15:13:29 -070032#include <media/stagefright/foundation/AUtils.h>
Dongwon Kang60761282017-10-09 11:16:48 -070033#include <media/stagefright/foundation/ByteUtils.h>
Wei Jia0a68f662017-08-30 18:01:26 -070034#include <media/stagefright/MediaClock.h>
Andreas Huber9575c962013-02-05 13:59:56 -080035#include <media/stagefright/MetaData.h>
Andy Hung2abde2c2014-09-30 14:40:32 -070036#include <media/stagefright/Utils.h>
Marco Nelissen42057ce2019-09-23 12:15:57 -070037#include <media/stagefright/FoundationUtils.h>
Andreas Huberf9334412010-12-15 15:17:42 -080038
Wei Jia1de22232017-01-04 16:09:50 -080039static const int kDumpLockRetries = 50;
40static const int kDumpLockSleepUs = 20000;
41
Andreas Huberf9334412010-12-15 15:17:42 -080042namespace android {
43
Ray Essickafb43f72017-03-09 10:23:55 -080044// key for media statistics
45static const char *kKeyPlayer = "nuplayer";
46// attrs for media statistics
Ray Essickde15b8c2018-01-30 16:35:56 -080047 // NB: these are matched with public Java API constants defined
48 // in frameworks/base/media/java/android/media/MediaPlayer.java
49 // These must be kept synchronized with the constants there.
Ray Essickafb43f72017-03-09 10:23:55 -080050static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
51static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
52static const char *kPlayerWidth = "android.media.mediaplayer.width";
53static const char *kPlayerHeight = "android.media.mediaplayer.height";
54static const char *kPlayerFrames = "android.media.mediaplayer.frames";
55static const char *kPlayerFramesDropped = "android.media.mediaplayer.dropped";
Ray Essick092f74a2018-11-20 10:25:13 -080056static const char *kPlayerFrameRate = "android.media.mediaplayer.fps";
Ray Essickafb43f72017-03-09 10:23:55 -080057static const char *kPlayerAMime = "android.media.mediaplayer.audio.mime";
58static const char *kPlayerACodec = "android.media.mediaplayer.audio.codec";
59static const char *kPlayerDuration = "android.media.mediaplayer.durationMs";
60static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
61static const char *kPlayerError = "android.media.mediaplayer.err";
62static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
Ray Essickde15b8c2018-01-30 16:35:56 -080063
64 // NB: These are not yet exposed as public Java API constants.
Ray Essick51f4c872017-12-15 12:27:56 -080065static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
Hassan Shojaniaff63de72017-04-26 15:10:42 -070066static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
Ray Essick58e0f7a2017-11-21 10:59:38 -080067//
68static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
69static const char *kPlayerRebufferingCount = "android.media.mediaplayer.rebuffers";
70static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
Ray Essickafb43f72017-03-09 10:23:55 -080071
Ray Essickd4d00612017-01-03 09:36:27 -080072
Ronghua Wu68845c12015-07-21 09:50:48 -070073NuPlayerDriver::NuPlayerDriver(pid_t pid)
Andreas Huber9575c962013-02-05 13:59:56 -080074 : mState(STATE_IDLE),
Andreas Huberec0c5972013-02-05 14:47:13 -080075 mIsAsyncPrepare(false),
Andreas Huber9575c962013-02-05 13:59:56 -080076 mAsyncResult(UNKNOWN_ERROR),
Chong Zhang13d6faa2014-08-22 15:35:28 -070077 mSetSurfaceInProgress(false),
Andreas Huber43c3e6c2011-01-05 12:17:08 -080078 mDurationUs(-1),
79 mPositionUs(-1),
Ronghua Wua73d9e02014-10-08 15:13:29 -070080 mSeekInProgress(false),
Ray Essickd4d00612017-01-03 09:36:27 -080081 mPlayingTimeUs(0),
Ray Essick58e0f7a2017-11-21 10:59:38 -080082 mRebufferingTimeUs(0),
83 mRebufferingEvents(0),
84 mRebufferingAtExit(false),
Andreas Huber1aef2112011-01-04 14:01:29 -080085 mLooper(new ALooper),
Wei Jia0a68f662017-08-30 18:01:26 -070086 mMediaClock(new MediaClock),
87 mPlayer(new NuPlayer(pid, mMediaClock)),
Andreas Huber9575c962013-02-05 13:59:56 -080088 mPlayerFlags(0),
Vlad Popab4f5b012022-08-12 15:53:09 +020089 mCachedPlayerIId(PLAYER_PIID_INVALID),
Ray Essickf27e9872019-12-07 06:28:46 -080090 mMetricsItem(NULL),
Ray Essickf65f4212017-08-31 11:41:19 -070091 mClientUid(-1),
Andreas Hubera4af2142011-10-26 15:23:31 -070092 mAtEOS(false),
Lajos Molnara2e14302014-07-31 12:07:58 -070093 mLooping(false),
Wei Jia419187c2015-10-29 10:07:26 -070094 mAutoLoop(false) {
Wei Jia1de22232017-01-04 16:09:50 -080095 ALOGD("NuPlayerDriver(%p) created, clientPid(%d)", this, pid);
Andreas Huberf9334412010-12-15 15:17:42 -080096 mLooper->setName("NuPlayerDriver Looper");
97
Wei Jia7b6f67d2017-08-24 17:20:29 -070098 mMediaClock->init();
99
Ray Essickd4d00612017-01-03 09:36:27 -0800100 // set up an analytics record
Ray Essickf27e9872019-12-07 06:28:46 -0800101 mMetricsItem = mediametrics::Item::create(kKeyPlayer);
Ray Essickd4d00612017-01-03 09:36:27 -0800102
Andreas Huberf9334412010-12-15 15:17:42 -0800103 mLooper->start(
104 false, /* runOnCallingThread */
105 true, /* canCallJava */
106 PRIORITY_AUDIO);
107
Andreas Huberf9334412010-12-15 15:17:42 -0800108 mLooper->registerHandler(mPlayer);
109
Dongwon Kang47afe0a2018-03-27 15:15:30 -0700110 mPlayer->init(this);
Andreas Huberf9334412010-12-15 15:17:42 -0800111}
112
113NuPlayerDriver::~NuPlayerDriver() {
Andy Hung2abde2c2014-09-30 14:40:32 -0700114 ALOGV("~NuPlayerDriver(%p)", this);
Andreas Huberf9334412010-12-15 15:17:42 -0800115 mLooper->stop();
Ray Essickd4d00612017-01-03 09:36:27 -0800116
117 // finalize any pending metrics, usually a no-op.
Ray Essick54097702017-03-17 16:18:35 -0700118 updateMetrics("destructor");
Ray Essickd4d00612017-01-03 09:36:27 -0800119 logMetrics("destructor");
120
Ray Essicke99bcf22020-05-04 16:18:33 -0700121 Mutex::Autolock autoLock(mMetricsLock);
Ray Essickf27e9872019-12-07 06:28:46 -0800122 if (mMetricsItem != NULL) {
123 delete mMetricsItem;
124 mMetricsItem = NULL;
Ray Essickd4d00612017-01-03 09:36:27 -0800125 }
Andreas Huberf9334412010-12-15 15:17:42 -0800126}
127
128status_t NuPlayerDriver::initCheck() {
129 return OK;
130}
131
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700132status_t NuPlayerDriver::setUID(uid_t uid) {
133 mPlayer->setUID(uid);
Ray Essickf65f4212017-08-31 11:41:19 -0700134 mClientUid = uid;
Ray Essicke99bcf22020-05-04 16:18:33 -0700135
136 Mutex::Autolock autoLock(mMetricsLock);
Ray Essickf27e9872019-12-07 06:28:46 -0800137 if (mMetricsItem) {
138 mMetricsItem->setUid(mClientUid);
Ray Essickf65f4212017-08-31 11:41:19 -0700139 }
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700140
141 return OK;
142}
143
Andreas Huberf9334412010-12-15 15:17:42 -0800144status_t NuPlayerDriver::setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800145 const sp<IMediaHTTPService> &httpService,
146 const char *url,
147 const KeyedVector<String8, String8> *headers) {
Andy Hung2abde2c2014-09-30 14:40:32 -0700148 ALOGV("setDataSource(%p) url(%s)", this, uriDebugString(url, false).c_str());
Andreas Huber9575c962013-02-05 13:59:56 -0800149 Mutex::Autolock autoLock(mLock);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800150
Andreas Huber9575c962013-02-05 13:59:56 -0800151 if (mState != STATE_IDLE) {
152 return INVALID_OPERATION;
153 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800154
Andreas Huber9575c962013-02-05 13:59:56 -0800155 mState = STATE_SET_DATASOURCE_PENDING;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800156
Andreas Huber1b86fe02014-01-29 11:13:26 -0800157 mPlayer->setDataSourceAsync(httpService, url, headers);
Andreas Huber9575c962013-02-05 13:59:56 -0800158
159 while (mState == STATE_SET_DATASOURCE_PENDING) {
160 mCondition.wait(mLock);
161 }
162
163 return mAsyncResult;
Andreas Huberf9334412010-12-15 15:17:42 -0800164}
165
166status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
Andy Hung2abde2c2014-09-30 14:40:32 -0700167 ALOGV("setDataSource(%p) file(%d)", this, fd);
Andreas Huber9575c962013-02-05 13:59:56 -0800168 Mutex::Autolock autoLock(mLock);
Andreas Huberafed0e12011-09-20 15:39:58 -0700169
Andreas Huber9575c962013-02-05 13:59:56 -0800170 if (mState != STATE_IDLE) {
171 return INVALID_OPERATION;
172 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700173
Andreas Huber9575c962013-02-05 13:59:56 -0800174 mState = STATE_SET_DATASOURCE_PENDING;
Andreas Huberafed0e12011-09-20 15:39:58 -0700175
Andreas Huber9575c962013-02-05 13:59:56 -0800176 mPlayer->setDataSourceAsync(fd, offset, length);
177
178 while (mState == STATE_SET_DATASOURCE_PENDING) {
179 mCondition.wait(mLock);
180 }
181
182 return mAsyncResult;
Andreas Huberf9334412010-12-15 15:17:42 -0800183}
184
185status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
Andy Hung2abde2c2014-09-30 14:40:32 -0700186 ALOGV("setDataSource(%p) stream source", this);
Andreas Huber9575c962013-02-05 13:59:56 -0800187 Mutex::Autolock autoLock(mLock);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800188
Andreas Huber9575c962013-02-05 13:59:56 -0800189 if (mState != STATE_IDLE) {
190 return INVALID_OPERATION;
191 }
Andreas Huberf9334412010-12-15 15:17:42 -0800192
Andreas Huber9575c962013-02-05 13:59:56 -0800193 mState = STATE_SET_DATASOURCE_PENDING;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800194
Andreas Huber9575c962013-02-05 13:59:56 -0800195 mPlayer->setDataSourceAsync(source);
196
197 while (mState == STATE_SET_DATASOURCE_PENDING) {
198 mCondition.wait(mLock);
199 }
200
201 return mAsyncResult;
Andreas Huberf9334412010-12-15 15:17:42 -0800202}
203
Chris Watkins99f31602015-03-20 13:06:33 -0700204status_t NuPlayerDriver::setDataSource(const sp<DataSource> &source) {
205 ALOGV("setDataSource(%p) callback source", this);
206 Mutex::Autolock autoLock(mLock);
207
208 if (mState != STATE_IDLE) {
209 return INVALID_OPERATION;
210 }
211
212 mState = STATE_SET_DATASOURCE_PENDING;
213
214 mPlayer->setDataSourceAsync(source);
215
216 while (mState == STATE_SET_DATASOURCE_PENDING) {
217 mCondition.wait(mLock);
218 }
219
220 return mAsyncResult;
221}
222
Byeongjo Park28225ab2019-01-24 20:31:19 +0900223status_t NuPlayerDriver::setDataSource(const String8& rtpParams) {
224 ALOGV("setDataSource(%p) rtp source", this);
225 Mutex::Autolock autoLock(mLock);
226
227 if (mState != STATE_IDLE) {
228 return INVALID_OPERATION;
229 }
230
231 mState = STATE_SET_DATASOURCE_PENDING;
232
233 mPlayer->setDataSourceAsync(rtpParams);
234
235 while (mState == STATE_SET_DATASOURCE_PENDING) {
236 mCondition.wait(mLock);
237 }
238
239 return mAsyncResult;
240}
241
242
Glenn Kasten11731182011-02-08 17:26:17 -0800243status_t NuPlayerDriver::setVideoSurfaceTexture(
Andy McFadden8ba01022012-12-18 09:46:54 -0800244 const sp<IGraphicBufferProducer> &bufferProducer) {
Andy Hung2abde2c2014-09-30 14:40:32 -0700245 ALOGV("setVideoSurfaceTexture(%p)", this);
Andreas Huber57a339c2012-12-03 11:18:00 -0800246 Mutex::Autolock autoLock(mLock);
247
Chong Zhang13d6faa2014-08-22 15:35:28 -0700248 if (mSetSurfaceInProgress) {
249 return INVALID_OPERATION;
250 }
251
Andreas Huber9575c962013-02-05 13:59:56 -0800252 switch (mState) {
253 case STATE_SET_DATASOURCE_PENDING:
254 case STATE_RESET_IN_PROGRESS:
255 return INVALID_OPERATION;
256
257 default:
258 break;
259 }
260
Chong Zhang13d6faa2014-08-22 15:35:28 -0700261 mSetSurfaceInProgress = true;
262
Andy McFadden8ba01022012-12-18 09:46:54 -0800263 mPlayer->setVideoSurfaceTextureAsync(bufferProducer);
Andreas Huber57a339c2012-12-03 11:18:00 -0800264
Chong Zhang13d6faa2014-08-22 15:35:28 -0700265 while (mSetSurfaceInProgress) {
266 mCondition.wait(mLock);
267 }
268
Glenn Kasten11731182011-02-08 17:26:17 -0800269 return OK;
270}
271
Wei Jia9bb38032017-03-23 18:00:38 -0700272status_t NuPlayerDriver::getBufferingSettings(BufferingSettings* buffering) {
273 ALOGV("getBufferingSettings(%p)", this);
Wei Jiaaaa4dfa2017-02-28 17:22:59 -0800274 {
275 Mutex::Autolock autoLock(mLock);
276 if (mState == STATE_IDLE) {
277 return INVALID_OPERATION;
278 }
Wei Jia48fa06d2016-12-20 15:30:49 -0800279 }
280
Wei Jia9bb38032017-03-23 18:00:38 -0700281 return mPlayer->getBufferingSettings(buffering);
Wei Jia48fa06d2016-12-20 15:30:49 -0800282}
283
284status_t NuPlayerDriver::setBufferingSettings(const BufferingSettings& buffering) {
285 ALOGV("setBufferingSettings(%p)", this);
Wei Jiaaaa4dfa2017-02-28 17:22:59 -0800286 {
287 Mutex::Autolock autoLock(mLock);
288 if (mState == STATE_IDLE) {
289 return INVALID_OPERATION;
290 }
Wei Jia48fa06d2016-12-20 15:30:49 -0800291 }
292
293 return mPlayer->setBufferingSettings(buffering);
294}
295
Andreas Huberf9334412010-12-15 15:17:42 -0800296status_t NuPlayerDriver::prepare() {
Andy Hung2abde2c2014-09-30 14:40:32 -0700297 ALOGV("prepare(%p)", this);
Andreas Huber9575c962013-02-05 13:59:56 -0800298 Mutex::Autolock autoLock(mLock);
299 return prepare_l();
300}
301
302status_t NuPlayerDriver::prepare_l() {
303 switch (mState) {
304 case STATE_UNPREPARED:
305 mState = STATE_PREPARING;
Andreas Huberec0c5972013-02-05 14:47:13 -0800306
307 // Make sure we're not posting any notifications, success or
308 // failure information is only communicated through our result
309 // code.
310 mIsAsyncPrepare = false;
Andreas Huber9575c962013-02-05 13:59:56 -0800311 mPlayer->prepareAsync();
312 while (mState == STATE_PREPARING) {
313 mCondition.wait(mLock);
314 }
315 return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR;
Lajos Molnar4b75b862013-08-15 15:59:19 -0700316 case STATE_STOPPED:
317 // this is really just paused. handle as seek to start
318 mAtEOS = false;
319 mState = STATE_STOPPED_AND_PREPARING;
320 mIsAsyncPrepare = false;
Wei Jiac5de0912016-11-18 10:22:14 -0800321 mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
322 true /* needNotify */);
Lajos Molnar4b75b862013-08-15 15:59:19 -0700323 while (mState == STATE_STOPPED_AND_PREPARING) {
324 mCondition.wait(mLock);
325 }
326 return (mState == STATE_STOPPED_AND_PREPARED) ? OK : UNKNOWN_ERROR;
Andreas Huber9575c962013-02-05 13:59:56 -0800327 default:
328 return INVALID_OPERATION;
329 };
Andreas Huberf9334412010-12-15 15:17:42 -0800330}
331
332status_t NuPlayerDriver::prepareAsync() {
Andy Hung2abde2c2014-09-30 14:40:32 -0700333 ALOGV("prepareAsync(%p)", this);
Andreas Huber9575c962013-02-05 13:59:56 -0800334 Mutex::Autolock autoLock(mLock);
Andreas Huberafed0e12011-09-20 15:39:58 -0700335
Andreas Huber9575c962013-02-05 13:59:56 -0800336 switch (mState) {
337 case STATE_UNPREPARED:
338 mState = STATE_PREPARING;
Andreas Huberec0c5972013-02-05 14:47:13 -0800339 mIsAsyncPrepare = true;
Andreas Huber9575c962013-02-05 13:59:56 -0800340 mPlayer->prepareAsync();
341 return OK;
Lajos Molnar4b75b862013-08-15 15:59:19 -0700342 case STATE_STOPPED:
343 // this is really just paused. handle as seek to start
344 mAtEOS = false;
345 mState = STATE_STOPPED_AND_PREPARING;
346 mIsAsyncPrepare = true;
Wei Jiac5de0912016-11-18 10:22:14 -0800347 mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
348 true /* needNotify */);
Lajos Molnar4b75b862013-08-15 15:59:19 -0700349 return OK;
Andreas Huber9575c962013-02-05 13:59:56 -0800350 default:
351 return INVALID_OPERATION;
352 };
Andreas Huberf9334412010-12-15 15:17:42 -0800353}
354
355status_t NuPlayerDriver::start() {
Siarhei Vishniakou6b0b5262019-01-25 19:48:31 -0800356 ALOGV("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
Andreas Huber9575c962013-02-05 13:59:56 -0800357 Mutex::Autolock autoLock(mLock);
Wei Jia8a092d32016-06-03 14:57:24 -0700358 return start_l();
359}
Andreas Huber9575c962013-02-05 13:59:56 -0800360
Wei Jia8a092d32016-06-03 14:57:24 -0700361status_t NuPlayerDriver::start_l() {
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800362 switch (mState) {
Andreas Huber9575c962013-02-05 13:59:56 -0800363 case STATE_UNPREPARED:
364 {
365 status_t err = prepare_l();
366
367 if (err != OK) {
368 return err;
369 }
370
371 CHECK_EQ(mState, STATE_PREPARED);
372
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700373 FALLTHROUGH_INTENDED;
Andreas Huber9575c962013-02-05 13:59:56 -0800374 }
375
Wei Jia94211742014-10-28 17:09:06 -0700376 case STATE_PAUSED:
377 case STATE_STOPPED_AND_PREPARED:
Andreas Huber9575c962013-02-05 13:59:56 -0800378 case STATE_PREPARED:
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800379 {
380 mPlayer->start();
381
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700382 FALLTHROUGH_INTENDED;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800383 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800384
Andreas Huber9575c962013-02-05 13:59:56 -0800385 case STATE_RUNNING:
Wei Jia05601952014-08-20 18:21:11 -0700386 {
387 if (mAtEOS) {
388 mPlayer->seekToAsync(0);
389 mAtEOS = false;
390 mPositionUs = -1;
391 }
Andreas Huber9575c962013-02-05 13:59:56 -0800392 break;
Wei Jia05601952014-08-20 18:21:11 -0700393 }
Andreas Huber9575c962013-02-05 13:59:56 -0800394
Andreas Huber9575c962013-02-05 13:59:56 -0800395 default:
396 return INVALID_OPERATION;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800397 }
398
Andreas Huber9575c962013-02-05 13:59:56 -0800399 mState = STATE_RUNNING;
Andreas Huberf9334412010-12-15 15:17:42 -0800400
401 return OK;
402}
403
404status_t NuPlayerDriver::stop() {
Andy Hung2abde2c2014-09-30 14:40:32 -0700405 ALOGD("stop(%p)", this);
Lajos Molnar4b75b862013-08-15 15:59:19 -0700406 Mutex::Autolock autoLock(mLock);
407
408 switch (mState) {
409 case STATE_RUNNING:
410 mPlayer->pause();
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -0700411 FALLTHROUGH_INTENDED;
Lajos Molnar4b75b862013-08-15 15:59:19 -0700412
413 case STATE_PAUSED:
Marco Nelissen2a79c322014-08-26 13:57:32 -0700414 mState = STATE_STOPPED;
Wei Jia05601952014-08-20 18:21:11 -0700415 notifyListener_l(MEDIA_STOPPED);
Marco Nelissen2a79c322014-08-26 13:57:32 -0700416 break;
Lajos Molnar4b75b862013-08-15 15:59:19 -0700417
418 case STATE_PREPARED:
419 case STATE_STOPPED:
420 case STATE_STOPPED_AND_PREPARING:
421 case STATE_STOPPED_AND_PREPARED:
422 mState = STATE_STOPPED;
423 break;
424
425 default:
426 return INVALID_OPERATION;
427 }
428
429 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800430}
431
432status_t NuPlayerDriver::pause() {
Wei Jia03a56532016-03-23 13:43:31 -0700433 ALOGD("pause(%p)", this);
Ronghua Wuf83408b2014-11-19 10:02:16 -0800434 // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
435 // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
436 // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
437 // getCurrentPosition here.
Wei Jia62cc8d02016-01-21 13:03:20 -0800438 int unused;
439 getCurrentPosition(&unused);
Ronghua Wuf83408b2014-11-19 10:02:16 -0800440
Andreas Huber9575c962013-02-05 13:59:56 -0800441 Mutex::Autolock autoLock(mLock);
442
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800443 switch (mState) {
Andreas Huber9575c962013-02-05 13:59:56 -0800444 case STATE_PAUSED:
445 case STATE_PREPARED:
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800446 return OK;
Andreas Huber9575c962013-02-05 13:59:56 -0800447
448 case STATE_RUNNING:
Marco Nelissen2a79c322014-08-26 13:57:32 -0700449 mState = STATE_PAUSED;
Wei Jia05601952014-08-20 18:21:11 -0700450 notifyListener_l(MEDIA_PAUSED);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800451 mPlayer->pause();
452 break;
Andreas Huber9575c962013-02-05 13:59:56 -0800453
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800454 default:
Andreas Huber9575c962013-02-05 13:59:56 -0800455 return INVALID_OPERATION;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800456 }
457
Andreas Huberf9334412010-12-15 15:17:42 -0800458 return OK;
459}
460
461bool NuPlayerDriver::isPlaying() {
Andreas Huber9575c962013-02-05 13:59:56 -0800462 return mState == STATE_RUNNING && !mAtEOS;
Andreas Huberf9334412010-12-15 15:17:42 -0800463}
464
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700465status_t NuPlayerDriver::setPlaybackSettings(const AudioPlaybackRate &rate) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700466 status_t err = mPlayer->setPlaybackSettings(rate);
467 if (err == OK) {
Wei Jia62cc8d02016-01-21 13:03:20 -0800468 // try to update position
469 int unused;
470 getCurrentPosition(&unused);
Wei Jiaf3631d22015-10-06 10:32:32 -0700471 Mutex::Autolock autoLock(mLock);
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700472 if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
473 mState = STATE_PAUSED;
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700474 notifyListener_l(MEDIA_PAUSED);
Wei Jia8a092d32016-06-03 14:57:24 -0700475 } else if (rate.mSpeed != 0.f
476 && (mState == STATE_PAUSED
477 || mState == STATE_STOPPED_AND_PREPARED
478 || mState == STATE_PREPARED)) {
479 err = start_l();
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700480 }
481 }
482 return err;
483}
484
485status_t NuPlayerDriver::getPlaybackSettings(AudioPlaybackRate *rate) {
486 return mPlayer->getPlaybackSettings(rate);
487}
488
489status_t NuPlayerDriver::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
490 return mPlayer->setSyncSettings(sync, videoFpsHint);
491}
492
493status_t NuPlayerDriver::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
494 return mPlayer->getSyncSettings(sync, videoFps);
Wei Jia98160162015-02-04 17:01:11 -0800495}
496
Wei Jiac5de0912016-11-18 10:22:14 -0800497status_t NuPlayerDriver::seekTo(int msec, MediaPlayerSeekMode mode) {
Siarhei Vishniakou6b0b5262019-01-25 19:48:31 -0800498 ALOGV("seekTo(%p) (%d ms, %d) at state %d", this, msec, mode, mState);
Andreas Huber9575c962013-02-05 13:59:56 -0800499 Mutex::Autolock autoLock(mLock);
500
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800501 int64_t seekTimeUs = msec * 1000LL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800502
503 switch (mState) {
Andreas Huber9575c962013-02-05 13:59:56 -0800504 case STATE_PREPARED:
Wei Jia94211742014-10-28 17:09:06 -0700505 case STATE_STOPPED_AND_PREPARED:
Andreas Huber9575c962013-02-05 13:59:56 -0800506 case STATE_PAUSED:
Wei Jia1061c9c2015-05-19 16:02:17 -0700507 case STATE_RUNNING:
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800508 {
Andreas Hubera4af2142011-10-26 15:23:31 -0700509 mAtEOS = false;
Ronghua Wua73d9e02014-10-08 15:13:29 -0700510 mSeekInProgress = true;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700511 // seeks can take a while, so we essentially paused
Wei Jia05601952014-08-20 18:21:11 -0700512 notifyListener_l(MEDIA_PAUSED);
Wei Jiac5de0912016-11-18 10:22:14 -0800513 mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800514 break;
515 }
516
517 default:
Andreas Huber9575c962013-02-05 13:59:56 -0800518 return INVALID_OPERATION;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800519 }
520
Wei Jia05601952014-08-20 18:21:11 -0700521 mPositionUs = seekTimeUs;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800522 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800523}
524
525status_t NuPlayerDriver::getCurrentPosition(int *msec) {
Ronghua Wua73d9e02014-10-08 15:13:29 -0700526 int64_t tempUs = 0;
Wei Jiad4cdba12014-12-18 10:44:17 -0800527 {
528 Mutex::Autolock autoLock(mLock);
Wei Jia62cc8d02016-01-21 13:03:20 -0800529 if (mSeekInProgress || (mState == STATE_PAUSED && !mAtEOS)) {
Wei Jiad4cdba12014-12-18 10:44:17 -0800530 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
531 *msec = (int)divRound(tempUs, (int64_t)(1000));
532 return OK;
533 }
534 }
535
Ronghua Wua73d9e02014-10-08 15:13:29 -0700536 status_t ret = mPlayer->getCurrentPosition(&tempUs);
537
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800538 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700539 // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
540 // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
541 // position value that's different the seek to position.
Wei Jiad4cdba12014-12-18 10:44:17 -0800542 if (ret != OK) {
Ronghua Wua73d9e02014-10-08 15:13:29 -0700543 tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800544 } else {
Ronghua Wua73d9e02014-10-08 15:13:29 -0700545 mPositionUs = tempUs;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800546 }
Ronghua Wua73d9e02014-10-08 15:13:29 -0700547 *msec = (int)divRound(tempUs, (int64_t)(1000));
Andreas Huber5bc087c2010-12-23 10:27:40 -0800548 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800549}
550
551status_t NuPlayerDriver::getDuration(int *msec) {
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800552 Mutex::Autolock autoLock(mLock);
553
554 if (mDurationUs < 0) {
Andreas Huberd85929f2013-04-11 11:07:55 -0700555 return UNKNOWN_ERROR;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800556 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800557
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800558 *msec = (mDurationUs + 500LL) / 1000;
Andreas Huberd85929f2013-04-11 11:07:55 -0700559
Andreas Huber5bc087c2010-12-23 10:27:40 -0800560 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800561}
562
Ray Essick54097702017-03-17 16:18:35 -0700563void NuPlayerDriver::updateMetrics(const char *where) {
Ray Essickeda32522018-02-28 12:08:28 -0800564
Ray Essickd4d00612017-01-03 09:36:27 -0800565 if (where == NULL) {
566 where = "unknown";
567 }
Ray Essick54097702017-03-17 16:18:35 -0700568 ALOGV("updateMetrics(%p) from %s at state %d", this, where, mState);
Ray Essickd4d00612017-01-03 09:36:27 -0800569
Ray Essicke99bcf22020-05-04 16:18:33 -0700570 // avoid nested locks by gathering our data outside of the metrics lock.
571
572 // final track statistics for this record
Ray Essickd4d00612017-01-03 09:36:27 -0800573 Vector<sp<AMessage>> trackStats;
574 mPlayer->getStats(&trackStats);
575
Ray Essicke99bcf22020-05-04 16:18:33 -0700576 // getDuration() uses mLock
577 int duration_ms = -1;
578 getDuration(&duration_ms);
579
580 mPlayer->updateInternalTimers();
581
582 int64_t playingTimeUs;
583 int64_t rebufferingTimeUs;
584 int32_t rebufferingEvents;
585 bool rebufferingAtExit;
586 {
587 Mutex::Autolock autoLock(mLock);
588
589 playingTimeUs = mPlayingTimeUs;
590 rebufferingTimeUs = mRebufferingTimeUs;
591 rebufferingEvents = mRebufferingEvents;
592 rebufferingAtExit = mRebufferingAtExit;
593 }
594
595 // finish the rest of the gathering under our mutex to avoid metrics races.
596 // some of the fields we read are updated under mLock.
597 Mutex::Autolock autoLock(mMetricsLock);
598
599 if (mMetricsItem == NULL) {
600 return;
601 }
602
603 mMetricsItem->setInt64(kPlayerDuration, duration_ms);
604 mMetricsItem->setInt64(kPlayerPlaying, (playingTimeUs+500)/1000 );
605
606 if (rebufferingEvents != 0) {
607 mMetricsItem->setInt64(kPlayerRebuffering, (rebufferingTimeUs+500)/1000 );
608 mMetricsItem->setInt32(kPlayerRebufferingCount, rebufferingEvents);
609 mMetricsItem->setInt32(kPlayerRebufferingAtExit, rebufferingAtExit);
610 }
611
612 mMetricsItem->setCString(kPlayerDataSourceType, mPlayer->getDataSourceType());
613
Ray Essickd4d00612017-01-03 09:36:27 -0800614 if (trackStats.size() > 0) {
615 for (size_t i = 0; i < trackStats.size(); ++i) {
616 const sp<AMessage> &stats = trackStats.itemAt(i);
617
618 AString mime;
619 stats->findString("mime", &mime);
620
621 AString name;
622 stats->findString("component-name", &name);
623
624 if (mime.startsWith("video/")) {
625 int32_t width, height;
Ray Essickf27e9872019-12-07 06:28:46 -0800626 mMetricsItem->setCString(kPlayerVMime, mime.c_str());
Ray Essickd4d00612017-01-03 09:36:27 -0800627 if (!name.empty()) {
Ray Essickf27e9872019-12-07 06:28:46 -0800628 mMetricsItem->setCString(kPlayerVCodec, name.c_str());
Ray Essickd4d00612017-01-03 09:36:27 -0800629 }
630
631 if (stats->findInt32("width", &width)
632 && stats->findInt32("height", &height)) {
Ray Essickf27e9872019-12-07 06:28:46 -0800633 mMetricsItem->setInt32(kPlayerWidth, width);
634 mMetricsItem->setInt32(kPlayerHeight, height);
Ray Essickd4d00612017-01-03 09:36:27 -0800635 }
636
637 int64_t numFramesTotal = 0;
638 int64_t numFramesDropped = 0;
639 stats->findInt64("frames-total", &numFramesTotal);
640 stats->findInt64("frames-dropped-output", &numFramesDropped);
641
Ray Essickf27e9872019-12-07 06:28:46 -0800642 mMetricsItem->setInt64(kPlayerFrames, numFramesTotal);
643 mMetricsItem->setInt64(kPlayerFramesDropped, numFramesDropped);
Ray Essickd4d00612017-01-03 09:36:27 -0800644
Ray Essick092f74a2018-11-20 10:25:13 -0800645 float frameRate = 0;
646 if (stats->findFloat("frame-rate-total", &frameRate)) {
Ray Essickf27e9872019-12-07 06:28:46 -0800647 mMetricsItem->setDouble(kPlayerFrameRate, (double) frameRate);
Ray Essick092f74a2018-11-20 10:25:13 -0800648 }
Ray Essickd4d00612017-01-03 09:36:27 -0800649
650 } else if (mime.startsWith("audio/")) {
Ray Essickf27e9872019-12-07 06:28:46 -0800651 mMetricsItem->setCString(kPlayerAMime, mime.c_str());
Ray Essickd4d00612017-01-03 09:36:27 -0800652 if (!name.empty()) {
Ray Essickf27e9872019-12-07 06:28:46 -0800653 mMetricsItem->setCString(kPlayerACodec, name.c_str());
Ray Essickd4d00612017-01-03 09:36:27 -0800654 }
655 }
656 }
Ray Essickd4d00612017-01-03 09:36:27 -0800657 }
658}
659
660
661void NuPlayerDriver::logMetrics(const char *where) {
662 if (where == NULL) {
663 where = "unknown";
664 }
Ray Essickafb43f72017-03-09 10:23:55 -0800665 ALOGV("logMetrics(%p) from %s at state %d", this, where, mState);
Ray Essickd4d00612017-01-03 09:36:27 -0800666
Ray Essicke99bcf22020-05-04 16:18:33 -0700667 // ensure mMetricsItem stability while we write it out
668 Mutex::Autolock autoLock(mMetricsLock);
669
Ray Essickf27e9872019-12-07 06:28:46 -0800670 if (mMetricsItem == NULL || mMetricsItem->isEnabled() == false) {
Ray Essickd4d00612017-01-03 09:36:27 -0800671 return;
672 }
673
Ray Essick2e82d312017-03-27 16:35:08 -0700674 // log only non-empty records
675 // we always updateMetrics() before we get here
Ray Essick39918092017-05-12 16:22:05 -0700676 // and that always injects 3 fields (duration, playing time, and
677 // datasource) into the record.
678 // So the canonical "empty" record has 3 elements in it.
Ray Essickf27e9872019-12-07 06:28:46 -0800679 if (mMetricsItem->count() > 3) {
Ray Essickd4d00612017-01-03 09:36:27 -0800680
Ray Essickf27e9872019-12-07 06:28:46 -0800681 mMetricsItem->selfrecord();
Ray Essickd4d00612017-01-03 09:36:27 -0800682
683 // re-init in case we prepare() and start() again.
Ray Essickf27e9872019-12-07 06:28:46 -0800684 delete mMetricsItem ;
685 mMetricsItem = mediametrics::Item::create(kKeyPlayer);
686 if (mMetricsItem) {
687 mMetricsItem->setUid(mClientUid);
Ray Essickd4d00612017-01-03 09:36:27 -0800688 }
689 } else {
Ray Essickf27e9872019-12-07 06:28:46 -0800690 ALOGV("nothing to record (only %zu fields)", mMetricsItem->count());
Ray Essickd4d00612017-01-03 09:36:27 -0800691 }
692}
693
Andreas Huberf9334412010-12-15 15:17:42 -0800694status_t NuPlayerDriver::reset() {
Wei Jiaf3c2b3d2015-08-06 11:39:45 -0700695 ALOGD("reset(%p) at state %d", this, mState);
Ray Essickd4d00612017-01-03 09:36:27 -0800696
Ray Essick54097702017-03-17 16:18:35 -0700697 updateMetrics("reset");
Ray Essickd4d00612017-01-03 09:36:27 -0800698 logMetrics("reset");
699
Andreas Huber1aef2112011-01-04 14:01:29 -0800700 Mutex::Autolock autoLock(mLock);
Andreas Huber1aef2112011-01-04 14:01:29 -0800701
Andreas Huber9575c962013-02-05 13:59:56 -0800702 switch (mState) {
703 case STATE_IDLE:
704 return OK;
705
706 case STATE_SET_DATASOURCE_PENDING:
707 case STATE_RESET_IN_PROGRESS:
708 return INVALID_OPERATION;
709
Andreas Huberb5f28d42013-04-25 15:11:19 -0700710 case STATE_PREPARING:
711 {
712 CHECK(mIsAsyncPrepare);
713
Wei Jia05601952014-08-20 18:21:11 -0700714 notifyListener_l(MEDIA_PREPARED);
Andreas Huberb5f28d42013-04-25 15:11:19 -0700715 break;
716 }
717
Andreas Huber9575c962013-02-05 13:59:56 -0800718 default:
719 break;
720 }
721
Lajos Molnar4b75b862013-08-15 15:59:19 -0700722 if (mState != STATE_STOPPED) {
Wei Jia05601952014-08-20 18:21:11 -0700723 notifyListener_l(MEDIA_STOPPED);
Lajos Molnar4b75b862013-08-15 15:59:19 -0700724 }
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700725
Anubhav Phukan210451e2017-07-28 13:05:31 +0530726 if (property_get_bool("persist.debug.sf.stats", false)) {
727 Vector<String16> args;
728 dump(-1, args);
729 }
730
Andreas Huber9575c962013-02-05 13:59:56 -0800731 mState = STATE_RESET_IN_PROGRESS;
Andreas Huber1aef2112011-01-04 14:01:29 -0800732 mPlayer->resetAsync();
733
Andreas Huber9575c962013-02-05 13:59:56 -0800734 while (mState == STATE_RESET_IN_PROGRESS) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800735 mCondition.wait(mLock);
736 }
737
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800738 mDurationUs = -1;
739 mPositionUs = -1;
Lajos Molnara2e14302014-07-31 12:07:58 -0700740 mLooping = false;
Ray Essickd4d00612017-01-03 09:36:27 -0800741 mPlayingTimeUs = 0;
Ray Essick58e0f7a2017-11-21 10:59:38 -0800742 mRebufferingTimeUs = 0;
743 mRebufferingEvents = 0;
744 mRebufferingAtExit = false;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800745
Andreas Huberf9334412010-12-15 15:17:42 -0800746 return OK;
747}
748
Wei Jia52c28512017-09-13 18:17:51 -0700749status_t NuPlayerDriver::notifyAt(int64_t mediaTimeUs) {
750 ALOGV("notifyAt(%p), time:%lld", this, (long long)mediaTimeUs);
751 return mPlayer->notifyAt(mediaTimeUs);
752}
753
Lajos Molnara2e14302014-07-31 12:07:58 -0700754status_t NuPlayerDriver::setLooping(int loop) {
755 mLooping = loop != 0;
756 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800757}
758
759player_type NuPlayerDriver::playerType() {
760 return NU_PLAYER;
761}
762
763status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
James Dong0d268a32012-08-31 12:18:27 -0700764 if (reply == NULL) {
765 ALOGE("reply is a NULL pointer");
766 return BAD_VALUE;
767 }
768
769 int32_t methodId;
770 status_t ret = request.readInt32(&methodId);
771 if (ret != OK) {
772 ALOGE("Failed to retrieve the requested method to invoke");
773 return ret;
774 }
775
776 switch (methodId) {
777 case INVOKE_ID_SET_VIDEO_SCALING_MODE:
778 {
779 int mode = request.readInt32();
780 return mPlayer->setVideoScalingMode(mode);
781 }
Andreas Huberd5e56232013-03-12 11:01:43 -0700782
Chong Zhangdcb89b32013-08-06 09:44:47 -0700783 case INVOKE_ID_GET_TRACK_INFO:
784 {
785 return mPlayer->getTrackInfo(reply);
786 }
787
788 case INVOKE_ID_SELECT_TRACK:
789 {
790 int trackIndex = request.readInt32();
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700791 int msec = 0;
792 // getCurrentPosition should always return OK
793 getCurrentPosition(&msec);
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800794 return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000LL);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700795 }
796
797 case INVOKE_ID_UNSELECT_TRACK:
798 {
799 int trackIndex = request.readInt32();
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700800 return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700801 }
802
Robert Shih7c4f0d72014-07-09 18:53:31 -0700803 case INVOKE_ID_GET_SELECTED_TRACK:
804 {
805 int32_t type = request.readInt32();
806 return mPlayer->getSelectedTrack(type, reply);
807 }
808
Vlad Popab4f5b012022-08-12 15:53:09 +0200809 case INVOKE_ID_SET_PLAYER_IID:
810 {
811 Mutex::Autolock autoLock(mAudioSinkLock);
812 mCachedPlayerIId = request.readInt32();
813 if (mAudioSink != nullptr) {
814 mAudioSink->setPlayerIId(mCachedPlayerIId);
815 }
816 return OK;
817 }
818
James Dong0d268a32012-08-31 12:18:27 -0700819 default:
820 {
821 return INVALID_OPERATION;
822 }
823 }
Andreas Huberf9334412010-12-15 15:17:42 -0800824}
825
826void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
Vlad Popab4f5b012022-08-12 15:53:09 +0200827 Mutex::Autolock autoLock(mAudioSinkLock);
Andreas Huberf9334412010-12-15 15:17:42 -0800828 mPlayer->setAudioSink(audioSink);
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700829 mAudioSink = audioSink;
Vlad Popab4f5b012022-08-12 15:53:09 +0200830 if (mCachedPlayerIId != PLAYER_PIID_INVALID) {
831 mAudioSink->setPlayerIId(mCachedPlayerIId);
832 }
Andreas Huberf9334412010-12-15 15:17:42 -0800833}
834
Andreas Huber84333e02014-02-07 15:36:10 -0800835status_t NuPlayerDriver::setParameter(
Lajos Molnared809da2020-08-17 16:53:02 -0700836 int key, const Parcel &request ) {
Kim Sungyeon23b23932019-07-18 17:48:32 +0900837 if (key == KEY_PARAMETER_RTP_ATTRIBUTES) {
838 mPlayer->setTargetBitrate(request.readInt32());
839 return OK;
840 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700841 return INVALID_OPERATION;
842}
843
Ray Essickdb122142017-01-25 17:51:55 -0800844status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
845
Ray Essicke99bcf22020-05-04 16:18:33 -0700846 if (key == FOURCC('m','t','r','X')) {
Ray Essickdb122142017-01-25 17:51:55 -0800847 // mtrX -- a play on 'metrics' (not matrix)
848 // gather current info all together, parcel it, and send it back
Ray Essick54097702017-03-17 16:18:35 -0700849 updateMetrics("api");
Ray Essicke99bcf22020-05-04 16:18:33 -0700850
851 // ensure mMetricsItem stability while writing to parcel
852 Mutex::Autolock autoLock(mMetricsLock);
853 if (mMetricsItem != NULL) {
854 mMetricsItem->writeToParcel(reply);
855 }
Ray Essickdb122142017-01-25 17:51:55 -0800856 return OK;
857 }
858
Gloria Wang4f9e47f2011-04-25 17:28:22 -0700859 return INVALID_OPERATION;
860}
861
Andreas Huberf9334412010-12-15 15:17:42 -0800862status_t NuPlayerDriver::getMetadata(
Andreas Huber84333e02014-02-07 15:36:10 -0800863 const media::Metadata::Filter& /* ids */, Parcel *records) {
Andreas Huber9575c962013-02-05 13:59:56 -0800864 Mutex::Autolock autoLock(mLock);
865
866 using media::Metadata;
867
868 Metadata meta(records);
869
870 meta.appendBool(
871 Metadata::kPauseAvailable,
872 mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
873
874 meta.appendBool(
875 Metadata::kSeekBackwardAvailable,
876 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
877
878 meta.appendBool(
879 Metadata::kSeekForwardAvailable,
880 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
881
882 meta.appendBool(
883 Metadata::kSeekAvailable,
884 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
885
886 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800887}
888
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800889void NuPlayerDriver::notifyResetComplete() {
Andy Hung8d121d42014-10-03 09:53:53 -0700890 ALOGD("notifyResetComplete(%p)", this);
Andreas Huber1aef2112011-01-04 14:01:29 -0800891 Mutex::Autolock autoLock(mLock);
Andreas Huber9575c962013-02-05 13:59:56 -0800892
893 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
894 mState = STATE_IDLE;
Andreas Huber1aef2112011-01-04 14:01:29 -0800895 mCondition.broadcast();
896}
897
Chong Zhang13d6faa2014-08-22 15:35:28 -0700898void NuPlayerDriver::notifySetSurfaceComplete() {
Andy Hung2abde2c2014-09-30 14:40:32 -0700899 ALOGV("notifySetSurfaceComplete(%p)", this);
Chong Zhang13d6faa2014-08-22 15:35:28 -0700900 Mutex::Autolock autoLock(mLock);
901
902 CHECK(mSetSurfaceInProgress);
903 mSetSurfaceInProgress = false;
904
905 mCondition.broadcast();
906}
907
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800908void NuPlayerDriver::notifyDuration(int64_t durationUs) {
909 Mutex::Autolock autoLock(mLock);
910 mDurationUs = durationUs;
911}
912
Ray Essickd4d00612017-01-03 09:36:27 -0800913void NuPlayerDriver::notifyMorePlayingTimeUs(int64_t playingUs) {
914 Mutex::Autolock autoLock(mLock);
915 mPlayingTimeUs += playingUs;
916}
917
Ray Essick58e0f7a2017-11-21 10:59:38 -0800918void NuPlayerDriver::notifyMoreRebufferingTimeUs(int64_t rebufferingUs) {
919 Mutex::Autolock autoLock(mLock);
920 mRebufferingTimeUs += rebufferingUs;
921 mRebufferingEvents++;
922}
923
924void NuPlayerDriver::notifyRebufferingWhenExit(bool status) {
925 Mutex::Autolock autoLock(mLock);
926 mRebufferingAtExit = status;
927}
928
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800929void NuPlayerDriver::notifySeekComplete() {
Andy Hung2abde2c2014-09-30 14:40:32 -0700930 ALOGV("notifySeekComplete(%p)", this);
Marco Nelisseneb645a02014-08-20 09:44:44 -0700931 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700932 mSeekInProgress = false;
Marco Nelisseneb645a02014-08-20 09:44:44 -0700933 notifySeekComplete_l();
934}
935
936void NuPlayerDriver::notifySeekComplete_l() {
Lajos Molnar4b75b862013-08-15 15:59:19 -0700937 bool wasSeeking = true;
Marco Nelisseneb645a02014-08-20 09:44:44 -0700938 if (mState == STATE_STOPPED_AND_PREPARING) {
939 wasSeeking = false;
940 mState = STATE_STOPPED_AND_PREPARED;
941 mCondition.broadcast();
942 if (!mIsAsyncPrepare) {
943 // if we are preparing synchronously, no need to notify listener
Lajos Molnar4b75b862013-08-15 15:59:19 -0700944 return;
945 }
Marco Nelisseneb645a02014-08-20 09:44:44 -0700946 } else if (mState == STATE_STOPPED) {
947 // no need to notify listener
948 return;
Lajos Molnar4b75b862013-08-15 15:59:19 -0700949 }
Wei Jia05601952014-08-20 18:21:11 -0700950 notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800951}
952
Andreas Huber84333e02014-02-07 15:36:10 -0800953status_t NuPlayerDriver::dump(
954 int fd, const Vector<String16> & /* args */) const {
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700955
956 Vector<sp<AMessage> > trackStats;
957 mPlayer->getStats(&trackStats);
Andreas Huber3fe62152011-09-16 15:09:22 -0700958
Praveen Chavan3a20d292015-05-21 08:47:34 -0700959 AString logString(" NuPlayer\n");
960 char buf[256] = {0};
Andreas Huber3fe62152011-09-16 15:09:22 -0700961
Wei Jia1de22232017-01-04 16:09:50 -0800962 bool locked = false;
963 for (int i = 0; i < kDumpLockRetries; ++i) {
964 if (mLock.tryLock() == NO_ERROR) {
965 locked = true;
966 break;
967 }
968 usleep(kDumpLockSleepUs);
969 }
970
971 if (locked) {
972 snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
973 mState, mAtEOS, mLooping, mAutoLoop);
974 mLock.unlock();
975 } else {
976 snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
977 }
978 logString.append(buf);
979
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700980 for (size_t i = 0; i < trackStats.size(); ++i) {
981 const sp<AMessage> &stats = trackStats.itemAt(i);
Andreas Huber3fe62152011-09-16 15:09:22 -0700982
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700983 AString mime;
984 if (stats->findString("mime", &mime)) {
Praveen Chavan3a20d292015-05-21 08:47:34 -0700985 snprintf(buf, sizeof(buf), " mime(%s)\n", mime.c_str());
986 logString.append(buf);
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700987 }
988
989 AString name;
990 if (stats->findString("component-name", &name)) {
Praveen Chavan3a20d292015-05-21 08:47:34 -0700991 snprintf(buf, sizeof(buf), " decoder(%s)\n", name.c_str());
992 logString.append(buf);
Praveen Chavane1e5d7a2015-05-19 19:09:48 -0700993 }
994
995 if (mime.startsWith("video/")) {
996 int32_t width, height;
997 if (stats->findInt32("width", &width)
998 && stats->findInt32("height", &height)) {
Praveen Chavan3a20d292015-05-21 08:47:34 -0700999 snprintf(buf, sizeof(buf), " resolution(%d x %d)\n", width, height);
1000 logString.append(buf);
Praveen Chavane1e5d7a2015-05-19 19:09:48 -07001001 }
1002
1003 int64_t numFramesTotal = 0;
1004 int64_t numFramesDropped = 0;
1005
1006 stats->findInt64("frames-total", &numFramesTotal);
1007 stats->findInt64("frames-dropped-output", &numFramesDropped);
Praveen Chavan3a20d292015-05-21 08:47:34 -07001008 snprintf(buf, sizeof(buf), " numFramesTotal(%lld), numFramesDropped(%lld), "
Praveen Chavane1e5d7a2015-05-19 19:09:48 -07001009 "percentageDropped(%.2f%%)\n",
1010 (long long)numFramesTotal,
1011 (long long)numFramesDropped,
1012 numFramesTotal == 0
1013 ? 0.0 : (double)(numFramesDropped * 100) / numFramesTotal);
Praveen Chavan3a20d292015-05-21 08:47:34 -07001014 logString.append(buf);
Praveen Chavane1e5d7a2015-05-19 19:09:48 -07001015 }
1016 }
Praveen Chavan3a20d292015-05-21 08:47:34 -07001017
1018 ALOGI("%s", logString.c_str());
1019
1020 if (fd >= 0) {
1021 FILE *out = fdopen(dup(fd), "w");
1022 fprintf(out, "%s", logString.c_str());
1023 fclose(out);
1024 out = NULL;
1025 }
Andreas Huber3fe62152011-09-16 15:09:22 -07001026
1027 return OK;
1028}
1029
Chong Zhangdcb89b32013-08-06 09:44:47 -07001030void NuPlayerDriver::notifyListener(
1031 int msg, int ext1, int ext2, const Parcel *in) {
Wei Jia05601952014-08-20 18:21:11 -07001032 Mutex::Autolock autoLock(mLock);
1033 notifyListener_l(msg, ext1, ext2, in);
1034}
1035
1036void NuPlayerDriver::notifyListener_l(
1037 int msg, int ext1, int ext2, const Parcel *in) {
Siarhei Vishniakou6b0b5262019-01-25 19:48:31 -08001038 ALOGV("notifyListener_l(%p), (%d, %d, %d, %d), loop setting(%d, %d)",
Hassan Shojaniacefac142017-02-06 21:02:02 -08001039 this, msg, ext1, ext2, (in == NULL ? -1 : (int)in->dataSize()), mAutoLoop, mLooping);
Lajos Molnara2e14302014-07-31 12:07:58 -07001040 switch (msg) {
1041 case MEDIA_PLAYBACK_COMPLETE:
1042 {
Wei Jia71079fc2014-09-10 10:06:11 -07001043 if (mState != STATE_RESET_IN_PROGRESS) {
Marco Nelissen707eade2014-11-18 09:50:35 -08001044 if (mAutoLoop) {
1045 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
Vlad Popab4f5b012022-08-12 15:53:09 +02001046 Mutex::Autolock autoLock(mAudioSinkLock);
Marco Nelissen707eade2014-11-18 09:50:35 -08001047 if (mAudioSink != NULL) {
1048 streamType = mAudioSink->getAudioStreamType();
1049 }
1050 if (streamType == AUDIO_STREAM_NOTIFICATION) {
1051 ALOGW("disabling auto-loop for notification");
1052 mAutoLoop = false;
1053 }
1054 }
Marco Nelissenb7848f12014-12-04 08:57:56 -08001055 if (mLooping || mAutoLoop) {
Wei Jia71079fc2014-09-10 10:06:11 -07001056 mPlayer->seekToAsync(0);
Vlad Popab4f5b012022-08-12 15:53:09 +02001057 Mutex::Autolock autoLock(mAudioSinkLock);
Marco Nelissen368e3372014-11-11 13:56:44 -08001058 if (mAudioSink != NULL) {
1059 // The renderer has stopped the sink at the end in order to play out
1060 // the last little bit of audio. If we're looping, we need to restart it.
1061 mAudioSink->start();
1062 }
Marco Nelissen0e4bd4d2015-10-08 10:00:34 -07001063 // don't send completion event when looping
1064 return;
Wei Jia71079fc2014-09-10 10:06:11 -07001065 }
Santhosh Beharaddd11ad2017-06-13 15:01:35 +05301066 if (property_get_bool("persist.debug.sf.stats", false)) {
1067 Vector<String16> args;
1068 dump(-1, args);
1069 }
Wei Jia71079fc2014-09-10 10:06:11 -07001070 mPlayer->pause();
Lajos Molnar18def1b2014-08-01 13:39:30 -07001071 mState = STATE_PAUSED;
Lajos Molnara2e14302014-07-31 12:07:58 -07001072 }
Chih-Hung Hsiehc89566d2018-09-13 14:22:06 -07001073 FALLTHROUGH_INTENDED;
Marco Nelissenc6993232014-07-02 15:01:57 -07001074 }
Lajos Molnara2e14302014-07-31 12:07:58 -07001075
1076 case MEDIA_ERROR:
1077 {
Ray Essickafb43f72017-03-09 10:23:55 -08001078 // when we have an error, add it to the analytics for this playback.
1079 // ext1 is our primary 'error type' value. Only add ext2 when non-zero.
1080 // [test against msg is due to fall through from previous switch value]
Ray Essicke99bcf22020-05-04 16:18:33 -07001081 if (msg == MEDIA_ERROR) {
1082 Mutex::Autolock autoLock(mMetricsLock);
1083 if (mMetricsItem != NULL) {
1084 mMetricsItem->setInt32(kPlayerError, ext1);
1085 if (ext2 != 0) {
1086 mMetricsItem->setInt32(kPlayerErrorCode, ext2);
1087 }
1088 mMetricsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
Ray Essickafb43f72017-03-09 10:23:55 -08001089 }
1090 }
Lajos Molnara2e14302014-07-31 12:07:58 -07001091 mAtEOS = true;
1092 break;
1093 }
1094
1095 default:
1096 break;
Andreas Hubera4af2142011-10-26 15:23:31 -07001097 }
1098
Wei Jia05601952014-08-20 18:21:11 -07001099 mLock.unlock();
Chong Zhangdcb89b32013-08-06 09:44:47 -07001100 sendEvent(msg, ext1, ext2, in);
Wei Jia05601952014-08-20 18:21:11 -07001101 mLock.lock();
Andreas Hubera4af2142011-10-26 15:23:31 -07001102}
1103
Andreas Huber9575c962013-02-05 13:59:56 -08001104void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
1105 Mutex::Autolock autoLock(mLock);
1106
1107 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
1108
1109 mAsyncResult = err;
1110 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
1111 mCondition.broadcast();
1112}
1113
1114void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
Hassan Shojaniacefac142017-02-06 21:02:02 -08001115 ALOGV("notifyPrepareCompleted %d", err);
1116
Andreas Huber9575c962013-02-05 13:59:56 -08001117 Mutex::Autolock autoLock(mLock);
1118
Andreas Huberb5f28d42013-04-25 15:11:19 -07001119 if (mState != STATE_PREPARING) {
1120 // We were preparing asynchronously when the client called
1121 // reset(), we sent a premature "prepared" notification and
1122 // then initiated the reset. This notification is stale.
1123 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
1124 return;
1125 }
1126
Andreas Huber9575c962013-02-05 13:59:56 -08001127 CHECK_EQ(mState, STATE_PREPARING);
1128
1129 mAsyncResult = err;
1130
1131 if (err == OK) {
Marco Nelissen2a79c322014-08-26 13:57:32 -07001132 // update state before notifying client, so that if client calls back into NuPlayerDriver
1133 // in response, NuPlayerDriver has the right state
1134 mState = STATE_PREPARED;
Andreas Huberec0c5972013-02-05 14:47:13 -08001135 if (mIsAsyncPrepare) {
Wei Jia05601952014-08-20 18:21:11 -07001136 notifyListener_l(MEDIA_PREPARED);
Andreas Huberec0c5972013-02-05 14:47:13 -08001137 }
Andreas Huber9575c962013-02-05 13:59:56 -08001138 } else {
Marco Nelissen2a79c322014-08-26 13:57:32 -07001139 mState = STATE_UNPREPARED;
Andreas Huberec0c5972013-02-05 14:47:13 -08001140 if (mIsAsyncPrepare) {
Wei Jia05601952014-08-20 18:21:11 -07001141 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
Andreas Huberec0c5972013-02-05 14:47:13 -08001142 }
Andreas Huber9575c962013-02-05 13:59:56 -08001143 }
1144
Marco Nelissenf0b72b52014-09-16 15:43:44 -07001145 sp<MetaData> meta = mPlayer->getFileMeta();
1146 int32_t loop;
1147 if (meta != NULL
1148 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
1149 mAutoLoop = true;
1150 }
1151
Andreas Huber9575c962013-02-05 13:59:56 -08001152 mCondition.broadcast();
1153}
1154
1155void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
1156 Mutex::Autolock autoLock(mLock);
1157
1158 mPlayerFlags = flags;
1159}
1160
Hassan Shojaniacefac142017-02-06 21:02:02 -08001161// Modular DRM
1162status_t NuPlayerDriver::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
1163{
1164 ALOGV("prepareDrm(%p) state: %d", this, mState);
1165
Hassan Shojaniacefac142017-02-06 21:02:02 -08001166 // leaving the state verification for mediaplayer.cpp
1167 status_t ret = mPlayer->prepareDrm(uuid, drmSessionId);
1168
1169 ALOGV("prepareDrm ret: %d", ret);
1170
1171 return ret;
1172}
1173
1174status_t NuPlayerDriver::releaseDrm()
1175{
1176 ALOGV("releaseDrm(%p) state: %d", this, mState);
1177
Hassan Shojaniacefac142017-02-06 21:02:02 -08001178 // leaving the state verification for mediaplayer.cpp
1179 status_t ret = mPlayer->releaseDrm();
1180
1181 ALOGV("releaseDrm ret: %d", ret);
1182
1183 return ret;
1184}
1185
Ray Essick51f4c872017-12-15 12:27:56 -08001186std::string NuPlayerDriver::stateString(State state) {
1187 const char *rval = NULL;
1188 char rawbuffer[16]; // allows "%d"
1189
1190 switch (state) {
1191 case STATE_IDLE: rval = "IDLE"; break;
1192 case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
1193 case STATE_UNPREPARED: rval = "UNPREPARED"; break;
1194 case STATE_PREPARING: rval = "PREPARING"; break;
1195 case STATE_PREPARED: rval = "PREPARED"; break;
1196 case STATE_RUNNING: rval = "RUNNING"; break;
1197 case STATE_PAUSED: rval = "PAUSED"; break;
1198 case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
1199 case STATE_STOPPED: rval = "STOPPED"; break;
1200 case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
1201 case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
1202 default:
1203 // yes, this buffer is shared and vulnerable to races
1204 snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
1205 rval = rawbuffer;
1206 break;
1207 }
1208
1209 return rval;
1210}
1211
Andreas Huberf9334412010-12-15 15:17:42 -08001212} // namespace android