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