Android mediaplayer native层判断文件中码流的具体格式

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

这里主要是抛砖引玉,有类似的需求可以参考这样的改法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值