当前位置: 首页 > 知识库问答 >
问题:

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

鞠通
2023-03-14

我在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);

我发现这是第一次录音。read()的返回时间较长,而后续read()的时间间隔更接近音频数据的实时性。例如,我的音频格式是44100Hz 16位1通道,而AudioRecord的缓冲区大小是16384,所以一个完整的缓冲区意味着185.76毫秒。当我记录每次read()调用的系统时间,并从基时间中减去它们时,我得到以下序列:

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

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

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

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

我想问:

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

共有1个答案

贺元明
2023-03-14

将单声道输入转换为立体声。在我意识到MediaCoder公开的AAC编码器只适用于立体声输入之前,我已经把头发拔了一段时间。

 类似资料:
  • 我正在尝试使用MediaCodec和MediaMuxer对来自相机的视频和来自麦克风的音频进行编码。我在录制时使用OpenGL在图像上覆盖文本。 我以这些课程为例: http://bigflake.com/mediacodec/CameraToMpegTest.java.txt https://github.com/OnlyInAmerica/HWEncoderExperiments/blob/m

  • 我正在尝试使用android AudioRecord和MediaCodec对aac音频进行编码。我创建了一个非常类似于(使用Android MediaCodec从相机编码H.264)的编码器类。使用此类,我创建了一个AudioRecord实例,并告诉它将其byte[]数据读出到AudioEncoder(audioEncoder.offerEncoder(Data))。 这是我的音频记录设置 我成功

  • 以下是我的问题: 什么是? 格式是不明确的,因为它可以是属于家族的任何格式,例如、、和,对吗? 如果我想把这些数据从Image的三个平面写到MediaCodec中,我需要转换成什么样的格式?YUV420、NV21、NV12、……? 格式也不明确,因为它可以是属于家族的任何格式,对吗?如果我将MediaCodec对象的选项设置为,那么是什么格式(YUV420P,yuv420sp...)是否应该向Me

  • 我正在使用MediaCodec将PCM数据转换为AAC,并使用MediaMuxer将此aac数据存储到m4a文件中。没有视频。 该文件会生成,甚至会播放。但是没有声音。如果我将aac文件导入Audacity,它不会显示任何数据。音频的长度甚至是预期的时间。我知道数据正在被编码,尽管我不确定这些数据是否被正确编码。 对pcm数据进行编码: 我已经浏览了大量示例,我所做的一切似乎都是正确的。如果我在o

  • 我能够在MediaCodec和MediaMuxer的帮助下录制(编码)视频。接下来,我需要在MediaCodec和MediaMuxer的帮助下处理音频部分和带视频的mux音频。 我面临两个问题: > 如何将音频和视频数据传递给MediaMuxer(因为writeSampleData()方法一次只接受一种类型的数据)? 我提到了MediaMuxerTest,但它使用的是MediaExtractor。

  • 我正在尝试使用使用编解码器对一些音频流进行编码。为此,我使用了google cts ExtractEncodeMust的这个实现。 对于某些aac文件,它会在编码某些帧后抛出。更准确地说,它会在第1030行抛出异常,。 我正在配置如下: 我完全不知道如何解决这个问题。任何形式的帮助都将不胜感激。 带有一些日志的堆栈跟踪: 设备:小米POCO x3 操作系统:Android10 导致溢出的示例文件信