Android 使用MediaCodec和MediaMuxer将PCM编码到AAC时没有音频
我正在使用MediaCodec将PCM数据转换为AAC,并使用MediaMuxer将此AAC数据存储到m4a文件中。没有录像 该文件会生成,甚至会播放。但是没有声音。如果我将aac文件导入Audacity,它将不显示任何数据。音频的长度甚至是预期的时间。我知道数据正在被编码,尽管我不确定这些数据是否被正确编码 对pcm数据进行编码:Android 使用MediaCodec和MediaMuxer将PCM编码到AAC时没有音频,android,android-mediacodec,Android,Android Mediacodec,我正在使用MediaCodec将PCM数据转换为AAC,并使用MediaMuxer将此AAC数据存储到m4a文件中。没有录像 该文件会生成,甚至会播放。但是没有声音。如果我将aac文件导入Audacity,它将不显示任何数据。音频的长度甚至是预期的时间。我知道数据正在被编码,尽管我不确定这些数据是否被正确编码 对pcm数据进行编码: audioEncoder.setCallback(object : MediaCodec.Callback() { override fun onInpu
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函数中放置断点,很明显我正在接收编码数据。结果表明,在将数据放入缓冲区后,需要倒带缓冲区:
buffer.put(pcmData)
buffer.rewind()
老实说,我非常惊讶于我遇到的使用buffer.put但从不调用回放的示例应用程序的数量。我不明白他们为什么工作。关于倒带的文档说明如下:
倒带这个缓冲区。该位置设置为零,标记被丢弃。
在通道写入或获取操作序列之前调用此方法,假设已正确设置限制
MediaCodec希望缓冲区在开始编码之前指向位置0。因为我没有调用rewind,put函数导致缓冲区位于最后一个位置,因此MediaCodec认为这意味着没有数据要编码。奇怪的是,当编解码器没有提供编码数据时,MediaMuxer甚至会费心写出数据