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