【发布时间】:2022-01-05 16:19:49
【问题描述】:
出于测试目的,我使用 MediaExtractor 和 MediaMuxer 从现有视频创建新视频。我希望新视频的持续时间与原始视频完全相同,但事实并非如此。新的视频时长比原来的略短。
fun test(firstVideo: FileDescriptor, outputFileAbsolutePathUri: String) {
val extractor = MediaExtractor().apply {
this.setDataSource(firstVideo)
}
val muxer = MediaMuxer(outputFileAbsolutePathUri, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
try {
val MAX_SAMPLE_SIZE = 20 * 1024 * 1024
val bufferSize: Int = MAX_SAMPLE_SIZE
val dstBuf: ByteBuffer = ByteBuffer.allocate(bufferSize)
val bufferInfo = MediaCodec.BufferInfo()
val indexMap = setMuxerTracks(extractor, muxer)
muxer.start()
muxDataFromExtractor(muxer, extractor, indexMap, dstBuf, bufferInfo)
muxer.stop()
} finally {
extractor.release()
muxer.release()
}
}
private fun setMuxerTracks(extractor: MediaExtractor, muxer: MediaMuxer): Map<Int, Int> {
val indexMap = HashMap<Int, Int>(extractor.trackCount)
for (i in 0 until extractor.trackCount) {
extractor.selectTrack(i)
val format: MediaFormat = extractor.getTrackFormat(i)
val dstIndex = muxer.addTrack(format)
indexMap[i] = dstIndex
}
return indexMap
}
private fun muxDataFromExtractor(muxer: MediaMuxer,
extractor: MediaExtractor,
trackIndexMap: Map<Int, Int>,
dstBuf: ByteBuffer,
bufferInfo: MediaCodec.BufferInfo) {
var sawEOS = false
val initialPresentationTimeUs = bufferInfo.presentationTimeUs
while (!sawEOS) {
bufferInfo.offset = 0
bufferInfo.size = extractor.readSampleData(dstBuf, 0)
if (bufferInfo.size < 0) {
sawEOS = true
bufferInfo.size = 0
} else {
bufferInfo.presentationTimeUs = initialPresentationTimeUs + extractor.sampleTime
bufferInfo.flags = extractor.sampleFlags
val trackIndex = extractor.sampleTrackIndex
muxer.writeSampleData(trackIndexMap[trackIndex]!!, dstBuf, bufferInfo)
extractor.advance()
}
}
}
为了便于比较,原始视频时长为 3366666 微秒,而创建的视频时长为 3366366 微秒。视频长度取自 MediaFormat (MediaFormat.KEY_DURATION)
【问题讨论】:
标签: android android-mediacodec mediamuxer mediaextractor