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