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