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