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