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