【问题标题】:No audio when encoding PCM to AAC using MediaCodec and MediaMuxer使用 MediaCodec 和 MediaMuxer 将 PCM 编码为 AAC 时没有音频
【发布时间】:2021-08-02 15:28:10
【问题描述】:

我正在使用 MediaCodec 将 PCM 数据转换为 AAC,并使用 MediaMuxer 将此 aac 数据存储到 m4a 文件中。没有视频。

文件被生成,甚至可以播放。但是没有声音。如果我将 aac 文件导入 Audacity,它不会显示任何数据。音频的长度甚至是预期的时间。我知道数据正在被编码,尽管我不确定这些数据是否被正确编码。

编码 pcm 数据:

audioEncoder.setCallback(object : MediaCodec.Callback() {

    override fun onInputBufferAvailable(mc: MediaCodec, inputBufferId: Int) {
        updateRemoveAudioBufferIndex(inputBufferId)
    }

    override fun onOutputBufferAvailable(mc: MediaCodec, outputBufferId: Int, bufferInfo: MediaCodec.BufferInfo) {
        val outputBuffer = mc.getOutputBuffer(outputBufferId)

        if (bufferInfo.flags == MediaCodec.BUFFER_FLAG_CODEC_CONFIG) {
            audioEncoder.releaseOutputBuffer(outputBufferId, false)
            return
        }

        if (bufferInfo.size > 0) {
            outputBuffer?.position(bufferInfo.offset);
            outputBuffer?.limit(bufferInfo.offset + bufferInfo.size)

            muxer!!.writeSampleData(audioTrackIndex, outputBuffer!!, bufferInfo)
            audioEncoder.releaseOutputBuffer(outputBufferId, false)
        }

        if (bufferInfo.flags == BUFFER_FLAG_END_OF_STREAM) {
            cleanupAudioEncoder()
        }

    }

    override fun onError(mc: MediaCodec, ex: MediaCodec.CodecException) {
    }

    override fun onOutputFormatChanged(mc: MediaCodec, mf: MediaFormat) {
        audioTrackIndex = muxer!!.addTrack(audioEncoder.outputFormat)
        startMuxer()
    }
})

val format = MediaFormat()
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm")
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1)
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 32000)
format.setInteger(MediaFormat.KEY_BIT_RATE, 128000)
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC)

audioEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
audioEncoder.start()


fun encodeAudio(pcmData: ByteBuffer) {
    if (audioInputBufferIds.isNotEmpty()) {
        val bufferId = updateRemoveAudioBufferIndex()
        val buffer = audioEncoder.getInputBuffer(bufferId) as ByteBuffer
        buffer.clear()
        buffer.put(pcmData)

        val flags = if (encodingStopped) BUFFER_FLAG_END_OF_STREAM else 0

        audioEncoder.queueInputBuffer(bufferId, 0, pcmData.capacity(), presentationTimeAudio.toLong(), flags)
        presentationTimeAudio += bufferIntervalInMicroseconds
    }
}

我经历了大量的例子,我所做的一切似乎都是正确的。如果我在 onOutputBufferAvailable 函数中设置断点,很明显我正在接收编码数据。

【问题讨论】:

    标签: android android-mediacodec


    【解决方案1】:

    原来你需要在将数据放入缓冲区后回退:

    buffer.put(pcmData)
    buffer.rewind()
    

    说实话,我对我遇到的使用 buffer.put 但从不调用 rewind 的示例应用程序的数量感到非常惊讶。为什么他们甚至工作都超出了我的范围。倒带的文档说明如下:

    倒回这个缓冲区。位置设置为零并且标记被丢弃。 在一系列通道写入或获取操作之前调用此方法,假设已适当设置限制。

    https://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#rewind()

    MediaCodec 期望缓冲区在开始编码之前指向位置 0。因为我没有调用 rewind,所以 put 函数导致缓冲区位于最后一个位置,因此,MediaCodec 认为这意味着没有要编码的数据。奇怪的是,当编解码器没有给它编码数据时,MediaMuxer 甚至会费心写出数据。

    【讨论】:

      猜你喜欢
      • 2013-09-22
      • 1970-01-01
      • 2013-11-18
      • 2021-12-01
      • 1970-01-01
      • 2014-07-21
      • 2016-04-25
      • 2017-04-22
      • 1970-01-01
      相关资源
      最近更新 更多