mediaplayer.cpp revision 2729ea9262ca60d93047e984739887cfc89e82eb
1/* 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
583