blob: bd8579ca8d84ba12e3ee22e5af625f8492eed0c8 [file] [log] [blame]
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001/* mediaplayer.cpp
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 <utils/IServiceManager.h>
28#include <utils/IPCThreadState.h>
29
30#include <media/mediaplayer.h>
31#include <media/AudioTrack.h>
32
33#include <utils/MemoryBase.h>
34
35namespace android {
36
37// client singleton for binder interface to service
38Mutex MediaPlayer::sServiceLock;
39sp<IMediaPlayerService> MediaPlayer::sMediaPlayerService;
40sp<MediaPlayer::DeathNotifier> MediaPlayer::sDeathNotifier;
41SortedVector< wp<MediaPlayer> > MediaPlayer::sObitRecipients;
42
43// establish binder interface to service
44const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService()
45{
46 Mutex::Autolock _l(sServiceLock);
47 if (sMediaPlayerService.get() == 0) {
48 sp<IServiceManager> sm = defaultServiceManager();
49 sp<IBinder> binder;
50 do {
51 binder = sm->getService(String16("media.player"));
52 if (binder != 0)
53 break;
54 LOGW("MediaPlayerService not published, waiting...");
55 usleep(500000); // 0.5 s
56 } while(true);
57 if (sDeathNotifier == NULL) {
58 sDeathNotifier = new DeathNotifier();
59 }
60 binder->linkToDeath(sDeathNotifier);
61 sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
62 }
63 LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?");
64 return sMediaPlayerService;
65}
66
67void MediaPlayer::addObitRecipient(const wp<MediaPlayer>& recipient)
68{
69 Mutex::Autolock _l(sServiceLock);
70 sObitRecipients.add(recipient);
71}
72
73void MediaPlayer::removeObitRecipient(const wp<MediaPlayer>& recipient)
74{
75 Mutex::Autolock _l(sServiceLock);
76 sObitRecipients.remove(recipient);
77}
78
79MediaPlayer::MediaPlayer()
80{
81 LOGV("constructor");
82 mListener = NULL;
83 mCookie = NULL;
84 mDuration = -1;
85 mStreamType = AudioSystem::MUSIC;
86 mCurrentPosition = -1;
87 mSeekPosition = -1;
88 mCurrentState = MEDIA_PLAYER_IDLE;
89 mPrepareSync = false;
90 mPrepareStatus = NO_ERROR;
91 mLoop = false;
92 mLeftVolume = mRightVolume = 1.0;
93 mVideoWidth = mVideoHeight = 0;
94}
95
96void MediaPlayer::onFirstRef()
97{
98 addObitRecipient(this);
99}
100
101MediaPlayer::~MediaPlayer()
102{
103 LOGV("destructor");
104 removeObitRecipient(this);
105 disconnect();
106 IPCThreadState::self()->flushCommands();
107}
108
109void MediaPlayer::disconnect()
110{
111 LOGV("disconnect");
112 sp<IMediaPlayer> p;
113 {
114 Mutex::Autolock _l(mLock);
115 p = mPlayer;
116 mPlayer.clear();
117 }
118
119 if (p != 0) {
120 p->disconnect();
121 }
122}
123
124// always call with lock held
125void MediaPlayer::clear_l()
126{
127 mDuration = -1;
128 mCurrentPosition = -1;
129 mSeekPosition = -1;
130 mVideoWidth = mVideoHeight = 0;
131}
132
133status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
134{
135 LOGV("setListener");
136 Mutex::Autolock _l(mLock);
137 mListener = listener;
138 return NO_ERROR;
139}
140
141
142status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player)
143{
144 status_t err = UNKNOWN_ERROR;
145 sp<IMediaPlayer> p;
146 { // scope for the lock
147 Mutex::Autolock _l(mLock);
148
149 if ( !( mCurrentState & ( MEDIA_PLAYER_IDLE | MEDIA_PLAYER_STATE_ERROR ) ) ) {
150 LOGE("setDataSource called in state %d", mCurrentState);
151 return INVALID_OPERATION;
152 }
153
154 clear_l();
155 p = mPlayer;
156 mPlayer = player;
157 if (player != 0) {
158 mCurrentState = MEDIA_PLAYER_INITIALIZED;
159 err = NO_ERROR;
160 } else {
161 LOGE("Unable to to create media player");
162 }
163 }
164
165 if (p != 0) {
166 p->disconnect();
167 }
168
169 return err;
170}
171
172status_t MediaPlayer::setDataSource(const char *url)
173{
174 LOGV("setDataSource(%s)", url);
175 status_t err = BAD_VALUE;
176 if (url != NULL) {
177 const sp<IMediaPlayerService>& service(getMediaPlayerService());
178 if (service != 0) {
179 sp<IMediaPlayer> player(service->create(getpid(), this, url));
180 err = setDataSource(player);
181 }
182 }
183 return err;
184}
185
186status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
187{
188 LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
189 status_t err = UNKNOWN_ERROR;
190 const sp<IMediaPlayerService>& service(getMediaPlayerService());
191 if (service != 0) {
192 sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length));
193 err = setDataSource(player);
194 }
195 return err;
196}
197
198status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
199{
200 LOGV("setVideoSurface");
201 Mutex::Autolock _l(mLock);
202 if (mPlayer == 0) return NO_INIT;
203 return mPlayer->setVideoSurface(surface->getISurface());
204}
205
206// must call with lock held
207status_t MediaPlayer::prepareAsync_l()
208{
209 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
210 mPlayer->setAudioStreamType(mStreamType);
211 mCurrentState = MEDIA_PLAYER_PREPARING;
212 return mPlayer->prepareAsync();
213 }
214 LOGE("prepareAsync called in state %d", mCurrentState);
215 return INVALID_OPERATION;
216}
217
218status_t MediaPlayer::prepare()
219{
220 LOGV("prepare");
221 Mutex::Autolock _l(mLock);
222 if (mPrepareSync) return -EALREADY;
223 mPrepareSync = true;
224 status_t ret = prepareAsync_l();
225 if (ret != NO_ERROR) return ret;
226
227 if (mPrepareSync) {
228 mSignal.wait(mLock); // wait for prepare done
229 mPrepareSync = false;
230 }
231 LOGV("prepare complete - status=%d", mPrepareStatus);
232 return mPrepareStatus;
233}
234
235status_t MediaPlayer::prepareAsync()
236{
237 LOGV("prepareAsync");
238 Mutex::Autolock _l(mLock);
239 return prepareAsync_l();
240}
241
242status_t MediaPlayer::start()
243{
244 LOGV("start");
245 Mutex::Autolock _l(mLock);
246 if (mCurrentState & MEDIA_PLAYER_STARTED)
247 return NO_ERROR;
248 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
249 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
250 mPlayer->setLooping(mLoop);
251 mPlayer->setVolume(mLeftVolume, mRightVolume);
252 mCurrentState = MEDIA_PLAYER_STARTED;
253 status_t ret = mPlayer->start();
254 if (ret != NO_ERROR) {
255 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
256 } else {
257 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
258 LOGV("playback completed immediately following start()");
259 }
260 }
261 return ret;
262 }
263 LOGE("start called in state %d", mCurrentState);
264 return INVALID_OPERATION;
265}
266
267status_t MediaPlayer::stop()
268{
269 LOGV("stop");
270 Mutex::Autolock _l(mLock);
271 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
272 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
273 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
274 status_t ret = mPlayer->stop();
275 if (ret != NO_ERROR) {
276 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
277 } else {
278 mCurrentState = MEDIA_PLAYER_STOPPED;
279 }
280 return ret;
281 }
282 LOGE("stop called in state %d", mCurrentState);
283 return INVALID_OPERATION;
284}
285
286status_t MediaPlayer::pause()
287{
288 LOGV("pause");
289 Mutex::Autolock _l(mLock);
290 if (mCurrentState & MEDIA_PLAYER_PAUSED)
291 return NO_ERROR;
292 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
293 status_t ret = mPlayer->pause();
294 if (ret != NO_ERROR) {
295 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
296 } else {
297 mCurrentState = MEDIA_PLAYER_PAUSED;
298 }
299 return ret;
300 }
301 LOGE("pause called in state %d", mCurrentState);
302 return INVALID_OPERATION;
303}
304
305bool MediaPlayer::isPlaying()
306{
307 Mutex::Autolock _l(mLock);
308 if (mPlayer != 0) {
309 bool temp = false;
310 mPlayer->isPlaying(&temp);
311 LOGV("isPlaying: %d", temp);
312 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
313 LOGE("internal/external state mismatch corrected");
314 mCurrentState = MEDIA_PLAYER_PAUSED;
315 }
316 return temp;
317 }
318 LOGV("isPlaying: no active player");
319 return false;
320}
321
322status_t MediaPlayer::getVideoWidth(int *w)
323{
324 LOGV("getVideoWidth");
325 Mutex::Autolock _l(mLock);
326 if (mPlayer == 0) return INVALID_OPERATION;
327 *w = mVideoWidth;
328 return NO_ERROR;
329}
330
331status_t MediaPlayer::getVideoHeight(int *h)
332{
333 LOGV("getVideoHeight");
334 Mutex::Autolock _l(mLock);
335 if (mPlayer == 0) return INVALID_OPERATION;
336 *h = mVideoHeight;
337 return NO_ERROR;
338}
339
340status_t MediaPlayer::getCurrentPosition(int *msec)
341{
342 LOGV("getCurrentPosition");
343 Mutex::Autolock _l(mLock);
344 if (mPlayer != 0) {
345 if (mCurrentPosition >= 0) {
346 LOGV("Using cached seek position: %d", mCurrentPosition);
347 *msec = mCurrentPosition;
348 return NO_ERROR;
349 }
350 return mPlayer->getCurrentPosition(msec);
351 }
352 return INVALID_OPERATION;
353}
354
355status_t MediaPlayer::getDuration_l(int *msec)
356{
357 LOGV("getDuration");
358 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
359 if (mPlayer != 0 && isValidState) {
360 status_t ret = NO_ERROR;
361 if (mDuration <= 0)
362 ret = mPlayer->getDuration(&mDuration);
363 if (msec)
364 *msec = mDuration;
365 return ret;
366 }
367 LOGE("Attempt to call getDuration without a valid mediaplayer");
368 return INVALID_OPERATION;
369}
370
371status_t MediaPlayer::getDuration(int *msec)
372{
373 Mutex::Autolock _l(mLock);
374 return getDuration_l(msec);
375}
376
377status_t MediaPlayer::seekTo_l(int msec)
378{
379 LOGV("seekTo %d", msec);
380 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
381 if ( msec < 0 ) {
382 LOGW("Attempt to seek to invalid position: %d", msec);
383 msec = 0;
384 } else if ((mDuration > 0) && (msec > mDuration)) {
385 LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
386 msec = mDuration;
387 }
388 // cache duration
389 mCurrentPosition = msec;
390 if (mSeekPosition < 0) {
391 getDuration_l(NULL);
392 mSeekPosition = msec;
393 return mPlayer->seekTo(msec);
394 }
395 else {
396 LOGV("Seek in progress - queue up seekTo[%d]", msec);
397 return NO_ERROR;
398 }
399 }
400 LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
401 return INVALID_OPERATION;
402}
403
404status_t MediaPlayer::seekTo(int msec)
405{
406 Mutex::Autolock _l(mLock);
407 return seekTo_l(msec);
408}
409
410status_t MediaPlayer::reset()
411{
412 LOGV("reset");
413 Mutex::Autolock _l(mLock);
414 mLoop = false;
415 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
416 mPrepareSync = false;
417 if (mPlayer != 0) {
418 status_t ret = mPlayer->reset();
419 if (ret != NO_ERROR) {
420 LOGE("reset() failed with return code (%d)", ret);
421 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
422 } else {
423 mCurrentState = MEDIA_PLAYER_IDLE;
424 }
425 return ret;
426 }
427 clear_l();
428 return NO_ERROR;
429}
430
431status_t MediaPlayer::setAudioStreamType(int type)
432{
433 LOGV("MediaPlayer::setAudioStreamType");
434 Mutex::Autolock _l(mLock);
435 if (mStreamType == type) return NO_ERROR;
436 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
437 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
438 // Can't change the stream type after prepare
439 LOGE("setAudioStream called in state %d", mCurrentState);
440 return INVALID_OPERATION;
441 }
442 // cache
443 mStreamType = type;
444 return OK;
445}
446
447status_t MediaPlayer::setLooping(int loop)
448{
449 LOGV("MediaPlayer::setLooping");
450 Mutex::Autolock _l(mLock);
451 mLoop = (loop != 0);
452 if (mPlayer != 0) {
453 return mPlayer->setLooping(loop);
454 }
455 return OK;
456}
457
458bool MediaPlayer::isLooping() {
459 LOGV("isLooping");
460 Mutex::Autolock _l(mLock);
461 if (mPlayer != 0) {
462 return mLoop;
463 }
464 LOGV("isLooping: no active player");
465 return false;
466}
467
468status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
469{
470 LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
471 Mutex::Autolock _l(mLock);
472 mLeftVolume = leftVolume;
473 mRightVolume = rightVolume;
474 if (mPlayer != 0) {
475 return mPlayer->setVolume(leftVolume, rightVolume);
476 }
477 return OK;
478}
479
480void MediaPlayer::notify(int msg, int ext1, int ext2)
481{
482 LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
483 bool send = true;
484
485 // TODO: In the future, we might be on the same thread if the app is
486 // running in the same process as the media server. In that case,
487 // this will deadlock.
488 mLock.lock();
489 if (mPlayer == 0) {
490 LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
491 mLock.unlock(); // release the lock when done.
492 return;
493 }
494
495 switch (msg) {
496 case MEDIA_NOP: // interface test message
497 break;
498 case MEDIA_PREPARED:
499 LOGV("prepared");
500 mCurrentState = MEDIA_PLAYER_PREPARED;
501 if (mPrepareSync) {
502 LOGV("signal application thread");
503 mPrepareSync = false;
504 mPrepareStatus = NO_ERROR;
505 mSignal.signal();
506 }
507 break;
508 case MEDIA_PLAYBACK_COMPLETE:
509 LOGV("playback complete");
510 if (!mLoop) {
511 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
512 }
513 break;
514 case MEDIA_ERROR:
515 // Always log errors
516 LOGE("error (%d, %d)", ext1, ext2);
517 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
518 if (mPrepareSync)
519 {
520 LOGV("signal application thread");
521 mPrepareSync = false;
522 mPrepareStatus = ext1;
523 mSignal.signal();
524 send = false;
525 }
526 break;
527 case MEDIA_SEEK_COMPLETE:
528 LOGV("Received seek complete");
529 if (mSeekPosition != mCurrentPosition) {
530 LOGV("Executing queued seekTo(%d)", mSeekPosition);
531 mSeekPosition = -1;
532 seekTo_l(mCurrentPosition);
533 }
534 else {
535 LOGV("All seeks complete - return to regularly scheduled program");
536 mCurrentPosition = mSeekPosition = -1;
537 }
538 break;
539 case MEDIA_BUFFERING_UPDATE:
540 LOGV("buffering %d", ext1);
541 break;
542 case MEDIA_SET_VIDEO_SIZE:
543 LOGV("New video size %d x %d", ext1, ext2);
544 mVideoWidth = ext1;
545 mVideoHeight = ext2;
546 break;
547 default:
548 LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
549 break;
550 }
551
552 sp<MediaPlayerListener> listener = mListener;
553 mLock.unlock();
554
555 // this prevents re-entrant calls into client code
556 if ((listener != 0) && send) {
557 Mutex::Autolock _l(mNotifyLock);
558 LOGV("callback application");
559 listener->notify(msg, ext1, ext2);
560 LOGV("back from callback");
561 }
562}
563
564void MediaPlayer::DeathNotifier::binderDied(const wp<IBinder>& who) {
565 LOGW("MediaPlayer server died!");
566
567 // Need to do this with the lock held
568 SortedVector< wp<MediaPlayer> > list;
569 {
570 Mutex::Autolock _l(MediaPlayer::sServiceLock);
571 MediaPlayer::sMediaPlayerService.clear();
572 list = sObitRecipients;
573 }
574
575 // Notify application when media server dies.
576 // Don't hold the static lock during callback in case app
577 // makes a call that needs the lock.
578 size_t count = list.size();
579 for (size_t iter = 0; iter < count; ++iter) {
580 sp<MediaPlayer> player = list[iter].promote();
581 if ((player != 0) && (player->mPlayer != 0)) {
582 player->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
583 }
584 }
585}
586
587MediaPlayer::DeathNotifier::~DeathNotifier()
588{
589 Mutex::Autolock _l(sServiceLock);
590 sObitRecipients.clear();
591 if (sMediaPlayerService != 0) {
592 sMediaPlayerService->asBinder()->unlinkToDeath(this);
593 }
594}
595
596/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
597{
598 LOGV("decode(%s)", url);
599 sp<IMemory> p;
600 const sp<IMediaPlayerService>& service = getMediaPlayerService();
601 if (service != 0) {
602 p = sMediaPlayerService->decode(url, pSampleRate, pNumChannels, pFormat);
603 } else {
604 LOGE("Unable to locate media service");
605 }
606 return p;
607
608}
609
610/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
611{
612 LOGV("decode(%d, %lld, %lld)", fd, offset, length);
613 sp<IMemory> p;
614 const sp<IMediaPlayerService>& service = getMediaPlayerService();
615 if (service != 0) {
616 p = sMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
617 } else {
618 LOGE("Unable to locate media service");
619 }
620 return p;
621
622}
623
624}; // namespace android