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/SurfaceTextureClient.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 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(getpid(), 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(getpid(), 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(getpid(), 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<ISurfaceTexture> & surfaceTexture)223 status_t MediaPlayer::setVideoSurfaceTexture(
224 const sp<ISurfaceTexture>& surfaceTexture)
225 {
226 ALOGV("setVideoSurfaceTexture");
227 Mutex::Autolock _l(mLock);
228 if (mPlayer == 0) return NO_INIT;
229 return mPlayer->setVideoSurfaceTexture(surfaceTexture);
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 if (msec) {
402 *msec = durationMs;
403 }
404 return ret;
405 }
406 ALOGE("Attempt to call getDuration without a valid mediaplayer");
407 return INVALID_OPERATION;
408 }
409
getDuration(int * msec)410 status_t MediaPlayer::getDuration(int *msec)
411 {
412 Mutex::Autolock _l(mLock);
413 return getDuration_l(msec);
414 }
415
seekTo_l(int msec)416 status_t MediaPlayer::seekTo_l(int msec)
417 {
418 ALOGV("seekTo %d", msec);
419 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
420 if ( msec < 0 ) {
421 ALOGW("Attempt to seek to invalid position: %d", msec);
422 msec = 0;
423 }
424
425 int durationMs;
426 status_t err = mPlayer->getDuration(&durationMs);
427
428 if (err != OK) {
429 ALOGW("Stream has no duration and is therefore not seekable.");
430 return err;
431 }
432
433 if (msec > durationMs) {
434 ALOGW("Attempt to seek to past end of file: request = %d, "
435 "durationMs = %d",
436 msec,
437 durationMs);
438
439 msec = durationMs;
440 }
441
442 // cache duration
443 mCurrentPosition = msec;
444 if (mSeekPosition < 0) {
445 mSeekPosition = msec;
446 return mPlayer->seekTo(msec);
447 }
448 else {
449 ALOGV("Seek in progress - queue up seekTo[%d]", msec);
450 return NO_ERROR;
451 }
452 }
453 ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
454 return INVALID_OPERATION;
455 }
456
seekTo(int msec)457 status_t MediaPlayer::seekTo(int msec)
458 {
459 mLockThreadId = getThreadId();
460 Mutex::Autolock _l(mLock);
461 status_t result = seekTo_l(msec);
462 mLockThreadId = 0;
463
464 return result;
465 }
466
reset_l()467 status_t MediaPlayer::reset_l()
468 {
469 mLoop = false;
470 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
471 mPrepareSync = false;
472 if (mPlayer != 0) {
473 status_t ret = mPlayer->reset();
474 if (ret != NO_ERROR) {
475 ALOGE("reset() failed with return code (%d)", ret);
476 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
477 } else {
478 mCurrentState = MEDIA_PLAYER_IDLE;
479 }
480 // setDataSource has to be called again to create a
481 // new mediaplayer.
482 mPlayer = 0;
483 return ret;
484 }
485 clear_l();
486 return NO_ERROR;
487 }
488
doSetRetransmitEndpoint(const sp<IMediaPlayer> & player)489 status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) {
490 Mutex::Autolock _l(mLock);
491
492 if (player == NULL) {
493 return UNKNOWN_ERROR;
494 }
495
496 if (mRetransmitEndpointValid) {
497 return player->setRetransmitEndpoint(&mRetransmitEndpoint);
498 }
499
500 return OK;
501 }
502
reset()503 status_t MediaPlayer::reset()
504 {
505 ALOGV("reset");
506 Mutex::Autolock _l(mLock);
507 return reset_l();
508 }
509
setAudioStreamType(audio_stream_type_t type)510 status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type)
511 {
512 ALOGV("MediaPlayer::setAudioStreamType");
513 Mutex::Autolock _l(mLock);
514 if (mStreamType == type) return NO_ERROR;
515 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
516 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
517 // Can't change the stream type after prepare
518 ALOGE("setAudioStream called in state %d", mCurrentState);
519 return INVALID_OPERATION;
520 }
521 // cache
522 mStreamType = type;
523 return OK;
524 }
525
setLooping(int loop)526 status_t MediaPlayer::setLooping(int loop)
527 {
528 ALOGV("MediaPlayer::setLooping");
529 Mutex::Autolock _l(mLock);
530 mLoop = (loop != 0);
531 if (mPlayer != 0) {
532 return mPlayer->setLooping(loop);
533 }
534 return OK;
535 }
536
isLooping()537 bool MediaPlayer::isLooping() {
538 ALOGV("isLooping");
539 Mutex::Autolock _l(mLock);
540 if (mPlayer != 0) {
541 return mLoop;
542 }
543 ALOGV("isLooping: no active player");
544 return false;
545 }
546
setVolume(float leftVolume,float rightVolume)547 status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
548 {
549 ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
550 Mutex::Autolock _l(mLock);
551 mLeftVolume = leftVolume;
552 mRightVolume = rightVolume;
553 if (mPlayer != 0) {
554 return mPlayer->setVolume(leftVolume, rightVolume);
555 }
556 return OK;
557 }
558
setAudioSessionId(int sessionId)559 status_t MediaPlayer::setAudioSessionId(int sessionId)
560 {
561 ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
562 Mutex::Autolock _l(mLock);
563 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
564 ALOGE("setAudioSessionId called in state %d", mCurrentState);
565 return INVALID_OPERATION;
566 }
567 if (sessionId < 0) {
568 return BAD_VALUE;
569 }
570 if (sessionId != mAudioSessionId) {
571 AudioSystem::releaseAudioSessionId(mAudioSessionId);
572 AudioSystem::acquireAudioSessionId(sessionId);
573 mAudioSessionId = sessionId;
574 }
575 return NO_ERROR;
576 }
577
getAudioSessionId()578 int MediaPlayer::getAudioSessionId()
579 {
580 Mutex::Autolock _l(mLock);
581 return mAudioSessionId;
582 }
583
setAuxEffectSendLevel(float level)584 status_t MediaPlayer::setAuxEffectSendLevel(float level)
585 {
586 ALOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
587 Mutex::Autolock _l(mLock);
588 mSendLevel = level;
589 if (mPlayer != 0) {
590 return mPlayer->setAuxEffectSendLevel(level);
591 }
592 return OK;
593 }
594
attachAuxEffect(int effectId)595 status_t MediaPlayer::attachAuxEffect(int effectId)
596 {
597 ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
598 Mutex::Autolock _l(mLock);
599 if (mPlayer == 0 ||
600 (mCurrentState & MEDIA_PLAYER_IDLE) ||
601 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
602 ALOGE("attachAuxEffect called in state %d", mCurrentState);
603 return INVALID_OPERATION;
604 }
605
606 return mPlayer->attachAuxEffect(effectId);
607 }
608
setParameter(int key,const Parcel & request)609 status_t MediaPlayer::setParameter(int key, const Parcel& request)
610 {
611 ALOGV("MediaPlayer::setParameter(%d)", key);
612 Mutex::Autolock _l(mLock);
613 if (mPlayer != NULL) {
614 return mPlayer->setParameter(key, request);
615 }
616 ALOGV("setParameter: no active player");
617 return INVALID_OPERATION;
618 }
619
getParameter(int key,Parcel * reply)620 status_t MediaPlayer::getParameter(int key, Parcel *reply)
621 {
622 ALOGV("MediaPlayer::getParameter(%d)", key);
623 Mutex::Autolock _l(mLock);
624 if (mPlayer != NULL) {
625 return mPlayer->getParameter(key, reply);
626 }
627 ALOGV("getParameter: no active player");
628 return INVALID_OPERATION;
629 }
630
setRetransmitEndpoint(const char * addrString,uint16_t port)631 status_t MediaPlayer::setRetransmitEndpoint(const char* addrString,
632 uint16_t port) {
633 ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)",
634 addrString ? addrString : "(null)", port);
635
636 Mutex::Autolock _l(mLock);
637 if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE))
638 return INVALID_OPERATION;
639
640 if (NULL == addrString) {
641 mRetransmitEndpointValid = false;
642 return OK;
643 }
644
645 struct in_addr saddr;
646 if(!inet_aton(addrString, &saddr)) {
647 return BAD_VALUE;
648 }
649
650 memset(&mRetransmitEndpoint, 0, sizeof(&mRetransmitEndpoint));
651 mRetransmitEndpoint.sin_family = AF_INET;
652 mRetransmitEndpoint.sin_addr = saddr;
653 mRetransmitEndpoint.sin_port = htons(port);
654 mRetransmitEndpointValid = true;
655
656 return OK;
657 }
658
notify(int msg,int ext1,int ext2,const Parcel * obj)659 void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
660 {
661 ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
662 bool send = true;
663 bool locked = false;
664
665 // TODO: In the future, we might be on the same thread if the app is
666 // running in the same process as the media server. In that case,
667 // this will deadlock.
668 //
669 // The threadId hack below works around this for the care of prepare
670 // and seekTo within the same process.
671 // FIXME: Remember, this is a hack, it's not even a hack that is applied
672 // consistently for all use-cases, this needs to be revisited.
673 if (mLockThreadId != getThreadId()) {
674 mLock.lock();
675 locked = true;
676 }
677
678 // Allows calls from JNI in idle state to notify errors
679 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
680 ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
681 if (locked) mLock.unlock(); // release the lock when done.
682 return;
683 }
684
685 switch (msg) {
686 case MEDIA_NOP: // interface test message
687 break;
688 case MEDIA_PREPARED:
689 ALOGV("prepared");
690 mCurrentState = MEDIA_PLAYER_PREPARED;
691 if (mPrepareSync) {
692 ALOGV("signal application thread");
693 mPrepareSync = false;
694 mPrepareStatus = NO_ERROR;
695 mSignal.signal();
696 }
697 break;
698 case MEDIA_PLAYBACK_COMPLETE:
699 ALOGV("playback complete");
700 if (mCurrentState == MEDIA_PLAYER_IDLE) {
701 ALOGE("playback complete in idle state");
702 }
703 if (!mLoop) {
704 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
705 }
706 break;
707 case MEDIA_ERROR:
708 // Always log errors.
709 // ext1: Media framework error code.
710 // ext2: Implementation dependant error code.
711 ALOGE("error (%d, %d)", ext1, ext2);
712 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
713 if (mPrepareSync)
714 {
715 ALOGV("signal application thread");
716 mPrepareSync = false;
717 mPrepareStatus = ext1;
718 mSignal.signal();
719 send = false;
720 }
721 break;
722 case MEDIA_INFO:
723 // ext1: Media framework error code.
724 // ext2: Implementation dependant error code.
725 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
726 ALOGW("info/warning (%d, %d)", ext1, ext2);
727 }
728 break;
729 case MEDIA_SEEK_COMPLETE:
730 ALOGV("Received seek complete");
731 if (mSeekPosition != mCurrentPosition) {
732 ALOGV("Executing queued seekTo(%d)", mSeekPosition);
733 mSeekPosition = -1;
734 seekTo_l(mCurrentPosition);
735 }
736 else {
737 ALOGV("All seeks complete - return to regularly scheduled program");
738 mCurrentPosition = mSeekPosition = -1;
739 }
740 break;
741 case MEDIA_BUFFERING_UPDATE:
742 ALOGV("buffering %d", ext1);
743 break;
744 case MEDIA_SET_VIDEO_SIZE:
745 ALOGV("New video size %d x %d", ext1, ext2);
746 mVideoWidth = ext1;
747 mVideoHeight = ext2;
748 break;
749 case MEDIA_TIMED_TEXT:
750 ALOGV("Received timed text message");
751 break;
752 default:
753 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
754 break;
755 }
756
757 sp<MediaPlayerListener> listener = mListener;
758 if (locked) mLock.unlock();
759
760 // this prevents re-entrant calls into client code
761 if ((listener != 0) && send) {
762 Mutex::Autolock _l(mNotifyLock);
763 ALOGV("callback application");
764 listener->notify(msg, ext1, ext2, obj);
765 ALOGV("back from callback");
766 }
767 }
768
decode(const char * url,uint32_t * pSampleRate,int * pNumChannels,audio_format_t * pFormat)769 /*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
770 {
771 ALOGV("decode(%s)", url);
772 sp<IMemory> p;
773 const sp<IMediaPlayerService>& service = getMediaPlayerService();
774 if (service != 0) {
775 p = service->decode(url, pSampleRate, pNumChannels, pFormat);
776 } else {
777 ALOGE("Unable to locate media service");
778 }
779 return p;
780
781 }
782
died()783 void MediaPlayer::died()
784 {
785 ALOGV("died");
786 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
787 }
788
decode(int fd,int64_t offset,int64_t length,uint32_t * pSampleRate,int * pNumChannels,audio_format_t * pFormat)789 /*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
790 {
791 ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
792 sp<IMemory> p;
793 const sp<IMediaPlayerService>& service = getMediaPlayerService();
794 if (service != 0) {
795 p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
796 } else {
797 ALOGE("Unable to locate media service");
798 }
799 return p;
800
801 }
802
setNextMediaPlayer(const sp<MediaPlayer> & next)803 status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
804 if (mPlayer == NULL) {
805 return NO_INIT;
806 }
807 return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
808 }
809
810 }; // namespace android
811