【问题标题】:How to handle the PTS correctly using Android AudioRecord and MediaCodec as audio encoder?如何使用 Android AudioRecord 和 MediaCodec 作为音频编码器正确处理 PTS?
【发布时间】:2014-05-01 12:51:03
【问题描述】:

我正在使用 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 的缓冲区大小是 16384,所以一个完整的缓冲区意味着 185.76 ms。当我记录每次调用 read() 的系统时间并从基本时间中减去它们时,我得到以下序列:

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

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

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

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

我想问一下:

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

【问题讨论】:

  • 你试过MediaFormat.KEY_CHANNEL_MASK = AudioFormat.CHANNEL_OUT_MONO吗?
  • 我已经通过设置 KEY_CHANNEL_MASK = AudioFormat.CHANNEL_OUT_MONO 配置了音频编码器,但它的行为仍然相同。它仍然尝试按预期持续时间“压缩”输出 PTS。
  • @Mark 你找到解决方案了吗?

标签: android audio encoder audiorecord android-mediacodec


【解决方案1】:

将单声道输入转换为立体声。在意识到 MediaCoder 暴露的 AAC 编码器仅适用于立体声输入之前,我一直在抓狂。

【讨论】:

  • 你能提供一些代码吗?我想我面临同样的问题,不知道如何解决它:(
猜你喜欢
  • 2013-11-18
  • 2016-03-12
  • 1970-01-01
  • 1970-01-01
  • 2015-11-09
  • 2021-12-01
  • 1970-01-01
  • 2021-08-02
  • 2018-03-06
相关资源
最近更新 更多