20cb94eeb5
MediaPlayer.java has 3 new methods: * newRequest creates a Parcel that can be used to send data to the native player using invoke. * invoke issues synchronous calls to the native player using opaque parcels for the request and reply. IMediaPlayer.h has 1 new abstract method: * invoke The Midi and Vorbis players have a stub for these. So far only PV makes use of that new feature. To avoid any copy overhead, the JNI interface uses Parcel as a java object (no serialization/copy happens at the JNI layer). The remote interface token is inserted when the Parcel is constructed in java. That way the parcel is already routable when it reaches IMediaPlayer.cpp (proxy). No extra copy is needed there.
206 lines
7.6 KiB
C++
206 lines
7.6 KiB
C++
/*
|
|
* Copyright (C) 2007 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef ANDROID_MEDIAPLAYER_H
|
|
#define ANDROID_MEDIAPLAYER_H
|
|
|
|
#include <binder/IMemory.h>
|
|
#include <ui/Surface.h>
|
|
#include <media/IMediaPlayerClient.h>
|
|
#include <media/IMediaPlayer.h>
|
|
#include <media/IMediaPlayerService.h>
|
|
#include <utils/SortedVector.h>
|
|
|
|
namespace android {
|
|
|
|
enum media_event_type {
|
|
MEDIA_NOP = 0, // interface test message
|
|
MEDIA_PREPARED = 1,
|
|
MEDIA_PLAYBACK_COMPLETE = 2,
|
|
MEDIA_BUFFERING_UPDATE = 3,
|
|
MEDIA_SEEK_COMPLETE = 4,
|
|
MEDIA_SET_VIDEO_SIZE = 5,
|
|
MEDIA_ERROR = 100,
|
|
MEDIA_INFO = 200,
|
|
};
|
|
|
|
// Generic error codes for the media player framework. Errors are fatal, the
|
|
// playback must abort.
|
|
//
|
|
// Errors are communicated back to the client using the
|
|
// MediaPlayerListener::notify method defined below.
|
|
// In this situation, 'notify' is invoked with the following:
|
|
// 'msg' is set to MEDIA_ERROR.
|
|
// 'ext1' should be a value from the enum media_error_type.
|
|
// 'ext2' contains an implementation dependant error code to provide
|
|
// more details. Should default to 0 when not used.
|
|
//
|
|
// The codes are distributed as follow:
|
|
// 0xx: Reserved
|
|
// 1xx: Android Player errors. Something went wrong inside the MediaPlayer.
|
|
// 2xx: Media errors (e.g Codec not supported). There is a problem with the
|
|
// media itself.
|
|
// 3xx: Runtime errors. Some extraordinary condition arose making the playback
|
|
// impossible.
|
|
//
|
|
enum media_error_type {
|
|
// 0xx
|
|
MEDIA_ERROR_UNKNOWN = 1,
|
|
// 1xx
|
|
MEDIA_ERROR_SERVER_DIED = 100,
|
|
// 2xx
|
|
MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200,
|
|
// 3xx
|
|
};
|
|
|
|
|
|
// Info and warning codes for the media player framework. These are non fatal,
|
|
// the playback is going on but there might be some user visible issues.
|
|
//
|
|
// Info and warning messages are communicated back to the client using the
|
|
// MediaPlayerListener::notify method defined below. In this situation,
|
|
// 'notify' is invoked with the following:
|
|
// 'msg' is set to MEDIA_INFO.
|
|
// 'ext1' should be a value from the enum media_info_type.
|
|
// 'ext2' contains an implementation dependant error code to provide
|
|
// more details. Should default to 0 when not used.
|
|
//
|
|
// The codes are distributed as follow:
|
|
// 0xx: Reserved
|
|
// 7xx: Android Player info/warning (e.g player lagging behind.)
|
|
// 8xx: Media info/warning (e.g media badly interleaved.)
|
|
//
|
|
enum media_info_type {
|
|
// 0xx
|
|
MEDIA_INFO_UNKNOWN = 1,
|
|
// 7xx
|
|
// The video is too complex for the decoder: it can't decode frames fast
|
|
// enough. Possibly only the audio plays fine at this stage.
|
|
MEDIA_INFO_VIDEO_TRACK_LAGGING = 700,
|
|
// 8xx
|
|
// Bad interleaving means that a media has been improperly interleaved or not
|
|
// interleaved at all, e.g has all the video samples first then all the audio
|
|
// ones. Video is playing but a lot of disk seek may be happening.
|
|
MEDIA_INFO_BAD_INTERLEAVING = 800,
|
|
// The media is not seekable (e.g live stream).
|
|
MEDIA_INFO_NOT_SEEKABLE = 801,
|
|
};
|
|
|
|
|
|
|
|
enum media_player_states {
|
|
MEDIA_PLAYER_STATE_ERROR = 0,
|
|
MEDIA_PLAYER_IDLE = 1 << 0,
|
|
MEDIA_PLAYER_INITIALIZED = 1 << 1,
|
|
MEDIA_PLAYER_PREPARING = 1 << 2,
|
|
MEDIA_PLAYER_PREPARED = 1 << 3,
|
|
MEDIA_PLAYER_STARTED = 1 << 4,
|
|
MEDIA_PLAYER_PAUSED = 1 << 5,
|
|
MEDIA_PLAYER_STOPPED = 1 << 6,
|
|
MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ref-counted object for callbacks
|
|
class MediaPlayerListener: virtual public RefBase
|
|
{
|
|
public:
|
|
virtual void notify(int msg, int ext1, int ext2) = 0;
|
|
};
|
|
|
|
class MediaPlayer : public BnMediaPlayerClient
|
|
{
|
|
public:
|
|
MediaPlayer();
|
|
~MediaPlayer();
|
|
void onFirstRef();
|
|
void disconnect();
|
|
status_t setDataSource(const char *url);
|
|
status_t setDataSource(int fd, int64_t offset, int64_t length);
|
|
status_t setVideoSurface(const sp<Surface>& surface);
|
|
status_t setListener(const sp<MediaPlayerListener>& listener);
|
|
status_t prepare();
|
|
status_t prepareAsync();
|
|
status_t start();
|
|
status_t stop();
|
|
status_t pause();
|
|
bool isPlaying();
|
|
status_t getVideoWidth(int *w);
|
|
status_t getVideoHeight(int *h);
|
|
status_t seekTo(int msec);
|
|
status_t getCurrentPosition(int *msec);
|
|
status_t getDuration(int *msec);
|
|
status_t reset();
|
|
status_t setAudioStreamType(int type);
|
|
status_t setLooping(int loop);
|
|
bool isLooping();
|
|
status_t setVolume(float leftVolume, float rightVolume);
|
|
void notify(int msg, int ext1, int ext2);
|
|
static sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
|
|
static sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
|
|
status_t invoke(const Parcel& request, Parcel *reply);
|
|
private:
|
|
void clear_l();
|
|
status_t seekTo_l(int msec);
|
|
status_t prepareAsync_l();
|
|
status_t getDuration_l(int *msec);
|
|
status_t setDataSource(const sp<IMediaPlayer>& player);
|
|
|
|
static const sp<IMediaPlayerService>& getMediaPlayerService();
|
|
static void addObitRecipient(const wp<MediaPlayer>& recipient);
|
|
static void removeObitRecipient(const wp<MediaPlayer>& recipient);
|
|
|
|
class DeathNotifier: public IBinder::DeathRecipient
|
|
{
|
|
public:
|
|
DeathNotifier() {}
|
|
virtual ~DeathNotifier();
|
|
|
|
virtual void binderDied(const wp<IBinder>& who);
|
|
};
|
|
|
|
sp<IMediaPlayer> mPlayer;
|
|
thread_id_t mLockThreadId;
|
|
Mutex mLock;
|
|
Mutex mNotifyLock;
|
|
Condition mSignal;
|
|
sp<MediaPlayerListener> mListener;
|
|
void* mCookie;
|
|
media_player_states mCurrentState;
|
|
int mDuration;
|
|
int mCurrentPosition;
|
|
int mSeekPosition;
|
|
bool mPrepareSync;
|
|
status_t mPrepareStatus;
|
|
int mStreamType;
|
|
bool mLoop;
|
|
float mLeftVolume;
|
|
float mRightVolume;
|
|
int mVideoWidth;
|
|
int mVideoHeight;
|
|
|
|
friend class DeathNotifier;
|
|
|
|
static Mutex sServiceLock;
|
|
static sp<IMediaPlayerService> sMediaPlayerService;
|
|
static sp<DeathNotifier> sDeathNotifier;
|
|
static SortedVector< wp<MediaPlayer> > sObitRecipients;
|
|
};
|
|
|
|
}; // namespace android
|
|
|
|
#endif // ANDROID_MEDIAPLAYER_H
|