mediaplayer.cpp revision 0662067b06658a4a56a8416c676f6cce8ccddb53
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 <gui/SurfaceTextureClient.h>
31
32#include <media/mediaplayer.h>
33#include <media/AudioTrack.h>
34
35#include <surfaceflinger/Surface.h>
36
37#include <binder/MemoryBase.h>
38
39#include <utils/KeyedVector.h>
40#include <utils/String8.h>
41
42#include <system/audio.h>
43#include <system/window.h>
44
45namespace android {
46
47MediaPlayer::MediaPlayer()
48{
49    LOGV("constructor");
50    mListener = NULL;
51    mCookie = NULL;
52    mDuration = -1;
53    mStreamType = AUDIO_STREAM_MUSIC;
54    mCurrentPosition = -1;
55    mSeekPosition = -1;
56    mCurrentState = MEDIA_PLAYER_IDLE;
57    mPrepareSync = false;
58    mPrepareStatus = NO_ERROR;
59    mLoop = false;
60    mLeftVolume = mRightVolume = 1.0;
61    mVideoWidth = mVideoHeight = 0;
62    mLockThreadId = 0;
63    mAudioSessionId = AudioSystem::newAudioSessionId();
64    AudioSystem::acquireAudioSessionId(mAudioSessionId);
65    mSendLevel = 0;
66}
67
68MediaPlayer::~MediaPlayer()
69{
70    LOGV("destructor");
71    AudioSystem::releaseAudioSessionId(mAudioSessionId);
72    disconnect();
73    IPCThreadState::self()->flushCommands();
74}
75
76void MediaPlayer::disconnect()
77{
78    LOGV("disconnect");
79    sp<IMediaPlayer> p;
80    {
81        Mutex::Autolock _l(mLock);
82        p = mPlayer;
83        mPlayer.clear();
84    }
85
86    if (p != 0) {
87        p->disconnect();
88    }
89
90    disconnectNativeWindow();
91}
92
93// always call with lock held
94void MediaPlayer::clear_l()
95{
96    mDuration = -1;
97    mCurrentPosition = -1;
98    mSeekPosition = -1;
99    mVideoWidth = mVideoHeight = 0;
100}
101
102status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
103{
104    LOGV("setListener");
105    Mutex::Autolock _l(mLock);
106    mListener = listener;
107    return NO_ERROR;
108}
109
110
111status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
112{
113    status_t err = UNKNOWN_ERROR;
114    sp<IMediaPlayer> p;
115    { // scope for the lock
116        Mutex::Autolock _l(mLock);
117
118        if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
119                (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
120            LOGE("attachNewPlayer called in state %d", mCurrentState);
121            return INVALID_OPERATION;
122        }
123
124        clear_l();
125        p = mPlayer;
126        mPlayer = player;
127        if (player != 0) {
128            mCurrentState = MEDIA_PLAYER_INITIALIZED;
129            err = NO_ERROR;
130        } else {
131            LOGE("Unable to to create media player");
132        }
133    }
134
135    if (p != 0) {
136        p->disconnect();
137    }
138
139    return err;
140}
141
142status_t MediaPlayer::setDataSource(
143        const char *url, const KeyedVector<String8, String8> *headers)
144{
145    LOGV("setDataSource(%s)", url);
146    status_t err = BAD_VALUE;
147    if (url != NULL) {
148        const sp<IMediaPlayerService>& service(getMediaPlayerService());
149        if (service != 0) {
150            sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
151            if (NO_ERROR != player->setDataSource(url, headers)) {
152                player.clear();
153            }
154            err = attachNewPlayer(player);
155        }
156    }
157    return err;
158}
159
160status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
161{
162    LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
163    status_t err = UNKNOWN_ERROR;
164    const sp<IMediaPlayerService>& service(getMediaPlayerService());
165    if (service != 0) {
166        sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
167        if (NO_ERROR != player->setDataSource(fd, offset, length)) {
168            player.clear();
169        }
170        err = attachNewPlayer(player);
171    }
172    return err;
173}
174
175status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
176{
177    LOGV("setDataSource");
178    status_t err = UNKNOWN_ERROR;
179    const sp<IMediaPlayerService>& service(getMediaPlayerService());
180    if (service != 0) {
181        sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
182        if (NO_ERROR != player->setDataSource(source)) {
183            player.clear();
184        }
185        err = attachNewPlayer(player);
186    }
187    return err;
188}
189
190status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
191{
192    Mutex::Autolock _l(mLock);
193    const bool hasBeenInitialized =
194            (mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
195            ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
196    if ((mPlayer != NULL) && hasBeenInitialized) {
197         LOGV("invoke %d", request.dataSize());
198         return  mPlayer->invoke(request, reply);
199    }
200    LOGE("invoke failed: wrong state %X", mCurrentState);
201    return INVALID_OPERATION;
202}
203
204status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
205{
206    LOGD("setMetadataFilter");
207    Mutex::Autolock lock(mLock);
208    if (mPlayer == NULL) {
209        return NO_INIT;
210    }
211    return mPlayer->setMetadataFilter(filter);
212}
213
214status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
215{
216    LOGD("getMetadata");
217    Mutex::Autolock lock(mLock);
218    if (mPlayer == NULL) {
219        return NO_INIT;
220    }
221    return mPlayer->getMetadata(update_only, apply_filter, metadata);
222}
223
224void MediaPlayer::disconnectNativeWindow() {
225    if (mConnectedWindow != NULL) {
226        status_t err = native_window_api_disconnect(mConnectedWindow.get(),
227                NATIVE_WINDOW_API_MEDIA);
228
229        if (err != OK) {
230            LOGW("native_window_api_disconnect returned an error: %s (%d)",
231                    strerror(-err), err);
232        }
233    }
234    mConnectedWindow.clear();
235}
236
237status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
238{
239    LOGV("setVideoSurface");
240    Mutex::Autolock _l(mLock);
241    if (mPlayer == 0) return NO_INIT;
242
243    sp<IBinder> binder(surface == NULL ? NULL : surface->asBinder());
244    if (mConnectedWindowBinder == binder) {
245        return OK;
246    }
247
248    if (surface != NULL) {
249        status_t err = native_window_api_connect(surface.get(),
250                NATIVE_WINDOW_API_MEDIA);
251
252        if (err != OK) {
253            LOGE("setVideoSurface failed: %d", err);
254            // Note that we must do the reset before disconnecting from the ANW.
255            // Otherwise queue/dequeue calls could be made on the disconnected
256            // ANW, which may result in errors.
257            reset_l();
258
259            disconnectNativeWindow();
260
261            return err;
262        }
263    }
264
265    // Note that we must set the player's new surface before disconnecting the
266    // old one.  Otherwise queue/dequeue calls could be made on the disconnected
267    // ANW, which may result in errors.
268    status_t err = mPlayer->setVideoSurface(surface);
269
270    disconnectNativeWindow();
271
272    mConnectedWindow = surface;
273
274    if (err == OK) {
275        mConnectedWindowBinder = binder;
276    } else {
277        disconnectNativeWindow();
278    }
279
280    return err;
281}
282
283status_t MediaPlayer::setVideoSurfaceTexture(
284        const sp<ISurfaceTexture>& surfaceTexture)
285{
286    LOGV("setVideoSurfaceTexture");
287    Mutex::Autolock _l(mLock);
288    if (mPlayer == 0) return NO_INIT;
289
290    sp<IBinder> binder(surfaceTexture == NULL ? NULL :
291            surfaceTexture->asBinder());
292    if (mConnectedWindowBinder == binder) {
293        return OK;
294    }
295
296    sp<ANativeWindow> anw;
297    if (surfaceTexture != NULL) {
298        anw = new SurfaceTextureClient(surfaceTexture);
299        status_t err = native_window_api_connect(anw.get(),
300                NATIVE_WINDOW_API_MEDIA);
301
302        if (err != OK) {
303            LOGE("setVideoSurfaceTexture failed: %d", err);
304            // Note that we must do the reset before disconnecting from the ANW.
305            // Otherwise queue/dequeue calls could be made on the disconnected
306            // ANW, which may result in errors.
307            reset_l();
308
309            disconnectNativeWindow();
310
311            return err;
312        }
313    }
314
315    // Note that we must set the player's new SurfaceTexture before
316    // disconnecting the old one.  Otherwise queue/dequeue calls could be made
317    // on the disconnected ANW, which may result in errors.
318    status_t err = mPlayer->setVideoSurfaceTexture(surfaceTexture);
319
320    disconnectNativeWindow();
321
322    mConnectedWindow = anw;
323
324    if (err == OK) {
325        mConnectedWindowBinder = binder;
326    } else {
327        disconnectNativeWindow();
328    }
329
330    return err;
331}
332
333// must call with lock held
334status_t MediaPlayer::prepareAsync_l()
335{
336    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
337        mPlayer->setAudioStreamType(mStreamType);
338        mCurrentState = MEDIA_PLAYER_PREPARING;
339        return mPlayer->prepareAsync();
340    }
341    LOGE("prepareAsync called in state %d", mCurrentState);
342    return INVALID_OPERATION;
343}
344
345// TODO: In case of error, prepareAsync provides the caller with 2 error codes,
346// one defined in the Android framework and one provided by the implementation
347// that generated the error. The sync version of prepare returns only 1 error
348// code.
349status_t MediaPlayer::prepare()
350{
351    LOGV("prepare");
352    Mutex::Autolock _l(mLock);
353    mLockThreadId = getThreadId();
354    if (mPrepareSync) {
355        mLockThreadId = 0;
356        return -EALREADY;
357    }
358    mPrepareSync = true;
359    status_t ret = prepareAsync_l();
360    if (ret != NO_ERROR) {
361        mLockThreadId = 0;
362        return ret;
363    }
364
365    if (mPrepareSync) {
366        mSignal.wait(mLock);  // wait for prepare done
367        mPrepareSync = false;
368    }
369    LOGV("prepare complete - status=%d", mPrepareStatus);
370    mLockThreadId = 0;
371    return mPrepareStatus;
372}
373
374status_t MediaPlayer::prepareAsync()
375{
376    LOGV("prepareAsync");
377    Mutex::Autolock _l(mLock);
378    return prepareAsync_l();
379}
380
381status_t MediaPlayer::start()
382{
383    LOGV("start");
384    Mutex::Autolock _l(mLock);
385    if (mCurrentState & MEDIA_PLAYER_STARTED)
386        return NO_ERROR;
387    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
388                    MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
389        mPlayer->setLooping(mLoop);
390        mPlayer->setVolume(mLeftVolume, mRightVolume);
391        mPlayer->setAuxEffectSendLevel(mSendLevel);
392        mCurrentState = MEDIA_PLAYER_STARTED;
393        status_t ret = mPlayer->start();
394        if (ret != NO_ERROR) {
395            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
396        } else {
397            if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
398                LOGV("playback completed immediately following start()");
399            }
400        }
401        return ret;
402    }
403    LOGE("start called in state %d", mCurrentState);
404    return INVALID_OPERATION;
405}
406
407status_t MediaPlayer::stop()
408{
409    LOGV("stop");
410    Mutex::Autolock _l(mLock);
411    if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
412    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
413                    MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
414        status_t ret = mPlayer->stop();
415        if (ret != NO_ERROR) {
416            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
417        } else {
418            mCurrentState = MEDIA_PLAYER_STOPPED;
419        }
420        return ret;
421    }
422    LOGE("stop called in state %d", mCurrentState);
423    return INVALID_OPERATION;
424}
425
426status_t MediaPlayer::pause()
427{
428    LOGV("pause");
429    Mutex::Autolock _l(mLock);
430    if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))
431        return NO_ERROR;
432    if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
433        status_t ret = mPlayer->pause();
434        if (ret != NO_ERROR) {
435            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
436        } else {
437            mCurrentState = MEDIA_PLAYER_PAUSED;
438        }
439        return ret;
440    }
441    LOGE("pause called in state %d", mCurrentState);
442    return INVALID_OPERATION;
443}
444
445bool MediaPlayer::isPlaying()
446{
447    Mutex::Autolock _l(mLock);
448    if (mPlayer != 0) {
449        bool temp = false;
450        mPlayer->isPlaying(&temp);
451        LOGV("isPlaying: %d", temp);
452        if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
453            LOGE("internal/external state mismatch corrected");
454            mCurrentState = MEDIA_PLAYER_PAUSED;
455        }
456        return temp;
457    }
458    LOGV("isPlaying: no active player");
459    return false;
460}
461
462status_t MediaPlayer::getVideoWidth(int *w)
463{
464    LOGV("getVideoWidth");
465    Mutex::Autolock _l(mLock);
466    if (mPlayer == 0) return INVALID_OPERATION;
467    *w = mVideoWidth;
468    return NO_ERROR;
469}
470
471status_t MediaPlayer::getVideoHeight(int *h)
472{
473    LOGV("getVideoHeight");
474    Mutex::Autolock _l(mLock);
475    if (mPlayer == 0) return INVALID_OPERATION;
476    *h = mVideoHeight;
477    return NO_ERROR;
478}
479
480status_t MediaPlayer::getCurrentPosition(int *msec)
481{
482    LOGV("getCurrentPosition");
483    Mutex::Autolock _l(mLock);
484    if (mPlayer != 0) {
485        if (mCurrentPosition >= 0) {
486            LOGV("Using cached seek position: %d", mCurrentPosition);
487            *msec = mCurrentPosition;
488            return NO_ERROR;
489        }
490        return mPlayer->getCurrentPosition(msec);
491    }
492    return INVALID_OPERATION;
493}
494
495status_t MediaPlayer::getDuration_l(int *msec)
496{
497    LOGV("getDuration");
498    bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
499    if (mPlayer != 0 && isValidState) {
500        status_t ret = NO_ERROR;
501        if (mDuration <= 0)
502            ret = mPlayer->getDuration(&mDuration);
503        if (msec)
504            *msec = mDuration;
505        return ret;
506    }
507    LOGE("Attempt to call getDuration without a valid mediaplayer");
508    return INVALID_OPERATION;
509}
510
511status_t MediaPlayer::getDuration(int *msec)
512{
513    Mutex::Autolock _l(mLock);
514    return getDuration_l(msec);
515}
516
517status_t MediaPlayer::seekTo_l(int msec)
518{
519    LOGV("seekTo %d", msec);
520    if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
521        if ( msec < 0 ) {
522            LOGW("Attempt to seek to invalid position: %d", msec);
523            msec = 0;
524        } else if ((mDuration > 0) && (msec > mDuration)) {
525            LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
526            msec = mDuration;
527        }
528        // cache duration
529        mCurrentPosition = msec;
530        if (mSeekPosition < 0) {
531            getDuration_l(NULL);
532            mSeekPosition = msec;
533            return mPlayer->seekTo(msec);
534        }
535        else {
536            LOGV("Seek in progress - queue up seekTo[%d]", msec);
537            return NO_ERROR;
538        }
539    }
540    LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
541    return INVALID_OPERATION;
542}
543
544status_t MediaPlayer::seekTo(int msec)
545{
546    mLockThreadId = getThreadId();
547    Mutex::Autolock _l(mLock);
548    status_t result = seekTo_l(msec);
549    mLockThreadId = 0;
550
551    return result;
552}
553
554status_t MediaPlayer::reset_l()
555{
556    mLoop = false;
557    if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
558    mPrepareSync = false;
559    if (mPlayer != 0) {
560        status_t ret = mPlayer->reset();
561        if (ret != NO_ERROR) {
562            LOGE("reset() failed with return code (%d)", ret);
563            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
564        } else {
565            mCurrentState = MEDIA_PLAYER_IDLE;
566        }
567        // setDataSource has to be called again to create a
568        // new mediaplayer.
569        mPlayer = 0;
570        return ret;
571    }
572    clear_l();
573    return NO_ERROR;
574}
575
576status_t MediaPlayer::reset()
577{
578    LOGV("reset");
579    Mutex::Autolock _l(mLock);
580    return reset_l();
581}
582
583status_t MediaPlayer::setAudioStreamType(int type)
584{
585    LOGV("MediaPlayer::setAudioStreamType");
586    Mutex::Autolock _l(mLock);
587    if (mStreamType == type) return NO_ERROR;
588    if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
589                MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
590        // Can't change the stream type after prepare
591        LOGE("setAudioStream called in state %d", mCurrentState);
592        return INVALID_OPERATION;
593    }
594    // cache
595    mStreamType = type;
596    return OK;
597}
598
599status_t MediaPlayer::setLooping(int loop)
600{
601    LOGV("MediaPlayer::setLooping");
602    Mutex::Autolock _l(mLock);
603    mLoop = (loop != 0);
604    if (mPlayer != 0) {
605        return mPlayer->setLooping(loop);
606    }
607    return OK;
608}
609
610bool MediaPlayer::isLooping() {
611    LOGV("isLooping");
612    Mutex::Autolock _l(mLock);
613    if (mPlayer != 0) {
614        return mLoop;
615    }
616    LOGV("isLooping: no active player");
617    return false;
618}
619
620status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
621{
622    LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
623    Mutex::Autolock _l(mLock);
624    mLeftVolume = leftVolume;
625    mRightVolume = rightVolume;
626    if (mPlayer != 0) {
627        return mPlayer->setVolume(leftVolume, rightVolume);
628    }
629    return OK;
630}
631
632status_t MediaPlayer::setAudioSessionId(int sessionId)
633{
634    LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
635    Mutex::Autolock _l(mLock);
636    if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
637        LOGE("setAudioSessionId called in state %d", mCurrentState);
638        return INVALID_OPERATION;
639    }
640    if (sessionId < 0) {
641        return BAD_VALUE;
642    }
643    if (sessionId != mAudioSessionId) {
644      AudioSystem::releaseAudioSessionId(mAudioSessionId);
645      AudioSystem::acquireAudioSessionId(sessionId);
646      mAudioSessionId = sessionId;
647    }
648    return NO_ERROR;
649}
650
651int MediaPlayer::getAudioSessionId()
652{
653    Mutex::Autolock _l(mLock);
654    return mAudioSessionId;
655}
656
657status_t MediaPlayer::setAuxEffectSendLevel(float level)
658{
659    LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
660    Mutex::Autolock _l(mLock);
661    mSendLevel = level;
662    if (mPlayer != 0) {
663        return mPlayer->setAuxEffectSendLevel(level);
664    }
665    return OK;
666}
667
668status_t MediaPlayer::attachAuxEffect(int effectId)
669{
670    LOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
671    Mutex::Autolock _l(mLock);
672    if (mPlayer == 0 ||
673        (mCurrentState & MEDIA_PLAYER_IDLE) ||
674        (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
675        LOGE("attachAuxEffect called in state %d", mCurrentState);
676        return INVALID_OPERATION;
677    }
678
679    return mPlayer->attachAuxEffect(effectId);
680}
681
682status_t MediaPlayer::setParameter(int key, const Parcel& request)
683{
684    LOGV("MediaPlayer::setParameter(%d)", key);
685    Mutex::Autolock _l(mLock);
686    if (mPlayer != NULL) {
687        return  mPlayer->setParameter(key, request);
688    }
689    LOGV("setParameter: no active player");
690    return INVALID_OPERATION;
691}
692
693status_t MediaPlayer::getParameter(int key, Parcel *reply)
694{
695    LOGV("MediaPlayer::getParameter(%d)", key);
696    Mutex::Autolock _l(mLock);
697    if (mPlayer != NULL) {
698         return  mPlayer->getParameter(key, reply);
699    }
700    LOGV("getParameter: no active player");
701    return INVALID_OPERATION;
702}
703
704void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
705{
706    LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
707    bool send = true;
708    bool locked = false;
709
710    // TODO: In the future, we might be on the same thread if the app is
711    // running in the same process as the media server. In that case,
712    // this will deadlock.
713    //
714    // The threadId hack below works around this for the care of prepare
715    // and seekTo within the same process.
716    // FIXME: Remember, this is a hack, it's not even a hack that is applied
717    // consistently for all use-cases, this needs to be revisited.
718     if (mLockThreadId != getThreadId()) {
719        mLock.lock();
720        locked = true;
721    }
722
723    // Allows calls from JNI in idle state to notify errors
724    if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
725        LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
726        if (locked) mLock.unlock();   // release the lock when done.
727        return;
728    }
729
730    switch (msg) {
731    case MEDIA_NOP: // interface test message
732        break;
733    case MEDIA_PREPARED:
734        LOGV("prepared");
735        mCurrentState = MEDIA_PLAYER_PREPARED;
736        if (mPrepareSync) {
737            LOGV("signal application thread");
738            mPrepareSync = false;
739            mPrepareStatus = NO_ERROR;
740            mSignal.signal();
741        }
742        break;
743    case MEDIA_PLAYBACK_COMPLETE:
744        LOGV("playback complete");
745        if (mCurrentState == MEDIA_PLAYER_IDLE) {
746            LOGE("playback complete in idle state");
747        }
748        if (!mLoop) {
749            mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
750        }
751        break;
752    case MEDIA_ERROR:
753        // Always log errors.
754        // ext1: Media framework error code.
755        // ext2: Implementation dependant error code.
756        LOGE("error (%d, %d)", ext1, ext2);
757        mCurrentState = MEDIA_PLAYER_STATE_ERROR;
758        if (mPrepareSync)
759        {
760            LOGV("signal application thread");
761            mPrepareSync = false;
762            mPrepareStatus = ext1;
763            mSignal.signal();
764            send = false;
765        }
766        break;
767    case MEDIA_INFO:
768        // ext1: Media framework error code.
769        // ext2: Implementation dependant error code.
770        if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
771            LOGW("info/warning (%d, %d)", ext1, ext2);
772        }
773        break;
774    case MEDIA_SEEK_COMPLETE:
775        LOGV("Received seek complete");
776        if (mSeekPosition != mCurrentPosition) {
777            LOGV("Executing queued seekTo(%d)", mSeekPosition);
778            mSeekPosition = -1;
779            seekTo_l(mCurrentPosition);
780        }
781        else {
782            LOGV("All seeks complete - return to regularly scheduled program");
783            mCurrentPosition = mSeekPosition = -1;
784        }
785        break;
786    case MEDIA_BUFFERING_UPDATE:
787        LOGV("buffering %d", ext1);
788        break;
789    case MEDIA_SET_VIDEO_SIZE:
790        LOGV("New video size %d x %d", ext1, ext2);
791        mVideoWidth = ext1;
792        mVideoHeight = ext2;
793        break;
794    case MEDIA_TIMED_TEXT:
795        LOGV("Received timed text message");
796        break;
797    default:
798        LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
799        break;
800    }
801
802    sp<MediaPlayerListener> listener = mListener;
803    if (locked) mLock.unlock();
804
805    // this prevents re-entrant calls into client code
806    if ((listener != 0) && send) {
807        Mutex::Autolock _l(mNotifyLock);
808        LOGV("callback application");
809        listener->notify(msg, ext1, ext2, obj);
810        LOGV("back from callback");
811    }
812}
813
814/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
815{
816    LOGV("decode(%s)", url);
817    sp<IMemory> p;
818    const sp<IMediaPlayerService>& service = getMediaPlayerService();
819    if (service != 0) {
820        p = service->decode(url, pSampleRate, pNumChannels, pFormat);
821    } else {
822        LOGE("Unable to locate media service");
823    }
824    return p;
825
826}
827
828void MediaPlayer::died()
829{
830    LOGV("died");
831    notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
832}
833
834/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
835{
836    LOGV("decode(%d, %lld, %lld)", fd, offset, length);
837    sp<IMemory> p;
838    const sp<IMediaPlayerService>& service = getMediaPlayerService();
839    if (service != 0) {
840        p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
841    } else {
842        LOGE("Unable to locate media service");
843    }
844    return p;
845
846}
847
848}; // namespace android
849