此文章作为在学习media过程中的记录,仅代表当下的理解和感悟。
1. 在main()函数中初始化 MediaPlayerService /frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
InitializeIcuOrDie();
MediaPlayerService::instantiate(); //实例化 MediaPlayerService --》2
ResourceManagerService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
2. MediaPlayerService::instantiate() 方法的实现 /frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService()); //创建MediaPlayerService 并添加至servicemanager ---->3
}
3. MediaPlayerService 的构造函数
MediaPlayerService::MediaPlayerService()
{
ALOGV("MediaPlayerService created");
mNextConnId = 1;
MediaPlayerFactory::registerBuiltinFactories(); //初始化了MediaPlayerFactory----》4
}
4.MediaPlayerFactory 是播放器的制造工厂,看下它的registerBuiltinFactories()做了什么:
void MediaPlayerFactory::registerBuiltinFactories() {
Mutex::Autolock lock_(&sLock);
if (sInitComplete)
return;
IFactory* factory = new NuPlayerFactory(); //创建NuPlayer的工厂
if (registerFactory_l(factory, NU_PLAYER) != OK)
delete factory;
factory = new TestPlayerFactory(); //创建TestPlayer的工厂
if (registerFactory_l(factory, TEST_PLAYER) != OK)
delete factory;
sInitComplete = true;
}
status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
player_type type) {
if (NULL == factory) {
ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
" NULL.", type);
return BAD_VALUE;
}
//如果map中已经存在此类型的播放器工厂,直接返回已经存在code
if (sFactoryMap.indexOfKey(type) >= 0) {
ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
" already registered.", type);
return ALREADY_EXISTS;
}
//将类型和播放器工厂以键值对的方式存入sFactoryMap 中
if (sFactoryMap.add(type, factory) < 0) {
ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
" to map.", type);
return UNKNOWN_ERROR;
}
return OK;
}
总结以上,在main执行完之后,MediaPlayerService 被实例化并加入ServiceManager,播放器工厂被实例化并存储
5.接下来看一下MediaPlayerService的 接口IMediaPlayerService 位于:/frameworks/av/include/media/IMediaPlayerService.h
class IMediaPlayerService: public IInterface //继承了 IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerService);
virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName) = 0; //----》6 创建录音器
virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;//----》7 创建数据解析器
virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE) = 0;//----》8创建播放器
virtual sp<IMediaCodecList> getCodecList() const = 0;//----》11 获取解码器列表
// Connects to a remote display.
// 'iface' specifies the address of the local interface on which to listen for
// a connection from the remote display as an ip address and port number
// of the form "x.x.x.x:y". The media server should call back into the provided remote
// display client when display connection, disconnection or errors occur.
// The assumption is that at most one remote display will be connected to the
// provided interface at a time.
virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName,
const sp<IRemoteDisplayClient>& client, const String8& iface) = 0;
// codecs and audio devices usage tracking for the battery app
enum BatteryDataBits {
// tracking audio codec
kBatteryDataTrackAudio = 0x1,
// tracking video codec
kBatteryDataTrackVideo = 0x2,
// codec is started, otherwise codec is paused
kBatteryDataCodecStarted = 0x4,
// tracking decoder (for media player),
// otherwise tracking encoder (for media recorder)
kBatteryDataTrackDecoder = 0x8,
// start to play an audio on an audio device
kBatteryDataAudioFlingerStart = 0x10,
// stop/pause the audio playback
kBatteryDataAudioFlingerStop = 0x20,
// audio is rounted to speaker
kBatteryDataSpeakerOn = 0x40,
// audio is rounted to devices other than speaker
kBatteryDataOtherAudioDeviceOn = 0x80,
};
virtual void addBatteryData(uint32_t params) = 0;
virtual status_t pullBatteryData(Parcel* reply) = 0;
};
// ----------------------------------------------------------------------------
class BnMediaPlayerService: public BnInterface<IMediaPlayerService> //内部类 BnMediaPlayerService 又继承于 BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
}; // namespace android
目前对binder和C++都是一知半解,对IInterface和BnInterface暂不详述
其中,通过MediaPlayerService.h (位于 /frameworks/av/media/libmediaplayerservice/MediaPlayerService.h) 我们知道MediaPlayerService 继承了BnMediaPlayerService
也就是说MediaPlayerService 实现了 IMediaPlayerService接口所定义的方法,其中的关系还没有太搞清楚。
6.先来看一下sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName) 函数 ,在MediaPlayerService.cpp中实现
sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(const String16 &opPackageName)
{
pid_t pid = IPCThreadState::self()->getCallingPid();
sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid, opPackageName);//用于录音
wp<MediaRecorderClient> w = recorder;
Mutex::Autolock lock(mLock);
mMediaRecorderClients.add(w);
ALOGV("Create new media recorder client from pid %d", pid);
return recorder;
}
//MediaRecorderClient 的位置在 : /frameworks/av/media/libmediaplayerservice/MediaRecorderClient.h 中定义的,继承了BnMediaRecorder
7. sp<IMediaMetadataRetriever> createMetadataRetriever()
sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever()
{
pid_t pid = IPCThreadState::self()->getCallingPid();
sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
ALOGV("Create new media retriever from pid %d", pid);
return retriever;
}
// MetadataRetriever 用于获取多媒体文件的元信息metadata, 如 名称,专辑等,其中MetadataRetrieverClient 位于/frameworks/av/media/libmediaplayerservice/MetadataRetrieverClient.h
MetadataRetrieverClient.cpp 实现了 IMediaMetadataRetriever 的接口
8.sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE) 创建播放器的函数
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId)
{
pid_t pid = IPCThreadState::self()->getCallingPid();
int32_t connId = android_atomic_inc(&mNextConnId);
sp<Client> c = new Client(
this, pid, connId, client, audioSessionId,
IPCThreadState::self()->getCallingUid()); //Client是IMediaPlayer的代理----》9
ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
IPCThreadState::self()->getCallingUid());
wp<Client> w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}
9. Client的来历:是在MediaPlayerService.h中定义的内部类,继承了BnMediaPlayer ,声明了一个播放器的全部方法
class Client : public BnMediaPlayer { //BnMediaPlayer 在IMediaPlayer.h中定义 ----》10
// IMediaPlayer interface
virtual void disconnect();
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer);
virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) override;
virtual status_t prepareAsync();
virtual status_t start();
virtual status_t stop();
virtual status_t pause();
virtual status_t isPlaying(bool* state);
virtual status_t setPlaybackSettings(const AudioPlaybackRate& rate);
virtual status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
virtual status_t setSyncSettings(const AVSyncSettings& rate, float videoFpsHint);
virtual status_t getSyncSettings(AVSyncSettings* rate /* nonnull */,
float* videoFps /* nonnull */);
virtual status_t seekTo(
int msec,
MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC);
virtual status_t getCurrentPosition(int* msec);
virtual status_t getDuration(int* msec);
virtual status_t reset();
virtual status_t notifyAt(int64_t mediaTimeUs);
virtual status_t setAudioStreamType(audio_stream_type_t type);
virtual status_t setLooping(int loop);
virtual status_t setVolume(float leftVolume, float rightVolume);
virtual status_t invoke(const Parcel& request, Parcel *reply);
virtual status_t setMetadataFilter(const Parcel& filter);
virtual status_t getMetadata(bool update_only,
bool apply_filter,
Parcel *reply);
virtual status_t setAuxEffectSendLevel(float level);
virtual status_t attachAuxEffect(int effectId);
virtual status_t setParameter(int key, const Parcel &request);
virtual status_t getParameter(int key, Parcel *reply);
virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint);
virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint);
virtual status_t setNextPlayer(const sp<IMediaPlayer>& player);
virtual media::VolumeShaper::Status applyVolumeShaper(
const sp<media::VolumeShaper::Configuration>& configuration,
const sp<media::VolumeShaper::Operation>& operation) override;
virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;
sp<MediaPlayerBase> createPlayer(player_type playerType);
virtual status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers);
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
virtual status_t setDataSource(const sp<IStreamSource> &source);
virtual status_t setDataSource(const sp<IDataSource> &source);
sp<MediaPlayerBase> setDataSource_pre(player_type playerType);
status_t setDataSource_post(const sp<MediaPlayerBase>& p,
status_t status);
void notify(int msg, int ext1, int ext2, const Parcel *obj);
pid_t pid() const { return mPid; }
virtual status_t dump(int fd, const Vector<String16>& args);
audio_session_t getAudioSessionId() { return mAudioSessionId; }
// Modular DRM
virtual status_t prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId);
virtual status_t releaseDrm();
// AudioRouting
virtual status_t setOutputDevice(audio_port_handle_t deviceId);
virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
virtual status_t enableAudioDeviceCallback(bool enabled);
private:
class ServiceDeathNotifier:
public IBinder::DeathRecipient,
public ::android::hardware::hidl_death_recipient
{
public:
ServiceDeathNotifier(
const sp<IBinder>& service,
const sp<MediaPlayerBase>& listener,
int which);
ServiceDeathNotifier(
const sp<IOmx>& omx,
const sp<MediaPlayerBase>& listener,
int which);
virtual ~ServiceDeathNotifier();
virtual void binderDied(const wp<IBinder>& who);
virtual void serviceDied(
uint64_t cookie,
const wp<::android::hidl::base::V1_0::IBase>& who);
void unlinkToDeath();
private:
int mWhich;
sp<IBinder> mService;
sp<IOmx> mOmx;
wp<MediaPlayerBase> mListener;
};
class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback
{
public:
AudioDeviceUpdatedNotifier(const sp<MediaPlayerBase>& listener) {
mListener = listener;
}
~AudioDeviceUpdatedNotifier() {}
virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
audio_port_handle_t deviceId);
private:
wp<MediaPlayerBase> mListener;
};
void clearDeathNotifiers_l();
friend class MediaPlayerService;
Client( const sp<MediaPlayerService>& service,
pid_t pid,
int32_t connId,
const sp<IMediaPlayerClient>& client,
audio_session_t audioSessionId,
uid_t uid);
Client();
virtual ~Client();
void deletePlayer();
sp<MediaPlayerBase> getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; }
// @param type Of the metadata to be tested.
// @return true if the metadata should be dropped according to
// the filters.
bool shouldDropMetadata(media::Metadata::Type type) const;
// Add a new element to the set of metadata updated. Noop if
// the element exists already.
// @param type Of the metadata to be recorded.
void addNewMetadataUpdate(media::Metadata::Type type);
// Disconnect from the currently connected ANativeWindow.
void disconnectNativeWindow_l();
status_t setAudioAttributes_l(const Parcel &request);
class Listener : public MediaPlayerBase::Listener {
public:
Listener(const wp<Client> &client) : mClient(client) {}
virtual ~Listener() {}
virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) {
sp<Client> client = mClient.promote();
if (client != NULL) {
client->notify(msg, ext1, ext2, obj);
}
}
private:
wp<Client> mClient;
};
mutable Mutex mLock;
sp<MediaPlayerBase> mPlayer;
sp<MediaPlayerService> mService;
sp<IMediaPlayerClient> mClient;
sp<AudioOutput> mAudioOutput;
pid_t mPid;
status_t mStatus;
bool mLoop;
int32_t mConnId;
audio_session_t mAudioSessionId;
audio_attributes_t * mAudioAttributes;
uid_t mUid;
sp<ANativeWindow> mConnectedWindow;
sp<IBinder> mConnectedWindowBinder;
struct sockaddr_in mRetransmitEndpoint;
bool mRetransmitEndpointValid;
sp<Client> mNextClient;
sp<MediaPlayerBase::Listener> mListener;
// Metadata filters.
media::Metadata::Filter mMetadataAllow; // protected by mLock
media::Metadata::Filter mMetadataDrop; // protected by mLock
// Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
// notification we try to update mMetadataUpdated which is a
// set: no duplicate.
// getMetadata clears this set.
media::Metadata::Filter mMetadataUpdated; // protected by mLock
sp<ServiceDeathNotifier> mExtractorDeathListener;
sp<ServiceDeathNotifier> mCodecDeathListener;
sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedListener;
#if CALLBACK_ANTAGONIZER
Antagonizer* mAntagonizer;
#endif
}; // Client
10.看一下IMediaPlayer.h /frameworks/av/media/libmedia/include/media/IMediaPlayer.h 定义了播放器的所有的接口
class IMediaPlayer: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayer);
virtual void disconnect() = 0;
virtual status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8>* headers) = 0;
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setDataSource(const sp<IStreamSource>& source) = 0;
virtual status_t setDataSource(const sp<IDataSource>& source) = 0;
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
virtual status_t getBufferingSettings(
BufferingSettings* buffering /* nonnull */) = 0;
virtual status_t setBufferingSettings(const BufferingSettings& buffering) = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t pause() = 0;
virtual status_t isPlaying(bool* state) = 0;
virtual status_t setPlaybackSettings(const AudioPlaybackRate& rate) = 0;
virtual status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) = 0;
virtual status_t setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) = 0;
virtual status_t getSyncSettings(AVSyncSettings* sync /* nonnull */,
float* videoFps /* nonnull */) = 0;
virtual status_t seekTo(
int msec,
MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) = 0;
virtual status_t getCurrentPosition(int* msec) = 0;
virtual status_t getDuration(int* msec) = 0;
virtual status_t notifyAt(int64_t mediaTimeUs) = 0;
virtual status_t reset() = 0;
virtual status_t setAudioStreamType(audio_stream_type_t type) = 0;
virtual status_t setLooping(int loop) = 0;
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
virtual status_t setAuxEffectSendLevel(float level) = 0;
virtual status_t attachAuxEffect(int effectId) = 0;
virtual status_t setParameter(int key, const Parcel& request) = 0;
virtual status_t getParameter(int key, Parcel* reply) = 0;
virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) = 0;
virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint) = 0;
virtual status_t setNextPlayer(const sp<IMediaPlayer>& next) = 0;
virtual media::VolumeShaper::Status applyVolumeShaper(
const sp<media::VolumeShaper::Configuration>& configuration,
const sp<media::VolumeShaper::Operation>& operation) = 0;
virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) = 0;
// Modular DRM
virtual status_t prepareDrm(const uint8_t uuid[16],
const Vector<uint8_t>& drmSessionId) = 0;
virtual status_t releaseDrm() = 0;
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
// @param request Parcel that must start with the media player
// interface token.
// @param[out] reply Parcel to hold the reply data. Cannot be null.
// @return OK if the invocation was made successfully.
virtual status_t invoke(const Parcel& request, Parcel *reply) = 0;
// Set a new metadata filter.
// @param filter A set of allow and drop rules serialized in a Parcel.
// @return OK if the invocation was made successfully.
virtual status_t setMetadataFilter(const Parcel& filter) = 0;
// Retrieve a set of metadata.
// @param update_only Include only the metadata that have changed
// since the last invocation of getMetadata.
// The set is built using the unfiltered
// notifications the native player sent to the
// MediaPlayerService during that period of
// time. If false, all the metadatas are considered.
// @param apply_filter If true, once the metadata set has been built based
// on the value update_only, the current filter is
// applied.
// @param[out] metadata On exit contains a set (possibly empty) of metadata.
// Valid only if the call returned OK.
// @return OK if the invocation was made successfully.
virtual status_t getMetadata(bool update_only,
bool apply_filter,
Parcel *metadata) = 0;
// AudioRouting
virtual status_t setOutputDevice(audio_port_handle_t deviceId) = 0;
virtual status_t getRoutedDeviceId(audio_port_handle_t *deviceId) = 0;
virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
};
// ----------------------------------------------------------------------------
class BnMediaPlayer: public BnInterface<IMediaPlayer> //内部类
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
11.回到MedaiPlayerService.cpp中 获取解码器列表方法 sp<IMediaCodecList> getCodecList()
sp<IMediaCodecList> MediaPlayerService::getCodecList() const {
return MediaCodecList::getLocalInstance();
}
///frameworks/av/media/libstagefright/MediaCodecList.cpp 中 getLocalInstance()
// static
sp<IMediaCodecList> MediaCodecList::getLocalInstance() {
Mutex::Autolock autoLock(sInitMutex);
if (sCodecList == nullptr) {
MediaCodecList *codecList = new MediaCodecList(GetBuilders());
if (codecList->initCheck() == OK) {
sCodecList = codecList;
if (isProfilingNeeded()) {
ALOGV("Codec profiling needed, will be run in separated thread.");
pthread_t profiler;
if (pthread_create(&profiler, nullptr, profilerThreadWrapper, nullptr) != 0) {
ALOGW("Failed to create thread for codec profiling.");
}
}
} else {
// failure to initialize may be temporary. retry on next call.
delete codecList;
}
}
return sCodecList;
}