frameworks/base/libmediaplayerservice/MediaPlayerService.cpp
因为工作的平台是mx51,所以分析的是mx51 10.3的代码,本文主要分析视频播放部分的代码,对于recorder和audio部分忽略掉。
Mediaplayer service是一个系统服务,Android 视频播放,录音录像,元数据获取等客户端应用与Mediaplayer service交互,由MediaPlayer Service实现视频的播放,录像,元数据获取等操作。
251 MediaPlayerService::MediaPlayerService()
252 {
253 LOGV("MediaPlayerService created");
254 mNextConnId = 1;
255 }
MediaPlayerService的构造函数
mNextConnId记录着client可用的connect id, 每创建一个client,mNextConnId都递增1,已经用过的connect id不能复用
sp MediaPlayerService::createMetadataRetriever(pid_t pid)
{
sp retriever = new MetadataRetrieverClient(pid);
LOGV("Create new media retriever from pid %d", pid);
return retriever;
}
创建一个Metadata retriever client,从类的名字我们可以猜测出这个函数是获取media文件的metadata。查看MetadataRetrieverClient的定义文件libmediaplayerservice/MetadataRetrieverClient.cpp,可以看到这个类提供了如下几种方法
286 sp MediaPlayerService::create(
287 pid_t pid, const sp& client, const char* url,
288 const KeyedVector *headers, int audioSessionId)
289 {
290 int32_t connId = android_atomic_inc(&mNextConnId);
291 sp c = new Client(this, pid, connId, client, audioSessionId);
292 LOGV("Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d",
293 connId, pid, url, connId, audioSessionId);
294 if (NO_ERROR != c->setDataSource(url, headers))
295 {
296 c.clear();
297 return c;
298 }
299 wp w = c;
300 Mutex::Autolock lock(mLock);
301 mClients.add(w);
302 return c;
303 }
为MediaPlayer Client创建一个对应的实体
@pid: client所在进程的id
@client: MediaPlayer client
@url: media 文件url
@headers: 未知
@audioSessionId:
301 mClients,是一个client对象数组,每一个新建的client都增加到这里面
305 sp MediaPlayerService::create(pid_t pid, const sp& client,
306 int fd, int64_t offset, int64_t length, int audioSessionId)
307 {
308 int32_t connId = android_atomic_inc(&mNextConnId);
309 sp c = new Client(this, pid, connId, client, audioSessionId);
310 LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d",
311 connId, pid, fd, offset, length, audioSessionId);
312 if (NO_ERROR != c->setDataSource(fd, offset, length)) {
313 c.clear();
314 } else {
315 wp w = c;
316 Mutex::Autolock lock(mLock);
317 mClients.add(w);
318 }
319 ::close(fd);
320 return c;
321 }
305 sp MediaPlayerService::create(pid_t pid, const sp& client,
306 int fd, int64_t offset, int64_t length, int audioSessionId)
307 {
308 int32_t connId = android_atomic_inc(&mNextConnId);
309 sp c = new Client(this, pid, connId, client, audioSessionId);
310 LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d",
311 connId, pid, fd, offset, length, audioSessionId);
312 if (NO_ERROR != c->setDataSource(fd, offset, length)) {
313 c.clear();
314 } else {
315 wp w = c;
316 Mutex::Autolock lock(mLock);
317 mClients.add(w);
318 }
319 ::close(fd);
320 return c;
321 }
@offset: 对android引入offset和length参数很迷惑,难道对media文件的操作不是从fd的起始位置开始吗?猜测可能确实存在这样的情况,media内容在另外一个文件容器中,这样就使用offset和length定义media内容的位置。
@length:
MediaPlayerService::Client::Client(const sp& service, pid_t pid,
int32_t connId, const sp& client, int audioSessionId)
{
LOGV("Client(%d) constructor", connId);
mPid = pid;
mConnId = connId;
mService = service;
mClient = client;
mLoop = false;
mStatus = NO_INIT;
mAudioSessionId = audioSessionId;
#if CALLBACK_ANTAGONIZER
LOGD("create Antagonizer");
mAntagonizer = new Antagonizer(notify, this);
#endif
}
服务器端client在MediaPlayerService::create中创建,新创建的Client对象加到mClients数组中
player_type getPlayerType(int fd, int64_t offset, int64_t length)
....
....
该函数根据首先读取文件的头部一些字节,然后根据头部标识的文件类型,返回相应的播放器类型
player_type getPlayerType(const char* url)
......
......
static sp createPlayer(player_type playerType, void* cookie,
notify_callback_f notifyFunc)
{
sp p;
switch (playerType & 0xff) {
#ifndef NO_OPENCORE
case PV_PLAYER:
LOGV(" create PVPlayer");
p = new PVPlayer();
break;
#endif
case SONIVOX_PLAYER:
LOGV(" create MidiFile");
p = new MidiFile();
break;
case STAGEFRIGHT_PLAYER:
LOGV(" create StagefrightPlayer");
p = new StagefrightPlayer;
break;
#ifdef PREBUILT_FSL_IMX_OMX
case OMX_PLAYER:
LOGV(" Create OMXPlayer.\n");
p = new OMXPlayer(playerType >> 8);
break;
#endif
case TEST_PLAYER:
LOGV("Create Test Player stub");
p = new TestPlayerStub();
break;
}
if (p != NULL) {
if (p->initCheck() == NO_ERROR) {
p->setNotifyCallback(cookie, notifyFunc);
} else {
p.clear();
}
}
if (p == NULL) {
LOGE("Failed to create player object");
}
return p;
}
OMXPlayer是freescale专有的播放器
status_t MediaPlayerService::Client::setDataSource(
const char *url, const KeyedVector *headers)
{
LOGV("setDataSource(%s)", url);
if (url == NULL)
return UNKNOWN_ERROR;
if (strncmp(url, "content://", 10) == 0) {
// get a filedescriptor for the content Uri and
// pass it to the setDataSource(fd) method
String16 url16(url);
int fd = android::openContentProviderFile(url16);
if (fd < 0)
{
LOGE("Couldn't open fd for %s", url);
return UNKNOWN_ERROR;
}
setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
close(fd);
return mStatus;
} else {
player_type playerType = getPlayerType(url);
LOGV("player type = %d", playerType);
// create the right type of player
sp p = createPlayer(playerType);
if (p == NULL) return NO_INIT;
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast(p.get())->setAudioSink(mAudioOutput);
}
// now set data source
LOGV(" setDataSource");
mStatus = p->setDataSource(url, headers);
if (mStatus == NO_ERROR) {
mPlayer = p;
} else {
LOGE(" error: %d", mStatus);
}
return mStatus;
}
}
status_t MediaPlayerService::Client::setVideoSurface(const sp& surface)
{
LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
sp p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
return p->setVideoSurface(surface);
}
为播放器设置surface对象
sp MediaPlayerService::Client::captureCurrentFrame()
{
LOGV("captureCurrentFrame");
sp p = getPlayer();
if (p == NULL) {
LOGE("media player is not initialized");
return NULL;
}
Mutex::Autolock lock(mLock);
mVideoFrame.clear();
mVideoFrameDealer.clear();
VideoFrame *frame = NULL;
p->captureCurrentFrame(&frame);
if (frame == NULL) {
LOGE("failed to capture a video frame");
return NULL;
}
size_t size = sizeof(VideoFrame) + frame->mSize;
mVideoFrameDealer = new MemoryDealer(size);
if (mVideoFrameDealer == NULL) {
LOGE("failed to create MemoryDealer");
return NULL;
}
mVideoFrame = mVideoFrameDealer->allocate(size);
if (mVideoFrame == NULL) {
LOGE("not enough memory for VideoFrame size=%u", size);
mVideoFrameDealer.clear();
return NULL;
}
VideoFrame *frameCopy = static_cast(mVideoFrame->pointer());
frameCopy->mWidth = frame->mWidth;
frameCopy->mHeight = frame->mHeight;
frameCopy->mDisplayWidth = frame->mDisplayWidth;
frameCopy->mDisplayHeight = frame->mDisplayHeight;
frameCopy->mSize = frame->mSize;
frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
memcpy(frameCopy->mData, frame->mData, frame->mSize);
return mVideoFrame;
}
MediaPlayerService.cpp中和video相关的代码就分析完了。
MediaPlayerService主要的工作就是在客户应用申请播放时,在Service创建对应的Client代理,处理客户端应用发过来的请求,Service会根据打开的文件或者URI类型,选择播放插件。