现在的位置: 首页 > 综合 > 正文

android MetadataRetriever

2013年05月15日 ⁄ 综合 ⁄ 共 2550字 ⁄ 字号 评论关闭

 

元数据(MetaData)获取

多媒体文件中有些元信息,如专辑、作者、标题、年代等。有时需要将这些信息显示到UI界面上。与前述播放和录制框架类似,元数据信息获取具有下图所示框架。自2.3版本后,使用StagefrightMetadataRetriever,不再有VorbisMetadataRetriever。
应用程序开发者调用Java API类android.media.MediaMetadataRetriever,进而调用到JNI层。JNI层调用用C++类MediaMetadataRetriever,后者又使用IMediaMetadataRetriever接口强指针(实际指向)进行跨进程调用到MediaPlayerService中的MetadataRetrieverClient。MetadataRetrieverClient是一个wrapper(包裹)类,它通过创建不同的多媒体框架的Retriever来获取元数据信息。

下图是类继承关系图,MediaMetadataRetriever被JNI层使用,它里面包含的接口类的强指针指向接口类子类BpMediaMetadataRetriever对象,进而与Server侧通讯。

在Client侧的C++中(见文件mediametadataretriever.cpp),获取一个Binder如下:
MediaMetadataRetriever::MediaMetadataRetriever()
{
LOGV(“constructor”);
//获取MediaPlayerService在本侧的代理对象
const sp<IMediaPlayerService>& service(getService());
if (service == 0) {
LOGE(“failed to obtain MediaMetadataRetrieverService”);
return;
}

//调用MediaPlayerService去创建一个retriever
sp<IMediaMetadataRetriever> retriever(service
->createMetadataRetriever(getpid()));
if (retriever == 0) {
LOGE(“failed to create IMediaMetadataRetriever object from server”);
}
mRetriever = retriever;
}
在得到代理对象后,即可使用它通过Binder IPC跨进程调用。
在MetadataRetrieverClient中有一本地全局函数创建各个Retriever。它根据媒体文件类型创建对应的Retriever,目前只支持三种类型:
static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType)
{
sp<MediaMetadataRetrieverBase> p;
switch (playerType) {
case STAGEFRIGHT_PLAYER:
{//使用StageFright
p = new StagefrightMetadataRetriever;
break;
}
#ifndef NO_OPENCORE
case PV_PLAYER://使用OpenCore,创建对应的Retriever
LOGV(“create pv metadata retriever”);
p = new PVMetadataRetriever();
break;
#endif
case SONIVOX_PLAYER://创建MIDI文件对应的Retriever
LOGV(“create midi metadata retriever”);
p = new MidiMetadataRetriever();
break;
default:
// TODO:
// support for TEST_PLAYER
LOGE(“player type %d is not supported”,  playerType);
break;
}
if (p == NULL) {
LOGE(“failed to create a retriever object”);
}
return p;
}

获取的MetaData数据通过字符串形式返回,专辑图片等可由位图数据返回,见MediaMetadataRetriever.java:
public native String extractMetadata(int keyCode);
public native Bitmap captureFrame();
public native byte[] extractAlbumArt();

经过一串调用后,它们最终调用到下面的代码,从而对各个具体的Retriever进行调用:
sp<IMemory> MediaMetadataRetriever::captureFrame()
{
LOGV(“captureFrame”);
if (mRetriever == 0) {
LOGE(“retriever is not initialized”);
return NULL;
}
return mRetriever->captureFrame();//获取图像帧,以共享内存的方式返回
}
const char* MediaMetadataRetriever::extractMetadata(int keyCode)
{
LOGV(“extractMetadata(%d)”, keyCode);
if (mRetriever == 0) {
LOGE(“retriever is not initialized”);
return NULL;
}
return mRetriever->extractMetadata(keyCode);//获取对应的字符串值
}
sp<IMemory> MediaMetadataRetriever::extractAlbumArt()
{
LOGV(“extractAlbumArt”);
if (mRetriever == 0) {
LOGE(“retriever is not initialized”);
return NULL;
}
return mRetriever->extractAlbumArt();//以共享内存的方式返回
}

抱歉!评论已关闭.