简体   繁体   English

使用 MediaExtractor 和 MediaMuxer 创建视频会产生比原始视频持续时间更短的视频

[英]Creating a video with MediaExtractor and MediaMuxer produces a video with shorter duration than the original one

For a testing purpose I am creating a new video from existing one by using MediaExtractor and MediaMuxer.出于测试目的,我正在使用 MediaExtractor 和 MediaMuxer 从现有视频创建一个新视频。 I expect the new video to be exactly the same duration as the original one but it is not the case.我希望新视频的持续时间与原始视频完全相同,但事实并非如此。 The new video duration is slightly shorter than the original one.新的视频时长比原来的略短。

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()
        }
    }
}

Just for the sake of comparison the original video duration was 3366666 microsec and the created video duration was 3366366 microseconds.只是为了比较,原始视频时长为 3366666 微秒,创建的视频时长为 3366366 微秒。 The video length is retrieved from MediaFormat (MediaFormat.KEY_DURATION)从 MediaFormat (MediaFormat.KEY_DURATION) 中检索视频长度

no answer but some inputs that may help:没有答案,但一些输入可能会有所帮助:

  1. I believe the media extractor and media muxer are vendor owned, google have the default cpp implementation but the vendors can override it.我相信媒体提取器和媒体复用器是供应商拥有的,谷歌有默认的 cpp 实现,但供应商可以覆盖它。 you can review the google implementation here: https://cs.android.com/android/platform/superproject/+/master:frameworks/av/media/libstagefright/MediaMuxer.cpp;l=173你可以在这里查看谷歌的实现: https://cs.android.com/android/platform/superproject/+/master:frameworks/av/media/libstagefright/MediaMuxer.cpp;l=173

    It helps me to solve one of the voodoo bugs in the engine related to "last frame" / time mismatch.它帮助我解决了引擎中与“最后一帧”/时间不匹配相关的一个巫毒错误。 NOTE: you need to make sure you are looking on the right version (check the blame tool to the right).注意:您需要确保您正在查看正确的版本(检查右侧的责备工具)。

  2. the media can contain any metadata value that was pushed while creating the file.媒体可以包含创建文件时推送的任何元数据值。 so, you can calculate it again or just use what you get.所以,你可以再次计算它或只使用你得到的。

  3. did you tried to take the video that you created and then run the test when this file is the input?您是否尝试拍摄您创建的视频,然后在输入此文件时运行测试?

It appears that it depends on the way the source video was created: When I used ffprobe to get source video metadata I got the following:看来这取决于源视频的创建方式:当我使用 ffprobe 获取源视频元数据时,我得到了以下信息:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'source.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.76.100
  Duration: 00:00:03.37, start: 0.000000, bitrate: 123 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 400x136, 118 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : Core Media Video

The result video metadata was:结果视频元数据是:

 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'result.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2022-01-06T12:01:21.000000Z
    com.android.version: 11
  Duration: 00:00:03.37, start: 0.000000, bitrate: 126 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 400x136, 118 kb/s, SAR 1:1 DAR 50:17, 30 fps, 30 tbr, 90k tbn, 60 tbc (default)
    Metadata:
      creation_time   : 2022-01-06T12:01:21.000000Z
      handler_name    : VideoHandle  

When I use the video that was created by using MediaExtractor and MediaMuxer as a source the video duration is the same (within 1 microsecond threshold)当我使用使用 MediaExtractor 和 MediaMuxer 创建的视频作为源时,视频持续时间是相同的(在 1 微秒阈值内)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM