Android音视频开发(八)MediaExtractor

简介

MediaExtractor,用于提取指定媒体文件的媒体信息的一个工具类。说白一点,就是可以利用它提取视频或者音频中的信息和数据流,例如轨道,时长,格式等等。
MediaExtractor通常和MediaCodec一起使用,用于视频解码播放。

说明

一个视频里,可以包含多个数据流(一般是视频与音频各一个,但是音频可以多个)。我们需要先获取需要的数据轨道编号,才能后续的各种操作。

通常我们播放一个视频会使用以下类:

  1. MediaCodec:负责媒体文件的编码和解码工作,内部方法均为native
  2. MediaExtractor:负责将指定类型的媒体文件从文件中找到轨道,并填充到MediaCodec的缓冲区中
  3. AudioTrack:负责将解码之后的音频播放
  4. SurfaceView:展示解码之后的视频

视频被播放主要分为以下步骤:

  1. 将资源加载到MediaExtractor
  2. 获取视频所在轨道
  3. MediaExtractor选中视频所在轨道
  4. 创将解码视频的MediaCodec,decoder
  5. 开始循环,直到视频资源的末尾
  6. 将extractor中资源以一个单位填充进decoder的输入缓冲区
  7. decoder将解码之后的视频填充到输出缓冲区
  8. decoder释放输出缓冲区的同时,将缓冲区中数据渲染到surface

当然,这上面只是播放了视频,并没有播放音频,音频播放可参考我之前写的AudioTrack使用。
大家注意,千万别把视频和音频混为一谈,虽然我们口头上一直在说视频,但实际播放中他们是分开的,音频对应声音,视频对应影像图画。

由上可以看出MediaExtractor在这其中的作用

主要方法

  • setDataSource(String path):设置数据源,可以是本地文件或者网络文件
  • getTrackCount():得到源文件的轨道数
  • getTrackFormat(int index):获取指定(index)的轨道格式
  • getSampleTime():返回当前的时间戳
  • readSampleData(ByteBuffer byteBuf, int offset):把指定轨道中的数据按偏移量读取到ByteBuffer中;
  • advance():读取下一帧数据
  • release(): 读取结束后释放资源

使用示例

private fun init() {
    
    
        try {
    
    
            //构造
            mExtractor = MediaExtractor()
            //设置视频数据源,可以是本地文件也可以是网络文件,这里我使用了手机本机拍摄的示例文件
            mExtractor?.setDataSource("${
      
      externalCacheDir!!.absolutePath}/test.mp4")
			for (i in 0 until mExtractor!!.getTrackCount()) {
    
    
	            //获取轨道信息
	            val mediaFormat: MediaFormat = mExtractor!!.getTrackFormat(i)
	            val mime = mediaFormat.getString(MediaFormat.KEY_MIME)
	            Log.i("Test", "第${
      
      i}个轨道格式:$mime\n")
	        }
        } catch (e: Exception) {
    
    
            Log.e("Test", "出错了", e)
        }

    }

打印数据如下:

I/Test: 第0个轨道格式:video/avc
I/Test: 第1个轨道格式:audio/mp4a-latm

从上面可以看出,MediaExtractor会帮我们提取视频文件的信息,其中video/avc代表视频所在轨道信息,audio/mp4a-latm代表音频所在轨道信息

主要是获取对应的MediaFormat.。MeidaFormat包含了视频的所有信息,下面列一些获取常用的视频信息:

val videoIndex = getTrackIndex("video/")//找到视频所在轨道
val mediaFormat: MediaFormat = mExtractor!!.getTrackFormat(videoIndex)
 //获取视频高度
val width = mediaFormat.getInteger(MediaFormat.KEY_WIDTH)
//获取视频高度
val height = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT) 
//总时长
val duration = mediaFormat.getLong(MediaFormat.KEY_DURATION) 
 //获取视频缓存输出的最大大小
val maxInputSize = mediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)
 //以下是不一定能获取到的数据
 //获取采样率
val sampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE) 
 //获取码率
val bitRate = mediaFormat.getInteger(MediaFormat.KEY_BIT_RATE)
//获取声道数量
val channelCount = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT) 
//获取帧率
val frameRate = mediaFormat.getInteger(MediaFormat.KEY_FRAME_RATE) 
//PCM编码 模拟信号编码
val pcmEncoding = mediaFormat.getInteger(MediaFormat.KEY_PCM_ENCODING)

更多的信息可以自己去探索,官方文档:MediaExtractor
项目示例源码:Github/VideoDemo

关于涉及到与MediaCodec配合使用的内容我将会在后续博客中更新。

扫描二维码关注公众号,回复: 15907522 查看本文章

猜你喜欢

转载自blog.csdn.net/gs12software/article/details/105951635