blob: ebdbda89379de44033c69cd4151b5936e2f2ea98 [file] [log] [blame]
The Android Open Source Project2729ea92008-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>
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080031#include <media/AudioTrack.h>
The Android Open Source Project2729ea92008-10-21 07:00:00 -070032
33#include <utils/MemoryBase.h>
34
35namespace android {
36
37// client singleton for binder interface to service
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080038Mutex MediaPlayer::sServiceLock;
39sp<IMediaPlayerService> MediaPlayer::sMediaPlayerService;
40sp<MediaPlayer::DeathNotifier> MediaPlayer::sDeathNotifier;
41SortedVector< wp<MediaPlayer> > MediaPlayer::sObitRecipients;
The Android Open Source Project2729ea92008-10-21 07:00:00 -070042
43// establish binder interface to service
44const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService()
45{
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080046 Mutex::Autolock _l(sServiceLock);
47 if (sMediaPlayerService.get() == 0) {
The Android Open Source Project2729ea92008-10-21 07:00:00 -070048 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);
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080057 if (sDeathNotifier == NULL) {
58 sDeathNotifier = new DeathNotifier();
The Android Open Source Project2729ea92008-10-21 07:00:00 -070059 }
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080060 binder->linkToDeath(sDeathNotifier);
61 sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
The Android Open Source Project2729ea92008-10-21 07:00:00 -070062 }
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080063 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);
The Android Open Source Project2729ea92008-10-21 07:00:00 -070077}
78
79MediaPlayer::MediaPlayer()
80{
81 LOGV("constructor");
82 mListener = NULL;
83 mCookie = NULL;
84 mDuration = -1;
85 mStreamType = AudioTrack::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;
The Android Open Source Project7b5eb022008-12-17 18:05:43 -080093 mVideoWidth = mVideoHeight = 0;
94}
95
96void MediaPlayer::onFirstRef()
97{
98 addObitRecipient(this);
The Android Open Source Project2729ea92008-10-21 07:00:00 -070099}
100
101MediaPlayer::~MediaPlayer()
102{
103 LOGV("destructor");
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800104 removeObitRecipient(this);
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700105 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();
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700121 }
122}
123
124// always call with lock held
125void MediaPlayer::clear_l()
126{
127 mDuration = -1;
128 mCurrentPosition = -1;
129 mSeekPosition = -1;
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800130 mVideoWidth = mVideoHeight = 0;
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700131}
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;
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700159 err = NO_ERROR;
160 } else {
161 LOGE("Unable to to create media player");
162 }
163 }
164
165 if (p != 0) {
166 p->disconnect();
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700167 }
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800168
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700169 return err;
170}
171
172status_t MediaPlayer::setDataSource(const char *url)
173{
174 LOGV("setDataSource(%s)", url);
175 status_t err = UNKNOWN_ERROR;
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 UNKNOWN_ERROR;
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 UNKNOWN_ERROR;
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 ret = UNKNOWN_ERROR;
257 } else {
258 if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
259 LOGV("playback completed immediately following start()");
260 }
261 }
262 return ret;
263 }
264 LOGE("start called in state %d", mCurrentState);
265 return INVALID_OPERATION;
266}
267
268status_t MediaPlayer::stop()
269{
270 LOGV("stop");
271 Mutex::Autolock _l(mLock);
272 if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
273 if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
274 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
275 status_t ret = mPlayer->stop();
276 if (ret != NO_ERROR) {
277 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
278 ret = UNKNOWN_ERROR;
279 } else {
280 mCurrentState = MEDIA_PLAYER_STOPPED;
281 }
282 return ret;
283 }
284 LOGE("stop called in state %d", mCurrentState);
285 return INVALID_OPERATION;
286}
287
288status_t MediaPlayer::pause()
289{
290 LOGV("pause");
291 Mutex::Autolock _l(mLock);
292 if (mCurrentState & MEDIA_PLAYER_PAUSED)
293 return NO_ERROR;
294 if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
295 status_t ret = mPlayer->pause();
296 if (ret != NO_ERROR) {
297 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
298 ret = UNKNOWN_ERROR;
299 } else {
300 mCurrentState = MEDIA_PLAYER_PAUSED;
301 }
302 return ret;
303 }
304 LOGE("pause called in state %d", mCurrentState);
305 return INVALID_OPERATION;
306}
307
308bool MediaPlayer::isPlaying()
309{
310 Mutex::Autolock _l(mLock);
311 if (mPlayer != 0) {
312 bool temp = false;
313 mPlayer->isPlaying(&temp);
314 LOGV("isPlaying: %d", temp);
315 if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
316 LOGE("internal/external state mismatch corrected");
317 mCurrentState = MEDIA_PLAYER_PAUSED;
318 }
319 return temp;
320 }
321 LOGV("isPlaying: no active player");
322 return false;
323}
324
325status_t MediaPlayer::getVideoWidth(int *w)
326{
327 LOGV("getVideoWidth");
328 Mutex::Autolock _l(mLock);
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800329 if (mPlayer == 0) return INVALID_OPERATION;
330 *w = mVideoWidth;
331 return NO_ERROR;
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700332}
333
334status_t MediaPlayer::getVideoHeight(int *h)
335{
336 LOGV("getVideoHeight");
337 Mutex::Autolock _l(mLock);
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800338 if (mPlayer == 0) return INVALID_OPERATION;
339 *h = mVideoHeight;
340 return NO_ERROR;
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700341}
342
343status_t MediaPlayer::getCurrentPosition(int *msec)
344{
345 LOGV("getCurrentPosition");
346 Mutex::Autolock _l(mLock);
347 if (mPlayer != 0) {
348 if (mCurrentPosition >= 0) {
349 LOGV("Using cached seek position: %d", mCurrentPosition);
350 *msec = mCurrentPosition;
351 return NO_ERROR;
352 }
353 return mPlayer->getCurrentPosition(msec);
354 }
355 return INVALID_OPERATION;
356}
357
358status_t MediaPlayer::getDuration_l(int *msec)
359{
360 LOGV("getDuration");
361 bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
362 if (mPlayer != 0 && isValidState) {
363 status_t ret = NO_ERROR;
364 if (mDuration <= 0)
365 ret = mPlayer->getDuration(&mDuration);
366 if (msec)
367 *msec = mDuration;
368 return ret;
369 }
370 LOGE("Attempt to call getDuration without a valid mediaplayer");
371 return INVALID_OPERATION;
372}
373
374status_t MediaPlayer::getDuration(int *msec)
375{
376 Mutex::Autolock _l(mLock);
377 return getDuration_l(msec);
378}
379
380status_t MediaPlayer::seekTo_l(int msec)
381{
382 LOGV("seekTo %d", msec);
383 if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
384 if ( msec < 0 ) {
385 LOGW("Attempt to seek to invalid position: %d", msec);
386 msec = 0;
387 } else if ((mDuration > 0) && (msec > mDuration)) {
388 LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
389 msec = mDuration;
390 }
391 // cache duration
392 mCurrentPosition = msec;
393 if (mSeekPosition < 0) {
394 getDuration_l(NULL);
395 mSeekPosition = msec;
396 return mPlayer->seekTo(msec);
397 }
398 else {
399 LOGV("Seek in progress - queue up seekTo[%d]", msec);
400 return NO_ERROR;
401 }
402 }
403 LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
404 return INVALID_OPERATION;
405}
406
407status_t MediaPlayer::seekTo(int msec)
408{
409 Mutex::Autolock _l(mLock);
410 return seekTo_l(msec);
411}
412
413status_t MediaPlayer::reset()
414{
415 LOGV("reset");
416 Mutex::Autolock _l(mLock);
417 mLoop = false;
418 if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
419 mPrepareSync = false;
420 if (mPlayer != 0) {
421 status_t ret = mPlayer->reset();
422 if (ret != NO_ERROR) {
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800423 LOGE("reset() failed with return code (%d)", ret);
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700424 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
425 ret = UNKNOWN_ERROR;
426 } else {
427 mCurrentState = MEDIA_PLAYER_IDLE;
428 }
429 return ret;
430 }
431 clear_l();
432 return NO_ERROR;
433}
434
435status_t MediaPlayer::setAudioStreamType(int type)
436{
437 LOGV("MediaPlayer::setAudioStreamType");
438 Mutex::Autolock _l(mLock);
439 if (mStreamType == type) return NO_ERROR;
440 if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
441 MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
442 // Can't change the stream type after prepare
443 LOGE("setAudioStream called in state %d", mCurrentState);
444 return INVALID_OPERATION;
445 }
446 // cache
447 mStreamType = type;
448 return OK;
449}
450
451status_t MediaPlayer::setLooping(int loop)
452{
453 LOGV("MediaPlayer::setLooping");
454 Mutex::Autolock _l(mLock);
455 mLoop = (loop != 0);
456 if (mPlayer != 0) {
457 return mPlayer->setLooping(loop);
458 }
459 return OK;
460}
461
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800462bool MediaPlayer::isLooping() {
463 LOGV("isLooping");
464 Mutex::Autolock _l(mLock);
465 if (mPlayer != 0) {
466 return mLoop;
467 }
468 LOGV("isLooping: no active player");
469 return false;
470}
471
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700472status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
473{
474 LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
475 Mutex::Autolock _l(mLock);
476 mLeftVolume = leftVolume;
477 mRightVolume = rightVolume;
478 if (mPlayer != 0) {
479 return mPlayer->setVolume(leftVolume, rightVolume);
480 }
481 return OK;
482}
483
484void MediaPlayer::notify(int msg, int ext1, int ext2)
485{
486 LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
487 bool send = true;
488
489 // TODO: In the future, we might be on the same thread if the app is
490 // running in the same process as the media server. In that case,
491 // this will deadlock.
492 mLock.lock();
493 if (mPlayer == 0) {
494 LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800495 mLock.unlock(); // release the lock when done.
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700496 return;
497 }
498
499 switch (msg) {
500 case MEDIA_NOP: // interface test message
501 break;
502 case MEDIA_PREPARED:
503 LOGV("prepared");
504 mCurrentState = MEDIA_PLAYER_PREPARED;
505 if (mPrepareSync) {
506 LOGV("signal application thread");
507 mPrepareSync = false;
508 mPrepareStatus = NO_ERROR;
509 mSignal.signal();
510 }
511 break;
512 case MEDIA_PLAYBACK_COMPLETE:
513 LOGV("playback complete");
514 if (!mLoop) {
515 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
516 }
517 break;
518 case MEDIA_ERROR:
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800519 // Always log errors
520 LOGE("error (%d, %d)", ext1, ext2);
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700521 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
522 if (mPrepareSync)
523 {
524 LOGV("signal application thread");
525 mPrepareSync = false;
526 mPrepareStatus = ext1;
527 mSignal.signal();
528 send = false;
529 }
530 break;
531 case MEDIA_SEEK_COMPLETE:
532 LOGV("Received seek complete");
533 if (mSeekPosition != mCurrentPosition) {
534 LOGV("Executing queued seekTo(%d)", mSeekPosition);
535 mSeekPosition = -1;
536 seekTo_l(mCurrentPosition);
537 }
538 else {
539 LOGV("All seeks complete - return to regularly scheduled program");
540 mCurrentPosition = mSeekPosition = -1;
541 }
542 break;
543 case MEDIA_BUFFERING_UPDATE:
544 LOGV("buffering %d", ext1);
545 break;
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800546 case MEDIA_SET_VIDEO_SIZE:
547 LOGV("New video size %d x %d", ext1, ext2);
548 mVideoWidth = ext1;
549 mVideoHeight = ext2;
550 break;
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700551 default:
552 LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
553 break;
554 }
555
556 sp<MediaPlayerListener> listener = mListener;
557 mLock.unlock();
558
559 // this prevents re-entrant calls into client code
560 if ((listener != 0) && send) {
561 Mutex::Autolock _l(mNotifyLock);
562 LOGV("callback application");
563 listener->notify(msg, ext1, ext2);
564 LOGV("back from callback");
565 }
566}
567
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700568void MediaPlayer::DeathNotifier::binderDied(const wp<IBinder>& who) {
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700569 LOGW("MediaPlayer server died!");
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800570
571 // Need to do this with the lock held
572 SortedVector< wp<MediaPlayer> > list;
573 {
574 Mutex::Autolock _l(MediaPlayer::sServiceLock);
575 MediaPlayer::sMediaPlayerService.clear();
576 list = sObitRecipients;
577 }
578
579 // Notify application when media server dies.
580 // Don't hold the static lock during callback in case app
581 // makes a call that needs the lock.
582 size_t count = list.size();
583 for (size_t iter = 0; iter < count; ++iter) {
584 sp<MediaPlayer> player = list[iter].promote();
585 if ((player != 0) && (player->mPlayer != 0)) {
586 player->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
587 }
588 }
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700589}
590
591MediaPlayer::DeathNotifier::~DeathNotifier()
592{
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800593 Mutex::Autolock _l(sServiceLock);
594 sObitRecipients.clear();
595 if (sMediaPlayerService != 0) {
596 sMediaPlayerService->asBinder()->unlinkToDeath(this);
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700597 }
598}
599
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800600/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700601{
602 LOGV("decode(%s)", url);
603 sp<IMemory> p;
604 const sp<IMediaPlayerService>& service = getMediaPlayerService();
605 if (service != 0) {
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800606 p = sMediaPlayerService->decode(url, pSampleRate, pNumChannels, pFormat);
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700607 } else {
608 LOGE("Unable to locate media service");
609 }
610 return p;
611
612}
613
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800614/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700615{
616 LOGV("decode(%d, %lld, %lld)", fd, offset, length);
617 sp<IMemory> p;
618 const sp<IMediaPlayerService>& service = getMediaPlayerService();
619 if (service != 0) {
The Android Open Source Project7b5eb022008-12-17 18:05:43 -0800620 p = sMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
The Android Open Source Project2729ea92008-10-21 07:00:00 -0700621 } else {
622 LOGE("Unable to locate media service");
623 }
624 return p;
625
626}
627
628}; // namespace android