Android音视频开发之MediaExtactor使用教程

作者:JulyYu 时间:2023-03-20 19:25:11 

前言

在之前学习如何使用MediaPlayer后,了解到Android系统提供开发者播放多媒体全家桶能力,但对于开发者希望DIY自由度更高的播放器能力也是可以利用Android内部提供组件包自行实现一个播放器的。举例实现一个视频播放这个流程,它大致流程是【多媒体文件解析提取视频文件】-> 【视频流解码】-> 【解码数据播放渲染到Render】。首要需要实现的是多媒体中需要文件提取工作,这就需要使用到Android提供MediaExtactor类来实现提取媒体信息能力。

MediaExtactor

MediaExtactorAndroid音视频开发中负责提取音视频信息和数据流的功能,可以通过该类实现从多媒体文件中剥离得到音频和视频的能力。

使用MediaExtactor

在一个音视频文件多可能会包含多个数据流(音频数据、视频数据等一般情况是一个视频组合多个音频)

  • 因此需要MediaExtactor加载音视频文件获取到所有数据轨道

  • 通过遍历获取到想要操作的轨道

  • 然后指定该轨道是MediaExtactor所有解析的数据流

  • 通过MediaExtactor获取到该轨道MediaFormat

加载音视频文件代码

加载音视频文件过程可传递UripathURL等。在确认希望需要解析的数据轨道后调用selectTrack就能锁定当前MediaExtactor要使用的轨道在之后数据解码中去使用。

// 加载资源
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(path);
// 遍历获取视频轨道
int trackIndex = getTrackIndex(extractor, "audio/");
// 选定轨道
extractor.selectTrack(trackIndex);

获取轨道代码

加载文件之后可以通过MediaExtactorgetTrackCount方法获取到所有数据轨道。然后可以通过getTrackFormat获取到轨道信息,通过MediaFormat.KEY_MIME得到轨道格式比对期望所有获取到的轨道,比如比对"audio/"就是希望获取到音频轨道数据。

// 获取指定轨道的方法
private static int getTrackIndex(MediaExtractor extractor, String mediaType) {
   int trackIndex = -1;
   for (int i = 0; i < extractor.getTrackCount(); i++) {
       MediaFormat mediaFormat = extractor.getTrackFormat(i);
       String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
       if (mime.startsWith(mediaType)) {
           trackIndex = i;
           break;
       }
   }
   return trackIndex;
}

提取轨道数据信息

在选定希望获取到的轨道后就可以获取到当前选择轨道的基本信息,例如视频尺寸大小、格式、时长、码率等一些音视频相关基础信息方便只有做解码时选用合适的解码器以及其他必要信息确认。

音频轨道基础信息获取

MediaFormatInfo mediaFormatInfo = new MediaFormatInfo();
mediaFormatInfo.mediaFormat = mediaFormat;
mediaFormatInfo.audioChannels = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
mediaFormatInfo.audioSampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
mediaFormatInfo.maxInputSize = mediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
mediaFormatInfo.mime = mediaFormat.getString(MediaFormat.KEY_MIME);

视频轨道基础信息获取

MediaFormatInfo mediaFormatInfo = new MediaFormatInfo();
mediaFormatInfo.mediaFormat = mediaFormat;
mediaFormatInfo.videoHeight = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
mediaFormatInfo.videoWidth = mediaFormat.getInteger(MediaFormat.KEY_WIDTH);
mediaFormatInfo.timeDuration = mediaFormat.getLong(MediaFormat.KEY_DURATION);
mediaFormatInfo.mime = mediaFormat.getString(MediaFormat.KEY_MIME);

但如果你选取的轨道是视频轨道但操作错误提取了音频相关信息可能会出现错误崩溃的情况(例如KEY_IS_ADTS 只有音频轨道才能提取),因此尽量保证提取参数是否正确做好代码保护机制。

一些源码细节分析

MediaExtactor作为提取器,其底层代码逻辑也是调用JNI来实现的,它只是上层API提供出能力而已。 在源码细节中可以看到MediaExtactor同样是加载media_jniso库,这和MediaPlayer是一样的逻辑。

public MediaExtractor() {
   native_setup();
}
private native final void native_setup();
static {
   System.loadLibrary("media_jni");
   native_init();
}

同时setDataSoure方法调用底层native接口和MediaPlayer也是同样的方法名和入参。

private native final void nativeSetDataSource(
       @NonNull IBinder httpServiceBinder,
       @NonNull String path,
       @Nullable String[] keys,
       @Nullable String[] values) throws IOException;

这基本也能够了解MediaExtactorMediaPlayer在底层实现上应该属于同一套逻辑和功能。只不过MediaExtactor可以理解为MediaPlayer其中一小部分功能提供提取能力而MediaPlayer是封装成型的工具类只需要加载音视频资源文件播放即可,中间提取轨道和解析过程直接就在底层帮开发者实现了。

来源:https://juejin.cn/post/7090477876813758471

标签:Android,MediaExtactor
0
投稿

猜你喜欢

  • C#递归应用之实现JS文件的自动引用

    2023-12-09 00:03:52
  • springboot以FTP方式上传文件到远程服务器

    2022-10-13 06:19:27
  • selenium+java破解极验滑动验证码的示例代码

    2022-11-19 21:52:01
  • SpringMVC数据页响应ModelAndView实现页面跳转

    2022-04-29 15:21:10
  • Android实现内存中数据保存到sdcard的方法

    2022-06-12 21:02:09
  • 浅谈Spring框架中@Autowired和@Resource的区别

    2023-11-26 11:31:21
  • Android自定义控件实现UC浏览器语音搜索效果

    2022-06-01 06:59:40
  • Android Camera2采集摄像头原始数据

    2021-06-23 22:55:53
  • Java MongoDB数据库连接方法梳理

    2023-11-25 01:01:20
  • Android自定义View弹性滑动Scroller详解

    2023-08-07 09:56:39
  • 详解Android系统中的root权限获得原理

    2023-06-19 20:28:25
  • Java实现斗地主案例

    2023-06-01 06:43:59
  • Android实现声音采集回声与回声消除

    2022-09-28 12:13:17
  • Android开发实现浏览器全屏显示功能

    2022-01-01 18:01:48
  • 详解在java中进行日期时间比较的4种方法

    2022-09-03 23:35:52
  • Android 将view 转换为Bitmap出现空指针问题解决办法

    2022-02-12 02:17:23
  • Unity2D实现游戏回旋镖

    2022-07-16 07:13:50
  • Android中EditText光标的显示与隐藏方法

    2022-03-01 17:52:35
  • Java如何实现简单后台访问并获取IP

    2021-10-27 02:26:27
  • C#实现套接字发送接收数据

    2023-01-09 19:34:38
  • asp之家 软件编程 m.aspxhome.com