android - 如何使用 Android AudioRecord 和 MediaCodec 作为音频编码器正确处理 PTS?

标签 android audio encoder audiorecord android-mediacodec

我正在使用 AudioRecord 在 Android 设备上的相机捕获过程中录制音频流。 由于我要处理帧数据和处理音频/视频样本,所以我不使用 MediaRecorder。

我在另一个线程中运行 AudioRecord 并调用 read() 来收集原始音频数据。 获得数据流后,我将它们送入配置为 AAC 音频编码器的 MediaCodec。

以下是我的一些关于录音机/编码器的代码:

m_encode_audio_mime = "audio/mp4a-latm";
m_audio_sample_rate = 44100;
m_audio_channels = AudioFormat.CHANNEL_IN_MONO;
m_audio_channel_count = (m_audio_channels == AudioFormat.CHANNEL_IN_MONO ? 1 : 2);

int audio_bit_rate = 64000;
int audio_data_format = AudioFormat.ENCODING_PCM_16BIT;

m_audio_buffer_size = AudioRecord.getMinBufferSize(m_audio_sample_rate, m_audio_channels, audio_data_format) * 2;
m_audio_recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, m_audio_sample_rate,
                                   m_audio_channels, audio_data_format, m_audio_buffer_size);

m_audio_encoder = MediaCodec.createEncoderByType(m_encode_audio_mime);
MediaFormat audio_format = new MediaFormat();
audio_format.setString(MediaFormat.KEY_MIME, m_encode_audio_mime);
audio_format.setInteger(MediaFormat.KEY_BIT_RATE, audio_bit_rate);
audio_format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, m_audio_channel_count);
audio_format.setInteger(MediaFormat.KEY_SAMPLE_RATE, m_audio_sample_rate);
audio_format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
audio_format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, m_audio_buffer_size);
m_audio_encoder.configure(audio_format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

我发现AudioRecord.read()的第一次返回时间较长,而后续的read()时间间隔更接近音频数据的实时时间。 比如我的音频格式是44100Hz 16Bit 1Channel,AudioRecord的buffer size是16384,那么满buffer就是185.76ms。当我记录每次调用 read() 的系统时间并从基准时间中减去它们时,我得到以下序列:

每次读取之前的时间():0ms、345ms、543ms、692ms、891ms、1093ms、1244ms,...

我将这些原始数据以上述时间值作为 PTS 提供给音频编码器,编码器输出具有以下 PTS 的编码音频样本:

编码器输出PTS: 0ms, 185ms, 371ms, 557ms, 743ms, 928ms, ...

看起来编码器将数据的每个部分视为具有相同的时间段。我相信编码器工作正常,因为我每次都给它提供相同大小 (16384) 的原始数据。但是,如果我使用编码器输出 PTS 作为多路复用器的输入,我将获得音频内容比视频内容更快的视频。

我想问的是:

  1. 是否预期 AudioRecord.read() 的第一次阻塞时间更长?我确定函数调用需要超过 300 毫秒,而它只将 16384 个字节记录为 186 毫秒。这是否也是一个取决于设备/Android 版本的问题?
  2. 我应该怎么做才能实现音频/视频同步?我有一个解决方法来测量第一次调用 read() 的延迟时间,然后通过延迟移动音频样本的 PTS。还有其他更好的方法来处理这个问题吗?

最佳答案

将单声道输入转换为立体声。在我意识到 MediaCoder 公开的 AAC 编码器只适用于立体声输入之前,我一直在苦苦思索。

关于android - 如何使用 Android AudioRecord 和 MediaCodec 作为音频编码器正确处理 PTS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22604756/

相关文章:

javascript - 如果我在 Windows 控制台中传递此代码,它可以工作,但是当我在 node.js 代码中模拟 Windows 控制台时,它不起作用,并返回不清楚的错误

C# Text.Encoder 和 Text.Encoding 有什么区别

python - 使用 python 的数字到字母数字编码器(排列和正则表达式)

android - 无法在模拟器中启动 AVD :QT library not found

php - 对 2 种类型的消息 gcm 使用折叠键

java - Groovy 或 Java 上的跨平台提示音

embedded - 是否有任何 MP3 编码器库 PIC 微 Controller 兼容?

java - 我怎样才能改变我的 ListView 的字体颜色和字体类型

android - 通过拖放重新排序 LazyColumn 项目

android - 从URI传输音频时,opensl中的音频播放器在哪里缓冲?