mediacodec解析mp4( 二 )


  • Flushed:在调用start()方法后MediaCodec立即进入Flushed子状态,此时MediaCodec会拥有所有的缓存 。可以在Executing状态的任何时候通过调用flush()方法返回到Flushed子状态 。
  • Running:一旦第一个输入缓存(input buffer)被移出队列,MediaCodec就转入Running子状态,这种状态占据了MediaCodec的大部分生命周期 。通过调用stop()方法转移到Uninitialized状态 。
  • EOS:将一个带有end-of-stream标记的输入buffer入队列时,MediaCodec将转入End-of-Stream子状态 。在这种状态下,MediaCodec不再接收之后的输入buffer,但它仍然产生输出buffer直到end-of-stream标记输出 。
Released状态
当使用完MediaCodec后,必须调用release()方法释放其资源 。调用 release()方法进入最终的Released状态 。
工作原理和基本流程
mediacodec解析mp4

文章插图
来看这个图片,这张图片就是MediaCodec的工作原理 。简单讲一下就是 。
  • 数据的生产方(左侧的Client)从input缓冲队列申请empty buffer,然后把要处理的数据,填充到这些empty buffer里面 。就是上面的空方块(empty buffer),经过Client(数据生成方)之后,变成了红色实心的方块(有数据的buffer)
  • 这些数据经过Codec处理之后,然后处理后的数据(黄色的方块)放入到右侧output缓冲区队列
  • 消费方Client(右侧Client)从output缓冲区队列申请处理后的buffer,然后进一步处理,最后再将改buffer放回缓冲队列 。
接下来,就以解析mp4的视频为例 。讲解一下mediaCodec的解码视频轨道的过程 。各个功能看文中的代码注释,一些异常处理,这里就暂时不考虑了 。
这里大概讲一下mp4解码的过程(代码参考grafika)
  1. 创建MediaExtractor(),并设置数据源,MediaExtractor类,可以用来分离容器中的视频track和音频track 。然后选中音频轨道
  2. 通过MediaCodec.createDecoderByType解码器
  3. 调用decoder的configure与start函数
  4. 调用decoder.dequeueInputBuffera得到inputBufIndex
  5. decoder.getInputBuffer(inputBufIndex)得到inputBuf
  6. 调用 extractor.readSampleData填充inputBuf
  7. 调用extractor.advance()移动到下一个样本
  8. 调用decoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC)得到decoderStatus,这里是消费者消费数据
  9. 调用decoder.releaseOutputBuffer(decoderStatus,doRender),释放输出的Buffer空间
【更多音视频学习资料,点击下方链接免费领取↓↓,先码住不迷路~】
C++程序员必看,抓住音视频开发的大浪潮!冲击年薪60万

package com.example.videodemo
import android.media.MediaCodec
import android.media.MediaExtractor
import android.media.MediaFormat
import android.os.Handler
import android.os.Message
import android.util.Log
import android.view.Surface
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
class MediaCodecDemo constructor(val path: File, val outputSurface: Surface,val callback: SpeedControlCallback) {
【mediacodec解析mp4】private val TAG: String = "MediaCodecDemo"
var mVideoHeight = -1
var mVideoWidth = -1
private val mBufferInfo = MediaCodec.BufferInfo() //输出buffer的metadata
var mLoop = false
init {
var extractor: MediaExtractor? = null
try {
extractor = MediaExtractor()
extractor.setDataSource(path.toString())
val trackIndex = selectVideoTrack(extractor)
if (trackIndex < 0) {
throw RuntimeException("找不到视频轨道")
}
extractor.selectTrack(trackIndex)
val format = extractor.getTrackFormat(trackIndex)

推荐阅读