blob: ee3f660c8ff3680c2fc5febd536c7082452d26ed [file] [log] [blame]
The Android Open Source Project9066cfe2009-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
Mathias Agopian07952722009-05-19 19:08:10 -070027#include <binder/IServiceManager.h>
28#include <binder/IPCThreadState.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
30#include <media/mediaplayer.h>
31#include <media/AudioTrack.h>
32
Mathias Agopian000479f2010-02-09 17:46:37 -080033#include <surfaceflinger/Surface.h>
34
Mathias Agopian07952722009-05-19 19:08:10 -070035#include <binder/MemoryBase.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036
Andreas Huber25643002010-01-28 11:19:57 -080037#include <utils/KeyedVector.h>
38#include <utils/String8.h>
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040namespace android {
41
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042MediaPlayer::MediaPlayer()
43{
44 LOGV("constructor");
45 mListener = NULL;
46 mCookie = NULL;
47 mDuration = -1;
48 mStreamType = AudioSystem::MUSIC;
49 mCurrentPosition = -1;
50 mSeekPosition = -1;
51 mCurrentState = MEDIA_PLAYER_IDLE;
52 mPrepareSync = false;
53 mPrepareStatus = NO_ERROR;
54 mLoop = false;
55 mLeftVolume = mRightVolume = 1.0;
56 mVideoWidth = mVideoHeight = 0;
Jason Samsebb020a2009-03-24 18:45:22 -070057 mLockThreadId = 0;
Eric Laurent619346f2010-06-21 09:27:30 -070058 mAudioSessionId = AudioSystem::newAudioSessionId();
Eric Laurentb3bdf3f2010-10-07 18:23:03 -070059 mSendLevel = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060}
61
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062MediaPlayer::~MediaPlayer()
63{
64 LOGV("destructor");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 disconnect();
66 IPCThreadState::self()->flushCommands();
67}
68
69void MediaPlayer::disconnect()
70{
71 LOGV("disconnect");
72 sp<IMediaPlayer> p;
73 {
74 Mutex::Autolock _l(mLock);
75 p = mPlayer;
76 mPlayer.clear();
77 }
78
79 if (p != 0) {
80 p->disconnect();
81 }
82}
83
84// always call with lock held
85void MediaPlayer::clear_l()
86{
87 mDuration = -1;
88 mCurrentPosition = -1;
89 mSeekPosition = -1;
90 mVideoWidth = mVideoHeight = 0;
91}
92
93status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
94{
95 LOGV("setListener");
96 Mutex::Autolock _l(mLock);
97 mListener = listener;
98 return NO_ERROR;
99}
100
101
102status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player)
103{
104 status_t err = UNKNOWN_ERROR;
105 sp<IMediaPlayer> p;
106 { // scope for the lock
107 Mutex::Autolock _l(mLock);
108
Marco Nelissene44b41b2010-03-10 10:53:16 -0800109 if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
110 (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 LOGE("setDataSource called in state %d", mCurrentState);
112 return INVALID_OPERATION;
113 }
114
115 clear_l();
116 p = mPlayer;
117 mPlayer = player;
118 if (player != 0) {
119 mCurrentState = MEDIA_PLAYER_INITIALIZED;
120 err = NO_ERROR;
121 } else {
122 LOGE("Unable to to create media player");
123 }
124 }
125
126 if (p != 0) {
127 p->disconnect();
128 }
129
130 return err;
131}
132
Andreas Huber25643002010-01-28 11:19:57 -0800133status_t MediaPlayer::setDataSource(
134 const char *url, const KeyedVector<String8, String8> *headers)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135{
136 LOGV("setDataSource(%s)", url);
137 status_t err = BAD_VALUE;
138 if (url != NULL) {
139 const sp<IMediaPlayerService>& service(getMediaPlayerService());
140 if (service != 0) {
Andreas Huber25643002010-01-28 11:19:57 -0800141 sp<IMediaPlayer> player(
Eric Laurent619346f2010-06-21 09:27:30 -0700142 service->create(getpid(), this, url, headers, mAudioSessionId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 err = setDataSource(player);
144 }
145 }
146 return err;
147}
148
149status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
150{
151 LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
152 status_t err = UNKNOWN_ERROR;
153 const sp<IMediaPlayerService>& service(getMediaPlayerService());
154 if (service != 0) {
Eric Laurent619346f2010-06-21 09:27:30 -0700155 sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 err = setDataSource(player);
157 }
158 return err;
159}
160
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700161status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
162{
163 Mutex::Autolock _l(mLock);
Nicolas Catania7bd3d7d2010-03-10 10:41:04 -0800164 const bool hasBeenInitialized =
165 (mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
166 ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
167 if ((mPlayer != NULL) && hasBeenInitialized) {
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700168 LOGV("invoke %d", request.dataSize());
169 return mPlayer->invoke(request, reply);
170 }
171 LOGE("invoke failed: wrong state %X", mCurrentState);
172 return INVALID_OPERATION;
173}
174
Andreas Huberfbb38852010-02-12 12:35:58 -0800175status_t MediaPlayer::suspend() {
176 Mutex::Autolock _l(mLock);
177 return mPlayer->suspend();
178}
179
180status_t MediaPlayer::resume() {
181 Mutex::Autolock _l(mLock);
182 return mPlayer->resume();
183}
184
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700185status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
186{
187 LOGD("setMetadataFilter");
Nicolas Catania5d55c712009-07-09 09:21:33 -0700188 Mutex::Autolock lock(mLock);
189 if (mPlayer == NULL) {
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700190 return NO_INIT;
191 }
192 return mPlayer->setMetadataFilter(filter);
193}
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700194
Nicolas Catania5d55c712009-07-09 09:21:33 -0700195status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
196{
197 LOGD("getMetadata");
198 Mutex::Autolock lock(mLock);
199 if (mPlayer == NULL) {
200 return NO_INIT;
201 }
202 return mPlayer->getMetadata(update_only, apply_filter, metadata);
203}
204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
206{
207 LOGV("setVideoSurface");
208 Mutex::Autolock _l(mLock);
209 if (mPlayer == 0) return NO_INIT;
Andreas Hubere3c01832010-08-16 08:49:37 -0700210
211 status_t err = mPlayer->setVideoISurface(
212 surface == NULL ? NULL : surface->getISurface());
213
214 if (err != OK) {
215 return err;
216 }
217
218 return mPlayer->setVideoSurface(surface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219}
220
221// must call with lock held
222status_t MediaPlayer::prepareAsync_l()
223{
224 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
225 mPlayer->setAudioStreamType(mStreamType);
226 mCurrentState = MEDIA_PLAYER_PREPARING;
227 return mPlayer->prepareAsync();
228 }
229 LOGE("prepareAsync called in state %d", mCurrentState);
230 return INVALID_OPERATION;
231}
232
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700233// TODO: In case of error, prepareAsync provides the caller with 2 error codes,
234// one defined in the Android framework and one provided by the implementation
235// that generated the error. The sync version of prepare returns only 1 error
236// code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237status_t MediaPlayer::prepare()
238{
239 LOGV("prepare");
240 Mutex::Autolock _l(mLock);
Jason Samsebb020a2009-03-24 18:45:22 -0700241 mLockThreadId = getThreadId();
242 if (mPrepareSync) {
243 mLockThreadId = 0;
244 return -EALREADY;
245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 mPrepareSync = true;
247 status_t ret = prepareAsync_l();
Jason Samsebb020a2009-03-24 18:45:22 -0700248 if (ret != NO_ERROR) {
249 mLockThreadId = 0;
250 return ret;
251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 if (mPrepareSync) {
254 mSignal.wait(mLock); // wait for prepare done
255 mPrepareSync = false;
256 }
257 LOGV("prepare complete - status=%d", mPrepareStatus);
Jason Samsebb020a2009-03-24 18:45:22 -0700258 mLockThreadId = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 return mPrepareStatus;
260}
261
262status_t MediaPlayer::prepareAsync()
263{
264 LOGV("prepareAsync");
265 Mutex::Autolock _l(mLock);
266 return prepareAsync_l();
267}
268
269status_t MediaPlayer::start()
270{
271 LOGV("start");
272 Mutex::Autolock _l(mLock);
273 if (mCurrentState & MEDIA_PLAYER_STARTED)
274 return NO_ERROR;
275 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
276 MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
277 mPlayer->setLooping(mLoop);
278 mPlayer->setVolume(mLeftVolume, mRightVolume);
Eric Laurent7070b362010-07-16 07:43:46 -0700279 mPlayer->setAuxEffectSendLevel(mSendLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 mCurrentState = MEDIA_PLAYER_STARTED;
281 status_t ret = mPlayer->start();
282 if (ret != NO_ERROR) {
283 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
284 } else {
285 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
286 LOGV("playback completed immediately following start()");
287 }
288 }
289 return ret;
290 }
291 LOGE("start called in state %d", mCurrentState);
292 return INVALID_OPERATION;
293}
294
295status_t MediaPlayer::stop()
296{
297 LOGV("stop");
298 Mutex::Autolock _l(mLock);
299 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
300 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
301 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
302 status_t ret = mPlayer->stop();
303 if (ret != NO_ERROR) {
304 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
305 } else {
306 mCurrentState = MEDIA_PLAYER_STOPPED;
307 }
308 return ret;
309 }
310 LOGE("stop called in state %d", mCurrentState);
311 return INVALID_OPERATION;
312}
313
314status_t MediaPlayer::pause()
315{
316 LOGV("pause");
317 Mutex::Autolock _l(mLock);
Marco Nelissen465faa92010-02-26 13:16:23 -0800318 if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 return NO_ERROR;
320 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
321 status_t ret = mPlayer->pause();
322 if (ret != NO_ERROR) {
323 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
324 } else {
325 mCurrentState = MEDIA_PLAYER_PAUSED;
326 }
327 return ret;
328 }
329 LOGE("pause called in state %d", mCurrentState);
330 return INVALID_OPERATION;
331}
332
333bool MediaPlayer::isPlaying()
334{
335 Mutex::Autolock _l(mLock);
336 if (mPlayer != 0) {
337 bool temp = false;
338 mPlayer->isPlaying(&temp);
339 LOGV("isPlaying: %d", temp);
340 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
341 LOGE("internal/external state mismatch corrected");
342 mCurrentState = MEDIA_PLAYER_PAUSED;
343 }
344 return temp;
345 }
346 LOGV("isPlaying: no active player");
347 return false;
348}
349
350status_t MediaPlayer::getVideoWidth(int *w)
351{
352 LOGV("getVideoWidth");
353 Mutex::Autolock _l(mLock);
354 if (mPlayer == 0) return INVALID_OPERATION;
355 *w = mVideoWidth;
356 return NO_ERROR;
357}
358
359status_t MediaPlayer::getVideoHeight(int *h)
360{
361 LOGV("getVideoHeight");
362 Mutex::Autolock _l(mLock);
363 if (mPlayer == 0) return INVALID_OPERATION;
364 *h = mVideoHeight;
365 return NO_ERROR;
366}
367
368status_t MediaPlayer::getCurrentPosition(int *msec)
369{
370 LOGV("getCurrentPosition");
371 Mutex::Autolock _l(mLock);
372 if (mPlayer != 0) {
373 if (mCurrentPosition >= 0) {
374 LOGV("Using cached seek position: %d", mCurrentPosition);
375 *msec = mCurrentPosition;
376 return NO_ERROR;
377 }
378 return mPlayer->getCurrentPosition(msec);
379 }
380 return INVALID_OPERATION;
381}
382
383status_t MediaPlayer::getDuration_l(int *msec)
384{
385 LOGV("getDuration");
386 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
387 if (mPlayer != 0 && isValidState) {
388 status_t ret = NO_ERROR;
389 if (mDuration <= 0)
390 ret = mPlayer->getDuration(&mDuration);
391 if (msec)
392 *msec = mDuration;
393 return ret;
394 }
395 LOGE("Attempt to call getDuration without a valid mediaplayer");
396 return INVALID_OPERATION;
397}
398
399status_t MediaPlayer::getDuration(int *msec)
400{
401 Mutex::Autolock _l(mLock);
402 return getDuration_l(msec);
403}
404
405status_t MediaPlayer::seekTo_l(int msec)
406{
407 LOGV("seekTo %d", msec);
408 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
409 if ( msec < 0 ) {
410 LOGW("Attempt to seek to invalid position: %d", msec);
411 msec = 0;
412 } else if ((mDuration > 0) && (msec > mDuration)) {
413 LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
414 msec = mDuration;
415 }
416 // cache duration
417 mCurrentPosition = msec;
418 if (mSeekPosition < 0) {
419 getDuration_l(NULL);
420 mSeekPosition = msec;
421 return mPlayer->seekTo(msec);
422 }
423 else {
424 LOGV("Seek in progress - queue up seekTo[%d]", msec);
425 return NO_ERROR;
426 }
427 }
428 LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
429 return INVALID_OPERATION;
430}
431
432status_t MediaPlayer::seekTo(int msec)
433{
Andreas Hubereffd8d52009-03-24 20:48:51 -0700434 mLockThreadId = getThreadId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 Mutex::Autolock _l(mLock);
Andreas Hubereffd8d52009-03-24 20:48:51 -0700436 status_t result = seekTo_l(msec);
437 mLockThreadId = 0;
438
439 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440}
441
442status_t MediaPlayer::reset()
443{
444 LOGV("reset");
445 Mutex::Autolock _l(mLock);
446 mLoop = false;
447 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
448 mPrepareSync = false;
449 if (mPlayer != 0) {
450 status_t ret = mPlayer->reset();
451 if (ret != NO_ERROR) {
452 LOGE("reset() failed with return code (%d)", ret);
453 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
454 } else {
455 mCurrentState = MEDIA_PLAYER_IDLE;
456 }
457 return ret;
458 }
459 clear_l();
460 return NO_ERROR;
461}
462
463status_t MediaPlayer::setAudioStreamType(int type)
464{
465 LOGV("MediaPlayer::setAudioStreamType");
466 Mutex::Autolock _l(mLock);
467 if (mStreamType == type) return NO_ERROR;
468 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
469 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
470 // Can't change the stream type after prepare
471 LOGE("setAudioStream called in state %d", mCurrentState);
472 return INVALID_OPERATION;
473 }
474 // cache
475 mStreamType = type;
476 return OK;
477}
478
479status_t MediaPlayer::setLooping(int loop)
480{
481 LOGV("MediaPlayer::setLooping");
482 Mutex::Autolock _l(mLock);
483 mLoop = (loop != 0);
484 if (mPlayer != 0) {
485 return mPlayer->setLooping(loop);
486 }
487 return OK;
488}
489
490bool MediaPlayer::isLooping() {
491 LOGV("isLooping");
492 Mutex::Autolock _l(mLock);
493 if (mPlayer != 0) {
494 return mLoop;
495 }
496 LOGV("isLooping: no active player");
497 return false;
498}
499
500status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
501{
502 LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
503 Mutex::Autolock _l(mLock);
504 mLeftVolume = leftVolume;
505 mRightVolume = rightVolume;
506 if (mPlayer != 0) {
507 return mPlayer->setVolume(leftVolume, rightVolume);
508 }
509 return OK;
510}
511
Eric Laurent619346f2010-06-21 09:27:30 -0700512status_t MediaPlayer::setAudioSessionId(int sessionId)
513{
514 LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
515 Mutex::Autolock _l(mLock);
516 if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
517 LOGE("setAudioSessionId called in state %d", mCurrentState);
518 return INVALID_OPERATION;
519 }
520 if (sessionId < 0) {
521 return BAD_VALUE;
522 }
523 mAudioSessionId = sessionId;
524 return NO_ERROR;
525}
526
527int MediaPlayer::getAudioSessionId()
528{
529 Mutex::Autolock _l(mLock);
530 return mAudioSessionId;
531}
532
Eric Laurent7070b362010-07-16 07:43:46 -0700533status_t MediaPlayer::setAuxEffectSendLevel(float level)
534{
535 LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
536 Mutex::Autolock _l(mLock);
537 mSendLevel = level;
538 if (mPlayer != 0) {
539 return mPlayer->setAuxEffectSendLevel(level);
540 }
541 return OK;
542}
543
544status_t MediaPlayer::attachAuxEffect(int effectId)
545{
546 LOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
547 Mutex::Autolock _l(mLock);
548 if (mPlayer == 0 ||
549 (mCurrentState & MEDIA_PLAYER_IDLE) ||
550 (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
551 LOGE("attachAuxEffect called in state %d", mCurrentState);
552 return INVALID_OPERATION;
553 }
554
555 return mPlayer->attachAuxEffect(effectId);
556}
557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558void MediaPlayer::notify(int msg, int ext1, int ext2)
559{
560 LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
561 bool send = true;
Jason Samsebb020a2009-03-24 18:45:22 -0700562 bool locked = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563
564 // TODO: In the future, we might be on the same thread if the app is
565 // running in the same process as the media server. In that case,
566 // this will deadlock.
Nicolas Catania32f82772009-06-11 16:33:49 -0700567 //
Jason Samsebb020a2009-03-24 18:45:22 -0700568 // The threadId hack below works around this for the care of prepare
Andreas Hubereffd8d52009-03-24 20:48:51 -0700569 // and seekTo within the same process.
570 // FIXME: Remember, this is a hack, it's not even a hack that is applied
571 // consistently for all use-cases, this needs to be revisited.
Jason Samsebb020a2009-03-24 18:45:22 -0700572 if (mLockThreadId != getThreadId()) {
573 mLock.lock();
574 locked = true;
Nicolas Catania32f82772009-06-11 16:33:49 -0700575 }
Jason Samsebb020a2009-03-24 18:45:22 -0700576
Eric Laurent1d53b2a2010-08-03 07:49:49 -0700577 // Allows calls from JNI in idle state to notify errors
578 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
Jason Samsebb020a2009-03-24 18:45:22 -0700580 if (locked) mLock.unlock(); // release the lock when done.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 return;
582 }
583
584 switch (msg) {
585 case MEDIA_NOP: // interface test message
586 break;
587 case MEDIA_PREPARED:
588 LOGV("prepared");
589 mCurrentState = MEDIA_PLAYER_PREPARED;
590 if (mPrepareSync) {
591 LOGV("signal application thread");
592 mPrepareSync = false;
593 mPrepareStatus = NO_ERROR;
594 mSignal.signal();
595 }
596 break;
597 case MEDIA_PLAYBACK_COMPLETE:
598 LOGV("playback complete");
Marco Nelissen3c473ea2010-09-17 15:04:01 -0700599 if (mCurrentState == MEDIA_PLAYER_IDLE) {
600 LOGE("playback complete in idle state");
601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 if (!mLoop) {
603 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
604 }
605 break;
606 case MEDIA_ERROR:
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700607 // Always log errors.
608 // ext1: Media framework error code.
609 // ext2: Implementation dependant error code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 LOGE("error (%d, %d)", ext1, ext2);
611 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
612 if (mPrepareSync)
613 {
614 LOGV("signal application thread");
615 mPrepareSync = false;
616 mPrepareStatus = ext1;
617 mSignal.signal();
618 send = false;
619 }
620 break;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700621 case MEDIA_INFO:
622 // ext1: Media framework error code.
623 // ext2: Implementation dependant error code.
624 LOGW("info/warning (%d, %d)", ext1, ext2);
625 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 case MEDIA_SEEK_COMPLETE:
627 LOGV("Received seek complete");
628 if (mSeekPosition != mCurrentPosition) {
629 LOGV("Executing queued seekTo(%d)", mSeekPosition);
630 mSeekPosition = -1;
631 seekTo_l(mCurrentPosition);
632 }
633 else {
634 LOGV("All seeks complete - return to regularly scheduled program");
635 mCurrentPosition = mSeekPosition = -1;
636 }
637 break;
638 case MEDIA_BUFFERING_UPDATE:
639 LOGV("buffering %d", ext1);
640 break;
641 case MEDIA_SET_VIDEO_SIZE:
642 LOGV("New video size %d x %d", ext1, ext2);
643 mVideoWidth = ext1;
644 mVideoHeight = ext2;
645 break;
646 default:
647 LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
648 break;
649 }
650
651 sp<MediaPlayerListener> listener = mListener;
Jason Samsebb020a2009-03-24 18:45:22 -0700652 if (locked) mLock.unlock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653
654 // this prevents re-entrant calls into client code
655 if ((listener != 0) && send) {
656 Mutex::Autolock _l(mNotifyLock);
657 LOGV("callback application");
658 listener->notify(msg, ext1, ext2);
659 LOGV("back from callback");
660 }
661}
662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
664{
665 LOGV("decode(%s)", url);
666 sp<IMemory> p;
667 const sp<IMediaPlayerService>& service = getMediaPlayerService();
668 if (service != 0) {
James Dong34bbc222010-01-15 18:13:58 -0800669 p = service->decode(url, pSampleRate, pNumChannels, pFormat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 } else {
671 LOGE("Unable to locate media service");
672 }
673 return p;
674
675}
676
James Dong34bbc222010-01-15 18:13:58 -0800677void MediaPlayer::died()
678{
679 LOGV("died");
680 notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
681}
682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
684{
685 LOGV("decode(%d, %lld, %lld)", fd, offset, length);
686 sp<IMemory> p;
687 const sp<IMediaPlayerService>& service = getMediaPlayerService();
688 if (service != 0) {
James Dong34bbc222010-01-15 18:13:58 -0800689 p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 } else {
691 LOGE("Unable to locate media service");
692 }
693 return p;
694
695}
696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697}; // namespace android