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