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