mediaplayer是android中的一种多媒体播放类,上层应用调用mediaplayer接口可以实现音视频的播放。mediaplayer最终是通过MediaPlayerFactory类的getPlayerType方法来选择具体的player。google默认的player是NU_PLAYER,该player最终会跑到mediacodec中去。很多公司在开发时会添加自己的player类型,如:ffmpeg
由于存在多个player类型,因此需要在getPlayerType这个接口中去进行选择。一般的文件都带有自己的后缀名,例如MP3、MP4、WAV等,这些文件名直接包含后缀的文件选择播放器十分简单,如下:
if(strstr(url,".ogg")){
return NU_PLAYER;
}
但是往往会碰到那种根据后缀名无法判断媒体类型的文件,例如打包进apk里面的raw文件,它通过setDataSource传到下面的路径往往是像下面这样的情况
setDataSource(fileurl =/system/app/webview/webview.apk)
此时我们无法直接得到媒体文件的封装格式,无法确定里面包含的媒体文件具体类型。
假如有这样的需求:上层传下的apk文件如果只包含音频,选择NU_PLAYER,此时该如何操作呢?实现代码如下:
bool MediaPlayerFactory::isFileOnlyContainAudio(int fd,
int64_t offset,
int64_t length){
bool hasAudio = false;
bool hasVideo = false;
sp<DataSource> checksource;
sp<IBinder> binder =
defaultServiceManager()->getService(String16("media.extractor"));
if (binder != nullptr) {
sp<IMediaExtractorService> mediaExService(
interface_cast<IMediaExtractorService>(binder));
sp<IDataSource> source =
mediaExService->makeIDataSource(fd, offset, length);
if (source.get() != nullptr) {
checksource = DataSource::CreateFromIDataSource(source);
} else {
ALOGW("extractor service cannot make data source");
}
} else {
ALOGW("extractor service not running");
}
sp<IMediaExtractor> extractor = MediaExtractor::Create(checksource);
size_t n = extractor->countTracks();
for(size_t i = 0; i < n; ++i){
sp<MetaData> trackMeta = extractor->getTrackMetaData(i);
const char *mime;
if (trackMeta->findCString(kKeyMIMEType, &mime)) {
if(!hasVideo && !strncasecmp("video/", mime, 6)){
hasVideo = true;
}else if(!hasAudio && !strncasecmp("audio/", mime, 6)){
hasAudio = true;
ALOGD("%s",mime);
}
}
}
if(extractor != NULL) extractor->release();
if(checksource != NULL) checksource.clear();
if(hasAudio && !hasVideo){
return true;
}
return false;
}
定义一个接口isFileOnlyContainAudio,通过binder调用IMediaExtractorService的接口提取文件中的所有track。通过这个接口来判断文件中是否只包含音频,最后在getPlayerType中添加:
if(strstr(filePath.string(),".apk") && isFileOnlyContainAudio(fd, offset, length)){
return NU_PLAYER;
}
修改位置:frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
这里主要是抛砖引玉,有类似的需求可以参考这样的改法