blob: 75d06b834d4f08918018bf19735e7f19907125db [file] [log] [blame]
Wei Jia53692fa2017-12-11 10:33:46 -08001/*
2**
3** Copyright 2017, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "MediaPlayer2Native"
20
21#include <fcntl.h>
22#include <inttypes.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <unistd.h>
26
27#include <utils/Log.h>
28
29#include <binder/IServiceManager.h>
30#include <binder/IPCThreadState.h>
31
Wei Jia53692fa2017-12-11 10:33:46 -080032#include <media/AudioResamplerPublic.h>
33#include <media/AudioSystem.h>
34#include <media/AVSyncSettings.h>
Wei Jiac5c79da2017-12-21 18:03:05 -080035#include <media/DataSource.h>
Wei Jiac2636032018-02-01 09:15:25 -080036#include <media/DataSourceDesc.h>
Wei Jia53692fa2017-12-11 10:33:46 -080037#include <media/MediaAnalyticsItem.h>
Wei Jia28288fb2017-12-15 13:45:29 -080038#include <media/NdkWrapper.h>
Wei Jia51b69562018-02-05 16:17:13 -080039#include <mediaplayer2/mediaplayer2.h>
Wei Jia53692fa2017-12-11 10:33:46 -080040
41#include <binder/MemoryBase.h>
42
43#include <utils/KeyedVector.h>
44#include <utils/String8.h>
45
46#include <system/audio.h>
47#include <system/window.h>
48
49#include "MediaPlayer2Manager.h"
50
51namespace android {
52
Wei Jia53692fa2017-12-11 10:33:46 -080053MediaPlayer2::MediaPlayer2()
54{
55 ALOGV("constructor");
Wei Jiad2bb1bd2018-02-08 09:47:37 -080056 mSrcId = 0;
Wei Jia53692fa2017-12-11 10:33:46 -080057 mListener = NULL;
58 mCookie = NULL;
59 mStreamType = AUDIO_STREAM_MUSIC;
60 mAudioAttributesParcel = NULL;
61 mCurrentPosition = -1;
62 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
63 mSeekPosition = -1;
64 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
65 mCurrentState = MEDIA_PLAYER2_IDLE;
Wei Jia53692fa2017-12-11 10:33:46 -080066 mLoop = false;
67 mLeftVolume = mRightVolume = 1.0;
68 mVideoWidth = mVideoHeight = 0;
69 mLockThreadId = 0;
70 mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
71 AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
72 mSendLevel = 0;
Wei Jia53692fa2017-12-11 10:33:46 -080073}
74
75MediaPlayer2::~MediaPlayer2()
76{
77 ALOGV("destructor");
78 if (mAudioAttributesParcel != NULL) {
79 delete mAudioAttributesParcel;
80 mAudioAttributesParcel = NULL;
81 }
82 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
83 disconnect();
84 IPCThreadState::self()->flushCommands();
85}
86
87void MediaPlayer2::disconnect()
88{
89 ALOGV("disconnect");
90 sp<MediaPlayer2Engine> p;
91 {
92 Mutex::Autolock _l(mLock);
93 p = mPlayer;
94 mPlayer.clear();
95 }
96
97 if (p != 0) {
98 p->disconnect();
99 }
100}
101
102// always call with lock held
103void MediaPlayer2::clear_l()
104{
105 mCurrentPosition = -1;
106 mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
107 mSeekPosition = -1;
108 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
109 mVideoWidth = mVideoHeight = 0;
Wei Jia53692fa2017-12-11 10:33:46 -0800110}
111
112status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener)
113{
114 ALOGV("setListener");
115 Mutex::Autolock _l(mLock);
116 mListener = listener;
117 return NO_ERROR;
118}
119
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800120status_t MediaPlayer2::getSrcId(int64_t *srcId) {
121 if (srcId == NULL) {
122 return BAD_VALUE;
123 }
Wei Jia53692fa2017-12-11 10:33:46 -0800124
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800125 Mutex::Autolock _l(mLock);
126 *srcId = mSrcId;
127 return OK;
128}
129
130status_t MediaPlayer2::attachNewPlayer(const sp<MediaPlayer2Engine>& player, long srcId)
Wei Jia53692fa2017-12-11 10:33:46 -0800131{
132 status_t err = UNKNOWN_ERROR;
133 sp<MediaPlayer2Engine> p;
134 { // scope for the lock
135 Mutex::Autolock _l(mLock);
136
137 if ( !( (mCurrentState & MEDIA_PLAYER2_IDLE) ||
138 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR ) ) ) {
139 ALOGE("attachNewPlayer called in state %d", mCurrentState);
140 return INVALID_OPERATION;
141 }
142
143 clear_l();
144 p = mPlayer;
145 mPlayer = player;
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800146 mSrcId = srcId;
Wei Jia53692fa2017-12-11 10:33:46 -0800147 if (player != 0) {
148 mCurrentState = MEDIA_PLAYER2_INITIALIZED;
149 err = NO_ERROR;
150 } else {
151 ALOGE("Unable to create media player");
152 }
153 }
154
155 if (p != 0) {
156 p->disconnect();
157 }
158
159 return err;
160}
161
Wei Jiac2636032018-02-01 09:15:25 -0800162status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd)
Wei Jia53692fa2017-12-11 10:33:46 -0800163{
Wei Jiac2636032018-02-01 09:15:25 -0800164 if (dsd == NULL) {
165 return BAD_VALUE;
Wei Jia53692fa2017-12-11 10:33:46 -0800166 }
Wei Jiac2636032018-02-01 09:15:25 -0800167 ALOGV("setDataSource type(%d)", dsd->mType);
Wei Jia53692fa2017-12-11 10:33:46 -0800168 status_t err = UNKNOWN_ERROR;
169 sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
Wei Jia65fdcf72018-02-02 17:43:04 -0800170 if (NO_ERROR != player->setDataSource(dsd)) {
Wei Jia53692fa2017-12-11 10:33:46 -0800171 player.clear();
172 }
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800173 err = attachNewPlayer(player, dsd->mId);
Wei Jia53692fa2017-12-11 10:33:46 -0800174 return err;
175}
176
Wei Jia57aeffd2018-02-15 16:01:14 -0800177status_t MediaPlayer2::prepareNextDataSource(const sp<DataSourceDesc> &dsd) {
178 if (dsd == NULL) {
179 return BAD_VALUE;
180 }
181 ALOGV("prepareNextDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
182
183 Mutex::Autolock _l(mLock);
184 if (mPlayer != NULL) {
185 return mPlayer->prepareNextDataSource(dsd);
186 }
187 ALOGE("prepareNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
188 return INVALID_OPERATION;
189}
190
191status_t MediaPlayer2::playNextDataSource(int64_t srcId) {
192 ALOGV("playNextDataSource srcId(%lld)", (long long)srcId);
193
194 Mutex::Autolock _l(mLock);
195 if (mPlayer != NULL) {
196 mSrcId = srcId;
197 return mPlayer->playNextDataSource(srcId);
198 }
199 ALOGE("playNextDataSource failed: state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
200 return INVALID_OPERATION;
201}
202
Wei Jia53692fa2017-12-11 10:33:46 -0800203status_t MediaPlayer2::invoke(const Parcel& request, Parcel *reply)
204{
205 Mutex::Autolock _l(mLock);
206 const bool hasBeenInitialized =
207 (mCurrentState != MEDIA_PLAYER2_STATE_ERROR) &&
208 ((mCurrentState & MEDIA_PLAYER2_IDLE) != MEDIA_PLAYER2_IDLE);
209 if ((mPlayer != NULL) && hasBeenInitialized) {
210 ALOGV("invoke %zu", request.dataSize());
211 return mPlayer->invoke(request, reply);
212 }
213 ALOGE("invoke failed: wrong state %X, mPlayer(%p)", mCurrentState, mPlayer.get());
214 return INVALID_OPERATION;
215}
216
217status_t MediaPlayer2::setMetadataFilter(const Parcel& filter)
218{
219 ALOGD("setMetadataFilter");
220 Mutex::Autolock lock(mLock);
221 if (mPlayer == NULL) {
222 return NO_INIT;
223 }
224 return mPlayer->setMetadataFilter(filter);
225}
226
227status_t MediaPlayer2::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
228{
229 ALOGD("getMetadata");
230 Mutex::Autolock lock(mLock);
231 if (mPlayer == NULL) {
232 return NO_INIT;
233 }
234 return mPlayer->getMetadata(update_only, apply_filter, metadata);
235}
236
Wei Jia28288fb2017-12-15 13:45:29 -0800237status_t MediaPlayer2::setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww)
Wei Jia53692fa2017-12-11 10:33:46 -0800238{
239 ALOGV("setVideoSurfaceTexture");
240 Mutex::Autolock _l(mLock);
241 if (mPlayer == 0) return NO_INIT;
Wei Jia28288fb2017-12-15 13:45:29 -0800242 return mPlayer->setVideoSurfaceTexture(nww);
Wei Jia53692fa2017-12-11 10:33:46 -0800243}
244
245status_t MediaPlayer2::getBufferingSettings(BufferingSettings* buffering /* nonnull */)
246{
247 ALOGV("getBufferingSettings");
248
249 Mutex::Autolock _l(mLock);
250 if (mPlayer == 0) {
251 return NO_INIT;
252 }
253 return mPlayer->getBufferingSettings(buffering);
254}
255
256status_t MediaPlayer2::setBufferingSettings(const BufferingSettings& buffering)
257{
258 ALOGV("setBufferingSettings");
259
260 Mutex::Autolock _l(mLock);
261 if (mPlayer == 0) {
262 return NO_INIT;
263 }
264 return mPlayer->setBufferingSettings(buffering);
265}
266
267// must call with lock held
268status_t MediaPlayer2::prepareAsync_l()
269{
270 if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER2_INITIALIZED | MEDIA_PLAYER2_STOPPED) ) ) {
271 if (mAudioAttributesParcel != NULL) {
272 mPlayer->setParameter(MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
273 } else {
274 mPlayer->setAudioStreamType(mStreamType);
275 }
276 mCurrentState = MEDIA_PLAYER2_PREPARING;
277 return mPlayer->prepareAsync();
278 }
279 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
280 return INVALID_OPERATION;
281}
282
Wei Jia53692fa2017-12-11 10:33:46 -0800283status_t MediaPlayer2::prepareAsync()
284{
285 ALOGV("prepareAsync");
286 Mutex::Autolock _l(mLock);
287 return prepareAsync_l();
288}
289
290status_t MediaPlayer2::start()
291{
292 ALOGV("start");
293
294 status_t ret = NO_ERROR;
295 Mutex::Autolock _l(mLock);
296
297 mLockThreadId = getThreadId();
298
299 if (mCurrentState & MEDIA_PLAYER2_STARTED) {
300 ret = NO_ERROR;
301 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_PREPARED |
302 MEDIA_PLAYER2_PLAYBACK_COMPLETE | MEDIA_PLAYER2_PAUSED ) ) ) {
303 mPlayer->setLooping(mLoop);
304 mPlayer->setVolume(mLeftVolume, mRightVolume);
305 mPlayer->setAuxEffectSendLevel(mSendLevel);
306 mCurrentState = MEDIA_PLAYER2_STARTED;
307 ret = mPlayer->start();
308 if (ret != NO_ERROR) {
309 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
310 } else {
311 if (mCurrentState == MEDIA_PLAYER2_PLAYBACK_COMPLETE) {
312 ALOGV("playback completed immediately following start()");
313 }
314 }
315 } else {
316 ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
317 ret = INVALID_OPERATION;
318 }
319
320 mLockThreadId = 0;
321
322 return ret;
323}
324
325status_t MediaPlayer2::stop()
326{
327 ALOGV("stop");
328 Mutex::Autolock _l(mLock);
329 if (mCurrentState & MEDIA_PLAYER2_STOPPED) return NO_ERROR;
330 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
331 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) ) {
332 status_t ret = mPlayer->stop();
333 if (ret != NO_ERROR) {
334 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
335 } else {
336 mCurrentState = MEDIA_PLAYER2_STOPPED;
337 }
338 return ret;
339 }
340 ALOGE("stop called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
341 return INVALID_OPERATION;
342}
343
344status_t MediaPlayer2::pause()
345{
346 ALOGV("pause");
347 Mutex::Autolock _l(mLock);
348 if (mCurrentState & (MEDIA_PLAYER2_PAUSED|MEDIA_PLAYER2_PLAYBACK_COMPLETE))
349 return NO_ERROR;
350 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER2_STARTED)) {
351 status_t ret = mPlayer->pause();
352 if (ret != NO_ERROR) {
353 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
354 } else {
355 mCurrentState = MEDIA_PLAYER2_PAUSED;
356 }
357 return ret;
358 }
359 ALOGE("pause called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
360 return INVALID_OPERATION;
361}
362
363bool MediaPlayer2::isPlaying()
364{
365 Mutex::Autolock _l(mLock);
366 if (mPlayer != 0) {
367 bool temp = false;
368 mPlayer->isPlaying(&temp);
369 ALOGV("isPlaying: %d", temp);
370 if ((mCurrentState & MEDIA_PLAYER2_STARTED) && ! temp) {
371 ALOGE("internal/external state mismatch corrected");
372 mCurrentState = MEDIA_PLAYER2_PAUSED;
373 } else if ((mCurrentState & MEDIA_PLAYER2_PAUSED) && temp) {
374 ALOGE("internal/external state mismatch corrected");
375 mCurrentState = MEDIA_PLAYER2_STARTED;
376 }
377 return temp;
378 }
379 ALOGV("isPlaying: no active player");
380 return false;
381}
382
383status_t MediaPlayer2::setPlaybackSettings(const AudioPlaybackRate& rate)
384{
385 ALOGV("setPlaybackSettings: %f %f %d %d",
386 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
387 // Negative speed and pitch does not make sense. Further validation will
388 // be done by the respective mediaplayers.
389 if (rate.mSpeed < 0.f || rate.mPitch < 0.f) {
390 return BAD_VALUE;
391 }
392 Mutex::Autolock _l(mLock);
393 if (mPlayer == 0 || (mCurrentState & MEDIA_PLAYER2_STOPPED)) {
394 return INVALID_OPERATION;
395 }
396
397 if (rate.mSpeed != 0.f && !(mCurrentState & MEDIA_PLAYER2_STARTED)
398 && (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_PAUSED
399 | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
400 mPlayer->setLooping(mLoop);
401 mPlayer->setVolume(mLeftVolume, mRightVolume);
402 mPlayer->setAuxEffectSendLevel(mSendLevel);
403 }
404
405 status_t err = mPlayer->setPlaybackSettings(rate);
406 if (err == OK) {
407 if (rate.mSpeed == 0.f && mCurrentState == MEDIA_PLAYER2_STARTED) {
408 mCurrentState = MEDIA_PLAYER2_PAUSED;
409 } else if (rate.mSpeed != 0.f
410 && (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_PAUSED
411 | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
412 mCurrentState = MEDIA_PLAYER2_STARTED;
413 }
414 }
415 return err;
416}
417
418status_t MediaPlayer2::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
419{
420 Mutex::Autolock _l(mLock);
421 if (mPlayer == 0) return INVALID_OPERATION;
422 return mPlayer->getPlaybackSettings(rate);
423}
424
425status_t MediaPlayer2::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint)
426{
427 ALOGV("setSyncSettings: %u %u %f %f",
428 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
429 Mutex::Autolock _l(mLock);
430 if (mPlayer == 0) return INVALID_OPERATION;
431 return mPlayer->setSyncSettings(sync, videoFpsHint);
432}
433
434status_t MediaPlayer2::getSyncSettings(
435 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
436{
437 Mutex::Autolock _l(mLock);
438 if (mPlayer == 0) return INVALID_OPERATION;
439 return mPlayer->getSyncSettings(sync, videoFps);
440}
441
442status_t MediaPlayer2::getVideoWidth(int *w)
443{
444 ALOGV("getVideoWidth");
445 Mutex::Autolock _l(mLock);
446 if (mPlayer == 0) return INVALID_OPERATION;
447 *w = mVideoWidth;
448 return NO_ERROR;
449}
450
451status_t MediaPlayer2::getVideoHeight(int *h)
452{
453 ALOGV("getVideoHeight");
454 Mutex::Autolock _l(mLock);
455 if (mPlayer == 0) return INVALID_OPERATION;
456 *h = mVideoHeight;
457 return NO_ERROR;
458}
459
460status_t MediaPlayer2::getCurrentPosition(int *msec)
461{
462 ALOGV("getCurrentPosition");
463 Mutex::Autolock _l(mLock);
464 if (mPlayer != 0) {
465 if (mCurrentPosition >= 0) {
466 ALOGV("Using cached seek position: %d", mCurrentPosition);
467 *msec = mCurrentPosition;
468 return NO_ERROR;
469 }
470 return mPlayer->getCurrentPosition(msec);
471 }
472 return INVALID_OPERATION;
473}
474
475status_t MediaPlayer2::getDuration_l(int *msec)
476{
477 ALOGV("getDuration_l");
478 bool isValidState = (mCurrentState & (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
479 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_STOPPED | MEDIA_PLAYER2_PLAYBACK_COMPLETE));
480 if (mPlayer != 0 && isValidState) {
481 int durationMs;
482 status_t ret = mPlayer->getDuration(&durationMs);
483
484 if (ret != OK) {
485 // Do not enter error state just because no duration was available.
486 durationMs = -1;
487 ret = OK;
488 }
489
490 if (msec) {
491 *msec = durationMs;
492 }
493 return ret;
494 }
495 ALOGE("Attempt to call getDuration in wrong state: mPlayer=%p, mCurrentState=%u",
496 mPlayer.get(), mCurrentState);
497 return INVALID_OPERATION;
498}
499
500status_t MediaPlayer2::getDuration(int *msec)
501{
502 Mutex::Autolock _l(mLock);
503 return getDuration_l(msec);
504}
505
506status_t MediaPlayer2::seekTo_l(int msec, MediaPlayer2SeekMode mode)
507{
508 ALOGV("seekTo (%d, %d)", msec, mode);
509 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER2_STARTED | MEDIA_PLAYER2_PREPARED |
510 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) ) {
511 if ( msec < 0 ) {
512 ALOGW("Attempt to seek to invalid position: %d", msec);
513 msec = 0;
514 }
515
516 int durationMs;
517 status_t err = mPlayer->getDuration(&durationMs);
518
519 if (err != OK) {
520 ALOGW("Stream has no duration and is therefore not seekable.");
521 return err;
522 }
523
524 if (msec > durationMs) {
525 ALOGW("Attempt to seek to past end of file: request = %d, "
526 "durationMs = %d",
527 msec,
528 durationMs);
529
530 msec = durationMs;
531 }
532
533 // cache duration
534 mCurrentPosition = msec;
535 mCurrentSeekMode = mode;
536 if (mSeekPosition < 0) {
537 mSeekPosition = msec;
538 mSeekMode = mode;
539 return mPlayer->seekTo(msec, mode);
540 }
541 else {
542 ALOGV("Seek in progress - queue up seekTo[%d, %d]", msec, mode);
543 return NO_ERROR;
544 }
545 }
546 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(),
547 mCurrentState);
548 return INVALID_OPERATION;
549}
550
551status_t MediaPlayer2::seekTo(int msec, MediaPlayer2SeekMode mode)
552{
553 mLockThreadId = getThreadId();
554 Mutex::Autolock _l(mLock);
555 status_t result = seekTo_l(msec, mode);
556 mLockThreadId = 0;
557
558 return result;
559}
560
561status_t MediaPlayer2::notifyAt(int64_t mediaTimeUs)
562{
563 Mutex::Autolock _l(mLock);
564 if (mPlayer != 0) {
565 return mPlayer->notifyAt(mediaTimeUs);
566 }
567 return INVALID_OPERATION;
568}
569
570status_t MediaPlayer2::reset_l()
571{
572 mLoop = false;
573 if (mCurrentState == MEDIA_PLAYER2_IDLE) return NO_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -0800574 if (mPlayer != 0) {
575 status_t ret = mPlayer->reset();
576 if (ret != NO_ERROR) {
577 ALOGE("reset() failed with return code (%d)", ret);
578 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
579 } else {
580 mPlayer->disconnect();
581 mCurrentState = MEDIA_PLAYER2_IDLE;
582 }
583 // setDataSource has to be called again to create a
584 // new mediaplayer.
585 mPlayer = 0;
586 return ret;
587 }
588 clear_l();
589 return NO_ERROR;
590}
591
Wei Jia53692fa2017-12-11 10:33:46 -0800592status_t MediaPlayer2::reset()
593{
594 ALOGV("reset");
595 mLockThreadId = getThreadId();
596 Mutex::Autolock _l(mLock);
597 status_t result = reset_l();
598 mLockThreadId = 0;
599
600 return result;
601}
602
603status_t MediaPlayer2::setAudioStreamType(audio_stream_type_t type)
604{
605 ALOGV("MediaPlayer2::setAudioStreamType");
606 Mutex::Autolock _l(mLock);
607 if (mStreamType == type) return NO_ERROR;
608 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
609 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE ) ) {
610 // Can't change the stream type after prepare
611 ALOGE("setAudioStream called in state %d", mCurrentState);
612 return INVALID_OPERATION;
613 }
614 // cache
615 mStreamType = type;
616 return OK;
617}
618
619status_t MediaPlayer2::getAudioStreamType(audio_stream_type_t *type)
620{
621 ALOGV("getAudioStreamType");
622 Mutex::Autolock _l(mLock);
623 *type = mStreamType;
624 return OK;
625}
626
627status_t MediaPlayer2::setLooping(int loop)
628{
629 ALOGV("MediaPlayer2::setLooping");
630 Mutex::Autolock _l(mLock);
631 mLoop = (loop != 0);
632 if (mPlayer != 0) {
633 return mPlayer->setLooping(loop);
634 }
635 return OK;
636}
637
638bool MediaPlayer2::isLooping() {
639 ALOGV("isLooping");
640 Mutex::Autolock _l(mLock);
641 if (mPlayer != 0) {
642 return mLoop;
643 }
644 ALOGV("isLooping: no active player");
645 return false;
646}
647
648status_t MediaPlayer2::setVolume(float leftVolume, float rightVolume)
649{
650 ALOGV("MediaPlayer2::setVolume(%f, %f)", leftVolume, rightVolume);
651 Mutex::Autolock _l(mLock);
652 mLeftVolume = leftVolume;
653 mRightVolume = rightVolume;
654 if (mPlayer != 0) {
655 return mPlayer->setVolume(leftVolume, rightVolume);
656 }
657 return OK;
658}
659
660status_t MediaPlayer2::setAudioSessionId(audio_session_t sessionId)
661{
662 ALOGV("MediaPlayer2::setAudioSessionId(%d)", sessionId);
663 Mutex::Autolock _l(mLock);
664 if (!(mCurrentState & MEDIA_PLAYER2_IDLE)) {
665 ALOGE("setAudioSessionId called in state %d", mCurrentState);
666 return INVALID_OPERATION;
667 }
668 if (sessionId < 0) {
669 return BAD_VALUE;
670 }
671 if (sessionId != mAudioSessionId) {
672 AudioSystem::acquireAudioSessionId(sessionId, -1);
673 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
674 mAudioSessionId = sessionId;
675 }
676 return NO_ERROR;
677}
678
679audio_session_t MediaPlayer2::getAudioSessionId()
680{
681 Mutex::Autolock _l(mLock);
682 return mAudioSessionId;
683}
684
685status_t MediaPlayer2::setAuxEffectSendLevel(float level)
686{
687 ALOGV("MediaPlayer2::setAuxEffectSendLevel(%f)", level);
688 Mutex::Autolock _l(mLock);
689 mSendLevel = level;
690 if (mPlayer != 0) {
691 return mPlayer->setAuxEffectSendLevel(level);
692 }
693 return OK;
694}
695
696status_t MediaPlayer2::attachAuxEffect(int effectId)
697{
698 ALOGV("MediaPlayer2::attachAuxEffect(%d)", effectId);
699 Mutex::Autolock _l(mLock);
700 if (mPlayer == 0 ||
701 (mCurrentState & MEDIA_PLAYER2_IDLE) ||
702 (mCurrentState == MEDIA_PLAYER2_STATE_ERROR )) {
703 ALOGE("attachAuxEffect called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
704 return INVALID_OPERATION;
705 }
706
707 return mPlayer->attachAuxEffect(effectId);
708}
709
710// always call with lock held
711status_t MediaPlayer2::checkStateForKeySet_l(int key)
712{
713 switch(key) {
714 case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
715 if (mCurrentState & ( MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_STARTED |
716 MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE) ) {
717 // Can't change the audio attributes after prepare
718 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
719 return INVALID_OPERATION;
720 }
721 break;
722 default:
723 // parameter doesn't require player state check
724 break;
725 }
726 return OK;
727}
728
729status_t MediaPlayer2::setParameter(int key, const Parcel& request)
730{
731 ALOGV("MediaPlayer2::setParameter(%d)", key);
732 status_t status = INVALID_OPERATION;
733 Mutex::Autolock _l(mLock);
734 if (checkStateForKeySet_l(key) != OK) {
735 return status;
736 }
737 switch (key) {
738 case MEDIA2_KEY_PARAMETER_AUDIO_ATTRIBUTES:
739 // save the marshalled audio attributes
740 if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; };
741 mAudioAttributesParcel = new Parcel();
742 mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
743 status = OK;
744 break;
745 default:
746 ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
747 break;
748 }
749
750 if (mPlayer != NULL) {
751 status = mPlayer->setParameter(key, request);
752 }
753 return status;
754}
755
756status_t MediaPlayer2::getParameter(int key, Parcel *reply)
757{
758 ALOGV("MediaPlayer2::getParameter(%d)", key);
759 Mutex::Autolock _l(mLock);
760 if (mPlayer != NULL) {
761 status_t status = mPlayer->getParameter(key, reply);
762 if (status != OK) {
763 ALOGD("getParameter returns %d", status);
764 }
765 return status;
766 }
767 ALOGV("getParameter: no active player");
768 return INVALID_OPERATION;
769}
770
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800771void MediaPlayer2::notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj)
Wei Jia53692fa2017-12-11 10:33:46 -0800772{
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800773 ALOGV("message received srcId=%lld, msg=%d, ext1=%d, ext2=%d",
774 (long long)srcId, msg, ext1, ext2);
Wei Jia53692fa2017-12-11 10:33:46 -0800775 bool send = true;
776 bool locked = false;
777
778 // TODO: In the future, we might be on the same thread if the app is
779 // running in the same process as the media server. In that case,
780 // this will deadlock.
781 //
782 // The threadId hack below works around this for the care of prepare,
783 // seekTo, start, and reset within the same process.
784 // FIXME: Remember, this is a hack, it's not even a hack that is applied
785 // consistently for all use-cases, this needs to be revisited.
786 if (mLockThreadId != getThreadId()) {
787 mLock.lock();
788 locked = true;
789 }
790
791 // Allows calls from JNI in idle state to notify errors
792 if (!(msg == MEDIA2_ERROR && mCurrentState == MEDIA_PLAYER2_IDLE) && mPlayer == 0) {
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800793 ALOGV("notify(%lld, %d, %d, %d) callback on disconnected mediaplayer",
794 (long long)srcId, msg, ext1, ext2);
Wei Jia53692fa2017-12-11 10:33:46 -0800795 if (locked) mLock.unlock(); // release the lock when done.
796 return;
797 }
798
799 switch (msg) {
800 case MEDIA2_NOP: // interface test message
801 break;
802 case MEDIA2_PREPARED:
803 ALOGV("MediaPlayer2::notify() prepared");
804 mCurrentState = MEDIA_PLAYER2_PREPARED;
Wei Jia53692fa2017-12-11 10:33:46 -0800805 break;
806 case MEDIA2_DRM_INFO:
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800807 ALOGV("MediaPlayer2::notify() MEDIA2_DRM_INFO(%lld, %d, %d, %d, %p)",
808 (long long)srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -0800809 break;
810 case MEDIA2_PLAYBACK_COMPLETE:
811 ALOGV("playback complete");
812 if (mCurrentState == MEDIA_PLAYER2_IDLE) {
813 ALOGE("playback complete in idle state");
814 }
815 if (!mLoop) {
816 mCurrentState = MEDIA_PLAYER2_PLAYBACK_COMPLETE;
817 }
818 break;
819 case MEDIA2_ERROR:
820 // Always log errors.
821 // ext1: Media framework error code.
822 // ext2: Implementation dependant error code.
823 ALOGE("error (%d, %d)", ext1, ext2);
824 mCurrentState = MEDIA_PLAYER2_STATE_ERROR;
Wei Jia53692fa2017-12-11 10:33:46 -0800825 break;
826 case MEDIA2_INFO:
827 // ext1: Media framework error code.
828 // ext2: Implementation dependant error code.
829 if (ext1 != MEDIA2_INFO_VIDEO_TRACK_LAGGING) {
830 ALOGW("info/warning (%d, %d)", ext1, ext2);
831 }
832 break;
833 case MEDIA2_SEEK_COMPLETE:
834 ALOGV("Received seek complete");
835 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
836 ALOGV("Executing queued seekTo(%d, %d)", mCurrentPosition, mCurrentSeekMode);
837 mSeekPosition = -1;
838 mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
839 seekTo_l(mCurrentPosition, mCurrentSeekMode);
840 }
841 else {
842 ALOGV("All seeks complete - return to regularly scheduled program");
843 mCurrentPosition = mSeekPosition = -1;
844 mCurrentSeekMode = mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
845 }
846 break;
847 case MEDIA2_BUFFERING_UPDATE:
848 ALOGV("buffering %d", ext1);
849 break;
850 case MEDIA2_SET_VIDEO_SIZE:
851 ALOGV("New video size %d x %d", ext1, ext2);
852 mVideoWidth = ext1;
853 mVideoHeight = ext2;
854 break;
855 case MEDIA2_NOTIFY_TIME:
856 ALOGV("Received notify time message");
857 break;
858 case MEDIA2_TIMED_TEXT:
859 ALOGV("Received timed text message");
860 break;
861 case MEDIA2_SUBTITLE_DATA:
862 ALOGV("Received subtitle data message");
863 break;
864 case MEDIA2_META_DATA:
865 ALOGV("Received timed metadata message");
866 break;
867 default:
868 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
869 break;
870 }
871
872 sp<MediaPlayer2Listener> listener = mListener;
873 if (locked) mLock.unlock();
874
875 // this prevents re-entrant calls into client code
876 if ((listener != 0) && send) {
877 Mutex::Autolock _l(mNotifyLock);
878 ALOGV("callback application");
Wei Jiad2bb1bd2018-02-08 09:47:37 -0800879 listener->notify(srcId, msg, ext1, ext2, obj);
Wei Jia53692fa2017-12-11 10:33:46 -0800880 ALOGV("back from callback");
881 }
882}
883
884status_t MediaPlayer2::setNextMediaPlayer(const sp<MediaPlayer2>& next) {
885 Mutex::Autolock _l(mLock);
886 if (mPlayer == NULL) {
887 return NO_INIT;
888 }
889
890 if (next != NULL && !(next->mCurrentState &
891 (MEDIA_PLAYER2_PREPARED | MEDIA_PLAYER2_PAUSED | MEDIA_PLAYER2_PLAYBACK_COMPLETE))) {
892 ALOGE("next player is not prepared");
893 return INVALID_OPERATION;
894 }
895
896 return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
897}
898
Wei Jia53692fa2017-12-11 10:33:46 -0800899// Modular DRM
900status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId)
901{
902 // TODO change to ALOGV
903 ALOGD("prepareDrm: uuid: %p drmSessionId: %p(%zu)", uuid,
904 drmSessionId.array(), drmSessionId.size());
905 Mutex::Autolock _l(mLock);
906 if (mPlayer == NULL) {
907 return NO_INIT;
908 }
909
910 // Only allowed it in player's preparing/prepared state.
911 // We get here only if MEDIA_DRM_INFO has already arrived (e.g., prepare is half-way through or
912 // completed) so the state change to "prepared" might not have happened yet (e.g., buffering).
913 // Still, we can allow prepareDrm for the use case of being called in OnDrmInfoListener.
914 if (!(mCurrentState & (MEDIA_PLAYER2_PREPARING | MEDIA_PLAYER2_PREPARED))) {
915 ALOGE("prepareDrm is called in the wrong state (%d).", mCurrentState);
916 return INVALID_OPERATION;
917 }
918
919 if (drmSessionId.isEmpty()) {
920 ALOGE("prepareDrm: Unexpected. Can't proceed with crypto. Empty drmSessionId.");
921 return INVALID_OPERATION;
922 }
923
924 // Passing down to mediaserver mainly for creating the crypto
925 status_t status = mPlayer->prepareDrm(uuid, drmSessionId);
926 ALOGE_IF(status != OK, "prepareDrm: Failed at mediaserver with ret: %d", status);
927
928 // TODO change to ALOGV
929 ALOGD("prepareDrm: mediaserver::prepareDrm ret=%d", status);
930
931 return status;
932}
933
934status_t MediaPlayer2::releaseDrm()
935{
936 Mutex::Autolock _l(mLock);
937 if (mPlayer == NULL) {
938 return NO_INIT;
939 }
940
941 // Not allowing releaseDrm in an active/resumable state
942 if (mCurrentState & (MEDIA_PLAYER2_STARTED |
943 MEDIA_PLAYER2_PAUSED |
944 MEDIA_PLAYER2_PLAYBACK_COMPLETE |
945 MEDIA_PLAYER2_STATE_ERROR)) {
946 ALOGE("releaseDrm Unexpected state %d. Can only be called in stopped/idle.", mCurrentState);
947 return INVALID_OPERATION;
948 }
949
950 status_t status = mPlayer->releaseDrm();
951 // TODO change to ALOGV
952 ALOGD("releaseDrm: mediaserver::releaseDrm ret: %d", status);
953 if (status != OK) {
954 ALOGE("releaseDrm: Failed at mediaserver with ret: %d", status);
955 // Overriding to OK so the client proceed with its own cleanup
956 // Client can't do more cleanup. mediaserver release its crypto at end of session anyway.
957 status = OK;
958 }
959
960 return status;
961}
962
963status_t MediaPlayer2::setOutputDevice(audio_port_handle_t deviceId)
964{
965 Mutex::Autolock _l(mLock);
966 if (mPlayer == NULL) {
967 ALOGV("setOutputDevice: player not init");
968 return NO_INIT;
969 }
970 return mPlayer->setOutputDevice(deviceId);
971}
972
973audio_port_handle_t MediaPlayer2::getRoutedDeviceId()
974{
975 Mutex::Autolock _l(mLock);
976 if (mPlayer == NULL) {
977 ALOGV("getRoutedDeviceId: player not init");
978 return AUDIO_PORT_HANDLE_NONE;
979 }
980 audio_port_handle_t deviceId;
981 status_t status = mPlayer->getRoutedDeviceId(&deviceId);
982 if (status != NO_ERROR) {
983 return AUDIO_PORT_HANDLE_NONE;
984 }
985 return deviceId;
986}
987
988status_t MediaPlayer2::enableAudioDeviceCallback(bool enabled)
989{
990 Mutex::Autolock _l(mLock);
991 if (mPlayer == NULL) {
992 ALOGV("addAudioDeviceCallback: player not init");
993 return NO_INIT;
994 }
995 return mPlayer->enableAudioDeviceCallback(enabled);
996}
997
998} // namespace android