kotlin
复制代码
import android.media.MediaCodec
import android.media.MediaExtractor
import android.media.MediaFormat
import android.util.Log
import java.io.IOException
import java.nio.ByteBuffer
class VideoDecoder {
companion object {
private const val TAG = "VideoDecoder"
}
fun decodeVideo(videoPath: String) {
val mediaExtractor = MediaExtractor()
try {
// 设置数据源
mediaExtractor.setDataSource(videoPath)
// 获取视频轨道索引
var trackIndex = -1
val numTracks = mediaExtractor.trackCount
for (i in 0 until numTracks) {
val format = mediaExtractor.getTrackFormat(i)
val mime = format.getString(MediaFormat.KEY_MIME)
if (mime?.startsWith("video/") == true) {
trackIndex = i
break
}
}
if (trackIndex == -1) {
Log.e(TAG, "No video track found!")
return
}
// 选择视频轨道
mediaExtractor.selectTrack(trackIndex)
val format = mediaExtractor.getTrackFormat(trackIndex)
// 获取解码器
val mimeType = format.getString(MediaFormat.KEY_MIME)
val mediaCodec = MediaCodec.createDecoderByType(mimeType!!)
mediaCodec.configure(format, null, null, 0)
mediaCodec.start()
// 获取解码器的输入输出缓冲区
// val inputBuffers = mediaCodec.inputBuffers
// val outputBuffers = mediaCodec.outputBuffers
val bufferInfo = MediaCodec.BufferInfo()
var isEOS = false
while (!isEOS) {
// 提交输入数据
val inputBufferIndex = mediaCodec.dequeueInputBuffer(10000)
if (inputBufferIndex >= 0) {
val inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex)
if (inputBuffer == null) {
isEOS = true
}else{
val sampleSize = mediaExtractor.readSampleData(inputBuffer, 0)
if (sampleSize < 0) {
// 如果没有更多的数据,标记结束
mediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
isEOS = true
} else {
mediaCodec.queueInputBuffer(inputBufferIndex, 0, sampleSize, mediaExtractor.sampleTime, 0)
mediaExtractor.advance()
}
}
}
// 获取输出数据并处理
val outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000)
if (outputBufferIndex >= 0) {
// 处理帧数据,这里可以进行渲染或存储操作
Log.i(TAG, "Decoded frame of size: ${bufferInfo.size}")
val outputBuffer: ByteBuffer? = mediaCodec.getOutputBuffer(outputBufferIndex)
val byteArray = ByteArray(bufferInfo.size)
outputBuffer?.get(byteArray)
// 释放输出缓冲区
mediaCodec.releaseOutputBuffer(outputBufferIndex, false)
if (bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM !== 0) {
// 解码结束
break
}
}
}
mediaExtractor.release()
mediaCodec.stop()
mediaCodec.release()
} catch (e: IOException) {
e.printStackTrace()
}
}
}