- 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标记输出 。
当使用完MediaCodec后,必须调用release()方法释放其资源 。调用 release()方法进入最终的Released状态 。
工作原理和基本流程
文章插图
来看这个图片,这张图片就是MediaCodec的工作原理 。简单讲一下就是 。
- 数据的生产方(左侧的Client)从input缓冲队列申请empty buffer,然后把要处理的数据,填充到这些empty buffer里面 。就是上面的空方块(empty buffer),经过Client(数据生成方)之后,变成了红色实心的方块(有数据的buffer)
- 这些数据经过Codec处理之后,然后处理后的数据(黄色的方块)放入到右侧output缓冲区队列
- 消费方Client(右侧Client)从output缓冲区队列申请处理后的buffer,然后进一步处理,最后再将改buffer放回缓冲队列 。
这里大概讲一下mp4解码的过程(代码参考grafika)
- 创建MediaExtractor(),并设置数据源,MediaExtractor类,可以用来分离容器中的视频track和音频track 。然后选中音频轨道
- 通过MediaCodec.createDecoderByType解码器
- 调用decoder的configure与start函数
- 调用decoder.dequeueInputBuffera得到inputBufIndex
- decoder.getInputBuffer(inputBufIndex)得到inputBuf
- 调用 extractor.readSampleData填充inputBuf
- 调用extractor.advance()移动到下一个样本
- 调用decoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC)得到decoderStatus,这里是消费者消费数据
- 调用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)推荐阅读
- 怎么在王者荣耀改名字,王者荣耀网名怎么改不了
- 美图秀秀抠图有什么用,美图秀秀要怎么进行抠图
- 怎么关闭抖音商品橱窗功能,商品橱窗开通后可以关闭几次
- 王者荣耀如何把恋人关系解除,怎么才能解除王者里的恋人关系呢
- 活蟹怎么处理干净,螃蟹买回来怎么处理干净
- 表格公式下拉公式不计算,Excel公式不自动计算怎么办
- 可乐开了可以放多久,可乐开封后放冰箱可以存放多久
- cad中文字如何放大,CAD中文字反向怎么办
- 华为手机玩游戏掉帧很卡怎么办