1 /*
2 **
3 ** Copyright 2006, 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 "MediaPlayer"
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
32 #include <gui/Surface.h>
33
34 #include <media/mediaplayer.h>
35 #include <media/AudioResamplerPublic.h>
36 #include <media/AudioSystem.h>
37 #include <media/AVSyncSettings.h>
38 #include <media/IDataSource.h>
39
40 #include <binder/MemoryBase.h>
41
42 #include <utils/KeyedVector.h>
43 #include <utils/String8.h>
44
45 #include <system/audio.h>
46 #include <system/window.h>
47
48 namespace android {
49
MediaPlayer()50 MediaPlayer::MediaPlayer()
51 {
52 ALOGV("constructor");
53 mListener = NULL;
54 mCookie = NULL;
55 mStreamType = AUDIO_STREAM_MUSIC;
56 mAudioAttributesParcel = NULL;
57 mCurrentPosition = -1;
58 mSeekPosition = -1;
59 mCurrentState = MEDIA_PLAYER_IDLE;
60 mPrepareSync = false;
61 mPrepareStatus = NO_ERROR;
62 mLoop = false;
63 mLeftVolume = mRightVolume = 1.0;
64 mVideoWidth = mVideoHeight = 0;
65 mLockThreadId = 0;
66 mAudioSessionId = AudioSystem::newAudioUniqueId();
67 AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
68 mSendLevel = 0;
69 mRetransmitEndpointValid = false;
70 }
71
~MediaPlayer()72 MediaPlayer::~MediaPlayer()
73 {
74 ALOGV("destructor");
75 if (mAudioAttributesParcel != NULL) {
76 delete mAudioAttributesParcel;
77 mAudioAttributesParcel = NULL;
78 }
79 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
80 disconnect();
81 IPCThreadState::self()->flushCommands();
82 }
83
disconnect()84 void MediaPlayer::disconnect()
85 {
86 ALOGV("disconnect");
87 sp<IMediaPlayer> p;
88 {
89 Mutex::Autolock _l(mLock);
90 p = mPlayer;
91 mPlayer.clear();
92 }
93
94 if (p != 0) {
95 p->disconnect();
96 }
97 }
98
99 // always call with lock held
clear_l()100 void MediaPlayer::clear_l()
101 {
102 mCurrentPosition = -1;
103 mSeekPosition = -1;
104 mVideoWidth = mVideoHeight = 0;
105 mRetransmitEndpointValid = false;
106 }
107
setListener(const sp<MediaPlayerListener> & listener)108 status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
109 {
110 ALOGV("setListener");
111 Mutex::Autolock _l(mLock);
112 mListener = listener;
113 return NO_ERROR;
114 }
115
116
attachNewPlayer(const sp<IMediaPlayer> & player)117 status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
118 {
119 status_t err = UNKNOWN_ERROR;
120 sp<IMediaPlayer> p;
121 { // scope for the lock
122 Mutex::Autolock _l(mLock);
123
124 if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
125 (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
126 ALOGE("attachNewPlayer called in state %d", mCurrentState);
127 return INVALID_OPERATION;
128 }
129
130 clear_l();
131 p = mPlayer;
132 mPlayer = player;
133 if (player != 0) {
134 mCurrentState = MEDIA_PLAYER_INITIALIZED;
135 err = NO_ERROR;
136 } else {
137 ALOGE("Unable to create media player");
138 }
139 }
140
141 if (p != 0) {
142 p->disconnect();
143 }
144
145 return err;
146 }
147
setDataSource(const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)148 status_t MediaPlayer::setDataSource(
149 const sp<IMediaHTTPService> &httpService,
150 const char *url, const KeyedVector<String8, String8> *headers)
151 {
152 ALOGV("setDataSource(%s)", url);
153 status_t err = BAD_VALUE;
154 if (url != NULL) {
155 const sp<IMediaPlayerService> service(getMediaPlayerService());
156 if (service != 0) {
157 sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
158 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
159 (NO_ERROR != player->setDataSource(httpService, url, headers))) {
160 player.clear();
161 }
162 err = attachNewPlayer(player);
163 }
164 }
165 return err;
166 }
167
setDataSource(int fd,int64_t offset,int64_t length)168 status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
169 {
170 ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
171 status_t err = UNKNOWN_ERROR;
172 const sp<IMediaPlayerService> service(getMediaPlayerService());
173 if (service != 0) {
174 sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
175 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
176 (NO_ERROR != player->setDataSource(fd, offset, length))) {
177 player.clear();
178 }
179 err = attachNewPlayer(player);
180 }
181 return err;
182 }
183
setDataSource(const sp<IStreamSource> & source)184 status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
185 {
186 ALOGV("setDataSource");
187 status_t err = UNKNOWN_ERROR;
188 const sp<IMediaPlayerService> service(getMediaPlayerService());
189 if (service != 0) {
190 sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
191 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
192 (NO_ERROR != player->setDataSource(source))) {
193 player.clear();
194 }
195 err = attachNewPlayer(player);
196 }
197 return err;
198 }
199
setDataSource(const sp<IDataSource> & source)200 status_t MediaPlayer::setDataSource(const sp<IDataSource> &source)
201 {
202 ALOGV("setDataSource(IDataSource)");
203 status_t err = UNKNOWN_ERROR;
204 const sp<IMediaPlayerService>& service(getMediaPlayerService());
205 if (service != 0) {
206 sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
207 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
208 (NO_ERROR != player->setDataSource(source))) {
209 player.clear();
210 }
211 err = attachNewPlayer(player);
212 }
213 return err;
214 }
215
invoke(const Parcel & request,Parcel * reply)216 status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
217 {
218 Mutex::Autolock _l(mLock);
219 const bool hasBeenInitialized =
220 (mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
221 ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
222 if ((mPlayer != NULL) && hasBeenInitialized) {
223 ALOGV("invoke %zu", request.dataSize());
224 return mPlayer->invoke(request, reply);
225 }
226 ALOGE("invoke failed: wrong state %X", mCurrentState);
227 return INVALID_OPERATION;
228 }
229
setMetadataFilter(const Parcel & filter)230 status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
231 {
232 ALOGD("setMetadataFilter");
233 Mutex::Autolock lock(mLock);
234 if (mPlayer == NULL) {
235 return NO_INIT;
236 }
237 return mPlayer->setMetadataFilter(filter);
238 }
239
getMetadata(bool update_only,bool apply_filter,Parcel * metadata)240 status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
241 {
242 ALOGD("getMetadata");
243 Mutex::Autolock lock(mLock);
244 if (mPlayer == NULL) {
245 return NO_INIT;
246 }
247 return mPlayer->getMetadata(update_only, apply_filter, metadata);
248 }
249
setVideoSurfaceTexture(const sp<IGraphicBufferProducer> & bufferProducer)250 status_t MediaPlayer::setVideoSurfaceTexture(
251 const sp<IGraphicBufferProducer>& bufferProducer)
252 {
253 ALOGV("setVideoSurfaceTexture");
254 Mutex::Autolock _l(mLock);
255 if (mPlayer == 0) return NO_INIT;
256 return mPlayer->setVideoSurfaceTexture(bufferProducer);
257 }
258
259 // must call with lock held
prepareAsync_l()260 status_t MediaPlayer::prepareAsync_l()
261 {
262 if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
263 if (mAudioAttributesParcel != NULL) {
264 mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
265 } else {
266 mPlayer->setAudioStreamType(mStreamType);
267 }
268 mCurrentState = MEDIA_PLAYER_PREPARING;
269 return mPlayer->prepareAsync();
270 }
271 ALOGE("prepareAsync called in state %d", mCurrentState);
272 return INVALID_OPERATION;
273 }
274
275 // TODO: In case of error, prepareAsync provides the caller with 2 error codes,
276 // one defined in the Android framework and one provided by the implementation
277 // that generated the error. The sync version of prepare returns only 1 error
278 // code.
prepare()279 status_t MediaPlayer::prepare()
280 {
281 ALOGV("prepare");
282 Mutex::Autolock _l(mLock);
283 mLockThreadId = getThreadId();
284 if (mPrepareSync) {
285 mLockThreadId = 0;
286 return -EALREADY;
287 }
288 mPrepareSync = true;
289 status_t ret = prepareAsync_l();
290 if (ret != NO_ERROR) {
291 mLockThreadId = 0;
292 return ret;
293 }
294
295 if (mPrepareSync) {
296 mSignal.wait(mLock); // wait for prepare done
297 mPrepareSync = false;
298 }
299 ALOGV("prepare complete - status=%d", mPrepareStatus);
300 mLockThreadId = 0;
301 return mPrepareStatus;
302 }
303
prepareAsync()304 status_t MediaPlayer::prepareAsync()
305 {
306 ALOGV("prepareAsync");
307 Mutex::Autolock _l(mLock);
308 return prepareAsync_l();
309 }
310
start()311 status_t MediaPlayer::start()
312 {
313 ALOGV("start");
314
315 status_t ret = NO_ERROR;
316 Mutex::Autolock _l(mLock);
317
318 mLockThreadId = getThreadId();
319
320 if (mCurrentState & MEDIA_PLAYER_STARTED) {
321 ret = NO_ERROR;
322 } else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
323 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
324 mPlayer->setLooping(mLoop);
325 mPlayer->setVolume(mLeftVolume, mRightVolume);
326 mPlayer->setAuxEffectSendLevel(mSendLevel);
327 mCurrentState = MEDIA_PLAYER_STARTED;
328 ret = mPlayer->start();
329 if (ret != NO_ERROR) {
330 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
331 } else {
332 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
333 ALOGV("playback completed immediately following start()");
334 }
335 }
336 } else {
337 ALOGE("start called in state %d", mCurrentState);
338 ret = INVALID_OPERATION;
339 }
340
341 mLockThreadId = 0;
342
343 return ret;
344 }
345
stop()346 status_t MediaPlayer::stop()
347 {
348 ALOGV("stop");
349 Mutex::Autolock _l(mLock);
350 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
351 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
352 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
353 status_t ret = mPlayer->stop();
354 if (ret != NO_ERROR) {
355 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
356 } else {
357 mCurrentState = MEDIA_PLAYER_STOPPED;
358 }
359 return ret;
360 }
361 ALOGE("stop called in state %d", mCurrentState);
362 return INVALID_OPERATION;
363 }
364
pause()365 status_t MediaPlayer::pause()
366 {
367 ALOGV("pause");
368 Mutex::Autolock _l(mLock);
369 if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))
370 return NO_ERROR;
371 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
372 status_t ret = mPlayer->pause();
373 if (ret != NO_ERROR) {
374 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
375 } else {
376 mCurrentState = MEDIA_PLAYER_PAUSED;
377 }
378 return ret;
379 }
380 ALOGE("pause called in state %d", mCurrentState);
381 return INVALID_OPERATION;
382 }
383
isPlaying()384 bool MediaPlayer::isPlaying()
385 {
386 Mutex::Autolock _l(mLock);
387 if (mPlayer != 0) {
388 bool temp = false;
389 mPlayer->isPlaying(&temp);
390 ALOGV("isPlaying: %d", temp);
391 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
392 ALOGE("internal/external state mismatch corrected");
393 mCurrentState = MEDIA_PLAYER_PAUSED;
394 } else if ((mCurrentState & MEDIA_PLAYER_PAUSED) && temp) {
395 ALOGE("internal/external state mismatch corrected");
396 mCurrentState = MEDIA_PLAYER_STARTED;
397 }
398 return temp;
399 }
400 ALOGV("isPlaying: no active player");
401 return false;
402 }
403
setPlaybackSettings(const AudioPlaybackRate & rate)404 status_t MediaPlayer::setPlaybackSettings(const AudioPlaybackRate& rate)
405 {
406 ALOGV("setPlaybackSettings: %f %f %d %d",
407 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
408 // Negative speed and pitch does not make sense. Further validation will
409 // be done by the respective mediaplayers.
410 if (rate.mSpeed < 0.f || rate.mPitch < 0.f) {
411 return BAD_VALUE;
412 }
413 Mutex::Autolock _l(mLock);
414 if (mPlayer == 0) return INVALID_OPERATION;
415 status_t err = mPlayer->setPlaybackSettings(rate);
416 if (err == OK) {
417 if (rate.mSpeed == 0.f && mCurrentState == MEDIA_PLAYER_STARTED) {
418 mCurrentState = MEDIA_PLAYER_PAUSED;
419 } else if (rate.mSpeed != 0.f && mCurrentState == MEDIA_PLAYER_PAUSED) {
420 mCurrentState = MEDIA_PLAYER_STARTED;
421 }
422 }
423 return err;
424 }
425
getPlaybackSettings(AudioPlaybackRate * rate)426 status_t MediaPlayer::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */)
427 {
428 Mutex::Autolock _l(mLock);
429 if (mPlayer == 0) return INVALID_OPERATION;
430 return mPlayer->getPlaybackSettings(rate);
431 }
432
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)433 status_t MediaPlayer::setSyncSettings(const AVSyncSettings& sync, float videoFpsHint)
434 {
435 ALOGV("setSyncSettings: %u %u %f %f",
436 sync.mSource, sync.mAudioAdjustMode, sync.mTolerance, videoFpsHint);
437 Mutex::Autolock _l(mLock);
438 if (mPlayer == 0) return INVALID_OPERATION;
439 return mPlayer->setSyncSettings(sync, videoFpsHint);
440 }
441
getSyncSettings(AVSyncSettings * sync,float * videoFps)442 status_t MediaPlayer::getSyncSettings(
443 AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */)
444 {
445 Mutex::Autolock _l(mLock);
446 if (mPlayer == 0) return INVALID_OPERATION;
447 return mPlayer->getSyncSettings(sync, videoFps);
448 }
449
getVideoWidth(int * w)450 status_t MediaPlayer::getVideoWidth(int *w)
451 {
452 ALOGV("getVideoWidth");
453 Mutex::Autolock _l(mLock);
454 if (mPlayer == 0) return INVALID_OPERATION;
455 *w = mVideoWidth;
456 return NO_ERROR;
457 }
458
getVideoHeight(int * h)459 status_t MediaPlayer::getVideoHeight(int *h)
460 {
461 ALOGV("getVideoHeight");
462 Mutex::Autolock _l(mLock);
463 if (mPlayer == 0) return INVALID_OPERATION;
464 *h = mVideoHeight;
465 return NO_ERROR;
466 }
467
getCurrentPosition(int * msec)468 status_t MediaPlayer::getCurrentPosition(int *msec)
469 {
470 ALOGV("getCurrentPosition");
471 Mutex::Autolock _l(mLock);
472 if (mPlayer != 0) {
473 if (mCurrentPosition >= 0) {
474 ALOGV("Using cached seek position: %d", mCurrentPosition);
475 *msec = mCurrentPosition;
476 return NO_ERROR;
477 }
478 return mPlayer->getCurrentPosition(msec);
479 }
480 return INVALID_OPERATION;
481 }
482
getDuration_l(int * msec)483 status_t MediaPlayer::getDuration_l(int *msec)
484 {
485 ALOGV("getDuration_l");
486 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
487 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
488 if (mPlayer != 0 && isValidState) {
489 int durationMs;
490 status_t ret = mPlayer->getDuration(&durationMs);
491
492 if (ret != OK) {
493 // Do not enter error state just because no duration was available.
494 durationMs = -1;
495 ret = OK;
496 }
497
498 if (msec) {
499 *msec = durationMs;
500 }
501 return ret;
502 }
503 ALOGE("Attempt to call getDuration without a valid mediaplayer");
504 return INVALID_OPERATION;
505 }
506
getDuration(int * msec)507 status_t MediaPlayer::getDuration(int *msec)
508 {
509 Mutex::Autolock _l(mLock);
510 return getDuration_l(msec);
511 }
512
seekTo_l(int msec)513 status_t MediaPlayer::seekTo_l(int msec)
514 {
515 ALOGV("seekTo %d", msec);
516 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
517 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
518 if ( msec < 0 ) {
519 ALOGW("Attempt to seek to invalid position: %d", msec);
520 msec = 0;
521 }
522
523 int durationMs;
524 status_t err = mPlayer->getDuration(&durationMs);
525
526 if (err != OK) {
527 ALOGW("Stream has no duration and is therefore not seekable.");
528 return err;
529 }
530
531 if (msec > durationMs) {
532 ALOGW("Attempt to seek to past end of file: request = %d, "
533 "durationMs = %d",
534 msec,
535 durationMs);
536
537 msec = durationMs;
538 }
539
540 // cache duration
541 mCurrentPosition = msec;
542 if (mSeekPosition < 0) {
543 mSeekPosition = msec;
544 return mPlayer->seekTo(msec);
545 }
546 else {
547 ALOGV("Seek in progress - queue up seekTo[%d]", msec);
548 return NO_ERROR;
549 }
550 }
551 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(),
552 mCurrentState);
553 return INVALID_OPERATION;
554 }
555
seekTo(int msec)556 status_t MediaPlayer::seekTo(int msec)
557 {
558 mLockThreadId = getThreadId();
559 Mutex::Autolock _l(mLock);
560 status_t result = seekTo_l(msec);
561 mLockThreadId = 0;
562
563 return result;
564 }
565
reset_l()566 status_t MediaPlayer::reset_l()
567 {
568 mLoop = false;
569 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
570 mPrepareSync = false;
571 if (mPlayer != 0) {
572 status_t ret = mPlayer->reset();
573 if (ret != NO_ERROR) {
574 ALOGE("reset() failed with return code (%d)", ret);
575 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
576 } else {
577 mPlayer->disconnect();
578 mCurrentState = MEDIA_PLAYER_IDLE;
579 }
580 // setDataSource has to be called again to create a
581 // new mediaplayer.
582 mPlayer = 0;
583 return ret;
584 }
585 clear_l();
586 return NO_ERROR;
587 }
588
doSetRetransmitEndpoint(const sp<IMediaPlayer> & player)589 status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) {
590 Mutex::Autolock _l(mLock);
591
592 if (player == NULL) {
593 return UNKNOWN_ERROR;
594 }
595
596 if (mRetransmitEndpointValid) {
597 return player->setRetransmitEndpoint(&mRetransmitEndpoint);
598 }
599
600 return OK;
601 }
602
reset()603 status_t MediaPlayer::reset()
604 {
605 ALOGV("reset");
606 Mutex::Autolock _l(mLock);
607 return reset_l();
608 }
609
setAudioStreamType(audio_stream_type_t type)610 status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type)
611 {
612 ALOGV("MediaPlayer::setAudioStreamType");
613 Mutex::Autolock _l(mLock);
614 if (mStreamType == type) return NO_ERROR;
615 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
616 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
617 // Can't change the stream type after prepare
618 ALOGE("setAudioStream called in state %d", mCurrentState);
619 return INVALID_OPERATION;
620 }
621 // cache
622 mStreamType = type;
623 return OK;
624 }
625
getAudioStreamType(audio_stream_type_t * type)626 status_t MediaPlayer::getAudioStreamType(audio_stream_type_t *type)
627 {
628 ALOGV("getAudioStreamType");
629 Mutex::Autolock _l(mLock);
630 *type = mStreamType;
631 return OK;
632 }
633
setLooping(int loop)634 status_t MediaPlayer::setLooping(int loop)
635 {
636 ALOGV("MediaPlayer::setLooping");
637 Mutex::Autolock _l(mLock);
638 mLoop = (loop != 0);
639 if (mPlayer != 0) {
640 return mPlayer->setLooping(loop);
641 }
642 return OK;
643 }
644
isLooping()645 bool MediaPlayer::isLooping() {
646 ALOGV("isLooping");
647 Mutex::Autolock _l(mLock);
648 if (mPlayer != 0) {
649 return mLoop;
650 }
651 ALOGV("isLooping: no active player");
652 return false;
653 }
654
setVolume(float leftVolume,float rightVolume)655 status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
656 {
657 ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
658 Mutex::Autolock _l(mLock);
659 mLeftVolume = leftVolume;
660 mRightVolume = rightVolume;
661 if (mPlayer != 0) {
662 return mPlayer->setVolume(leftVolume, rightVolume);
663 }
664 return OK;
665 }
666
setAudioSessionId(int sessionId)667 status_t MediaPlayer::setAudioSessionId(int sessionId)
668 {
669 ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
670 Mutex::Autolock _l(mLock);
671 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
672 ALOGE("setAudioSessionId called in state %d", mCurrentState);
673 return INVALID_OPERATION;
674 }
675 if (sessionId < 0) {
676 return BAD_VALUE;
677 }
678 if (sessionId != mAudioSessionId) {
679 AudioSystem::acquireAudioSessionId(sessionId, -1);
680 AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
681 mAudioSessionId = sessionId;
682 }
683 return NO_ERROR;
684 }
685
getAudioSessionId()686 int MediaPlayer::getAudioSessionId()
687 {
688 Mutex::Autolock _l(mLock);
689 return mAudioSessionId;
690 }
691
setAuxEffectSendLevel(float level)692 status_t MediaPlayer::setAuxEffectSendLevel(float level)
693 {
694 ALOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
695 Mutex::Autolock _l(mLock);
696 mSendLevel = level;
697 if (mPlayer != 0) {
698 return mPlayer->setAuxEffectSendLevel(level);
699 }
700 return OK;
701 }
702
attachAuxEffect(int effectId)703 status_t MediaPlayer::attachAuxEffect(int effectId)
704 {
705 ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
706 Mutex::Autolock _l(mLock);
707 if (mPlayer == 0 ||
708 (mCurrentState & MEDIA_PLAYER_IDLE) ||
709 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
710 ALOGE("attachAuxEffect called in state %d", mCurrentState);
711 return INVALID_OPERATION;
712 }
713
714 return mPlayer->attachAuxEffect(effectId);
715 }
716
717 // always call with lock held
checkStateForKeySet_l(int key)718 status_t MediaPlayer::checkStateForKeySet_l(int key)
719 {
720 switch(key) {
721 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
722 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
723 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) {
724 // Can't change the audio attributes after prepare
725 ALOGE("trying to set audio attributes called in state %d", mCurrentState);
726 return INVALID_OPERATION;
727 }
728 break;
729 default:
730 // parameter doesn't require player state check
731 break;
732 }
733 return OK;
734 }
735
setParameter(int key,const Parcel & request)736 status_t MediaPlayer::setParameter(int key, const Parcel& request)
737 {
738 ALOGV("MediaPlayer::setParameter(%d)", key);
739 status_t status = INVALID_OPERATION;
740 Mutex::Autolock _l(mLock);
741 if (checkStateForKeySet_l(key) != OK) {
742 return status;
743 }
744 switch (key) {
745 case KEY_PARAMETER_AUDIO_ATTRIBUTES:
746 // save the marshalled audio attributes
747 if (mAudioAttributesParcel != NULL) { delete mAudioAttributesParcel; };
748 mAudioAttributesParcel = new Parcel();
749 mAudioAttributesParcel->appendFrom(&request, 0, request.dataSize());
750 status = OK;
751 break;
752 default:
753 ALOGV_IF(mPlayer == NULL, "setParameter: no active player");
754 break;
755 }
756
757 if (mPlayer != NULL) {
758 status = mPlayer->setParameter(key, request);
759 }
760 return status;
761 }
762
getParameter(int key,Parcel * reply)763 status_t MediaPlayer::getParameter(int key, Parcel *reply)
764 {
765 ALOGV("MediaPlayer::getParameter(%d)", key);
766 Mutex::Autolock _l(mLock);
767 if (mPlayer != NULL) {
768 return mPlayer->getParameter(key, reply);
769 }
770 ALOGV("getParameter: no active player");
771 return INVALID_OPERATION;
772 }
773
setRetransmitEndpoint(const char * addrString,uint16_t port)774 status_t MediaPlayer::setRetransmitEndpoint(const char* addrString,
775 uint16_t port) {
776 ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)",
777 addrString ? addrString : "(null)", port);
778
779 Mutex::Autolock _l(mLock);
780 if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE))
781 return INVALID_OPERATION;
782
783 if (NULL == addrString) {
784 mRetransmitEndpointValid = false;
785 return OK;
786 }
787
788 struct in_addr saddr;
789 if(!inet_aton(addrString, &saddr)) {
790 return BAD_VALUE;
791 }
792
793 memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint));
794 mRetransmitEndpoint.sin_family = AF_INET;
795 mRetransmitEndpoint.sin_addr = saddr;
796 mRetransmitEndpoint.sin_port = htons(port);
797 mRetransmitEndpointValid = true;
798
799 return OK;
800 }
801
notify(int msg,int ext1,int ext2,const Parcel * obj)802 void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
803 {
804 ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
805 bool send = true;
806 bool locked = false;
807
808 // TODO: In the future, we might be on the same thread if the app is
809 // running in the same process as the media server. In that case,
810 // this will deadlock.
811 //
812 // The threadId hack below works around this for the care of prepare,
813 // seekTo and start within the same process.
814 // FIXME: Remember, this is a hack, it's not even a hack that is applied
815 // consistently for all use-cases, this needs to be revisited.
816 if (mLockThreadId != getThreadId()) {
817 mLock.lock();
818 locked = true;
819 }
820
821 // Allows calls from JNI in idle state to notify errors
822 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
823 ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
824 if (locked) mLock.unlock(); // release the lock when done.
825 return;
826 }
827
828 switch (msg) {
829 case MEDIA_NOP: // interface test message
830 break;
831 case MEDIA_PREPARED:
832 ALOGV("prepared");
833 mCurrentState = MEDIA_PLAYER_PREPARED;
834 if (mPrepareSync) {
835 ALOGV("signal application thread");
836 mPrepareSync = false;
837 mPrepareStatus = NO_ERROR;
838 mSignal.signal();
839 }
840 break;
841 case MEDIA_PLAYBACK_COMPLETE:
842 ALOGV("playback complete");
843 if (mCurrentState == MEDIA_PLAYER_IDLE) {
844 ALOGE("playback complete in idle state");
845 }
846 if (!mLoop) {
847 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
848 }
849 break;
850 case MEDIA_ERROR:
851 // Always log errors.
852 // ext1: Media framework error code.
853 // ext2: Implementation dependant error code.
854 ALOGE("error (%d, %d)", ext1, ext2);
855 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
856 if (mPrepareSync)
857 {
858 ALOGV("signal application thread");
859 mPrepareSync = false;
860 mPrepareStatus = ext1;
861 mSignal.signal();
862 send = false;
863 }
864 break;
865 case MEDIA_INFO:
866 // ext1: Media framework error code.
867 // ext2: Implementation dependant error code.
868 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
869 ALOGW("info/warning (%d, %d)", ext1, ext2);
870 }
871 break;
872 case MEDIA_SEEK_COMPLETE:
873 ALOGV("Received seek complete");
874 if (mSeekPosition != mCurrentPosition) {
875 ALOGV("Executing queued seekTo(%d)", mSeekPosition);
876 mSeekPosition = -1;
877 seekTo_l(mCurrentPosition);
878 }
879 else {
880 ALOGV("All seeks complete - return to regularly scheduled program");
881 mCurrentPosition = mSeekPosition = -1;
882 }
883 break;
884 case MEDIA_BUFFERING_UPDATE:
885 ALOGV("buffering %d", ext1);
886 break;
887 case MEDIA_SET_VIDEO_SIZE:
888 ALOGV("New video size %d x %d", ext1, ext2);
889 mVideoWidth = ext1;
890 mVideoHeight = ext2;
891 break;
892 case MEDIA_TIMED_TEXT:
893 ALOGV("Received timed text message");
894 break;
895 case MEDIA_SUBTITLE_DATA:
896 ALOGV("Received subtitle data message");
897 break;
898 case MEDIA_META_DATA:
899 ALOGV("Received timed metadata message");
900 break;
901 default:
902 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
903 break;
904 }
905
906 sp<MediaPlayerListener> listener = mListener;
907 if (locked) mLock.unlock();
908
909 // this prevents re-entrant calls into client code
910 if ((listener != 0) && send) {
911 Mutex::Autolock _l(mNotifyLock);
912 ALOGV("callback application");
913 listener->notify(msg, ext1, ext2, obj);
914 ALOGV("back from callback");
915 }
916 }
917
died()918 void MediaPlayer::died()
919 {
920 ALOGV("died");
921 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
922 }
923
setNextMediaPlayer(const sp<MediaPlayer> & next)924 status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
925 if (mPlayer == NULL) {
926 return NO_INIT;
927 }
928
929 if (next != NULL && !(next->mCurrentState &
930 (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE))) {
931 ALOGE("next player is not prepared");
932 return INVALID_OPERATION;
933 }
934
935 return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
936 }
937
938 } // namespace android
939