马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
- 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()
- }
- }
- }
复制代码
- MediaExtractor:用于从 MP4 文件中提取视频轨道数据。通过 setDataSource() 设置视频路径,然后使用 getTrackCount() 获取轨道数量。接下来,我们通过 getTrackFormat() 获取轨道的格式,查找视频轨道。
- MediaCodec:用于解码视频帧。我们使用 createDecoderByType() 创建合适的解码器,并通过 configure() 设置解码器,最后调用 start() 开始解码。
- ByteBuffer:解码后的视频帧数据存储在 ByteBuffer 中。每次解码成功后,调用 dequeueOutputBuffer() 获取输出帧并通过 get() 方法提取数据。
- BufferInfo:用于存储每帧的解码信息,例如帧大小、时间戳等。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |