mediacodec解析mp4( 三 )


mVideoHeight = format.getInteger(MediaFormat.KEY_HEIGHT)
mVideoWidth = format.getInteger(MediaFormat.KEY_WIDTH)
} finally {
extractor?.release()
}
}
//寻找视频轨道,并返回对应的index
private fun selectVideoTrack(extractor: MediaExtractor): Int {
val numTracks = extractor.trackCount
Log.d("hch","index $numTracks")
for (index in 0 until numTracks) {
val format = extractor.getTrackFormat(index)
val mime = format.getString(MediaFormat.KEY_MIME)
mime?.let {
if (it.startsWith("video/")) {
Log.d("hch","index $index")
return index
}
}
}
return -1
}
private fun play() {
var extractor: MediaExtractor? = null
var decoder: MediaCodec? = null
try {
extractor = MediaExtractor()
extractor.setDataSource(path.toString())
//文件不存在,直接抛出异常
if (!path.exists()) {
throw FileNotFoundException("file donot exists")
}
val trackIndex = selectVideoTrack(extractor)
if (trackIndex < 0) {
throw RuntimeException("video track dont find")
}
extractor.selectTrack(trackIndex)
val format = extractor.getTrackFormat(trackIndex)
val mine = format.getString(MediaFormat.KEY_MIME)
decoder = mine?.let { MediaCodec.createDecoderByType(it) }
decoder?.let {
decoder?.configure(format, outputSurface, null, 0)
decoder?.start()
doFrame(extractor!!, trackIndex, it)
}
} catch (e:IOException){
}
finally {
decoder?.stop()
decoder?.release()
decoder = null
extractor?.release()
extractor = null
}
}
private fun doFrame(extractor: MediaExtractor, trackIndex: Int, decoder: MediaCodec) {
val TIMEOUT_USEC = 10000L
var inputChunk = 0
var inputDOne= false
var outputDOne= false
while (!outputDone) {
//获取输入buff的空间
if (!inputDone) {
//得到inputBufIndex
val inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC)
if (inputBufIndex >= 0) {
//得到对应的inputBuffer
val inputBuf = decoder.getInputBuffer(inputBufIndex)
inputBuf?.let {
//数据生成方填充对应的inputBuf
val chunkSize = extractor.readSampleData(it, 0)
if (chunkSize < 0) {
//读到文件末
decoder.queueInputBuffer(
inputBufIndex,
0,
0,
0L,
MediaCodec.BUFFER_FLAG_END_OF_STREAM
)
//推出循环
inputDOne= true
} else {
//
val presentatiOnTimeUs= extractor.sampleTime
decoder.queueInputBuffer(
inputBufIndex,
0,
chunkSize,
presentationTimeUs,
0
)
inputChunk++
//移动到下一个样本
extractor.advance()
}
}
} else {
Log.d("hch", "input buffer not available")
}
}
if (!outputDone) {
//获取Codec的数据
val decoderStatus = decoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC)
when {
decoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER -> {
Log.d("hch", "no output from decoder available")
}
decoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED -> {
val newFormat = decoder.outputFormat
Log.d(TAG, "decoder output format changed: $newFormat")
}
decoderStatus < 0 -> {
throw RuntimeException("unexpected result from decoder.dequeueOutputBuffer: $decoderStatus")
}
else -> {
// decoderStatus >= 0
var doLoop = false
if (mBufferInfo.flags.and(MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
if (mLoop) {
doLoop = true
} else {
outputDOne= true
}
}
val doRender = (mBufferInfo.size != 0)
//控制速率

推荐阅读