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