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