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