繁体   English   中英

MediaCodec - 缺少编解码器特定数据

[英]MediaCodec - Missing codec specific data

我们的项目使用设备的麦克风作为音频输入录制视频,并将 openGL 场景作为视频 - openGL 场景是音频的可视化(光谱仪等)。 在 Android 11 更新之前,它在设备上运行良好,但现在更新设备上的 output 视频没有声音。 该问题并非特定于任何制造商,例如 Google Pixel 3/4 和三星 Galaxy S20 都受到影响。 没有运行时错误或崩溃,使用什么设备播放文件都没有关系 - 它肯定没有声音。 视频中的音频可视化很好,所以麦克风/输入不是问题。 我们使用 MediaMuxer 和 MediaCodec 将 output 录制到 mp4 文件中。

是否有其他人在设备的最新 Android 11 更新中遇到此问题? 有人对我们如何调试有任何建议吗?

这是我们配置视频和音频编解码器的方式:

//VIDEO OUTPUT (MP4)
public static final String VIDEO_MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
public static final int VIDEO_FRAME_RATE = 30; 
public static final int VIDEO_IFRAME_INTERVAL = 5;
public static final String AUDIO_MIME_TYPE = MediaFormat.MIMETYPE_AUDIO_AAC;Video Coding

//AUDIO INPUT (MIC)
public static final int RECORDER_SAMPLE_RATE = 44100;
public static final int RECORDER_CHANNELS = 1;
public static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

//AUDIO OUTPUT (MP4)
public static final String ENCODER_AUDIO_FORMAT = MediaFormat.MIMETYPE_AUDIO_AAC;
public static final int ENCODER_AAC_PROFILE = MediaCodecInfo.CodecProfileLevel.AACObjectLC;
public static final int AUDIO_BIT_RATE = 128000; 
public static final int AUDIO_SAMPLE_RATE = 44100;
public static final int AUDIO_SAMPLES_PER_FRAME = 1024;
public static final int AUDIO_FRAMES_PER_BUFFER = 25;
public static final int AUDIO_BYTES_PER_ELEMENT = 2;
public static final int AUDIO_NUMBER_OF_SPECTRUM_BINS = 20;

//...

//Initialise Video Encoder
MediaFormat format = MediaFormat.createVideoFormat(Config.VIDEO_MIME_TYPE, width, height);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, Config.VIDEO_FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, Config.VIDEO_IFRAME_INTERVAL);
videoEncoder = MediaCodec.createEncoderByType(Config.VIDEO_MIME_TYPE);
videoEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mInputSurface = videoEncoder.createInputSurface();
videoEncoder.start();

//Initialise Audio Encoder
audioEncoder = MediaCodec.createEncoderByType(Config.AUDIO_MIME_TYPE);
MediaFormat audioFormat = MediaFormat.createAudioFormat(Config.ENCODER_AUDIO_FORMAT,Config.AUDIO_SAMPLE_RATE,Config.RECORDER_CHANNELS);
audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, Config.ENCODER_AAC_PROFILE);
audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, Config.AUDIO_BIT_RATE);
audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, Config.RECORDER_CHANNELS);
audioEncoder.configure(audioFormat, null, null,MediaCodec.CONFIGURE_FLAG_ENCODE);
audioEncoder.start();

//Initiate Muxer
mMuxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
mMuxer.setOrientationHint(orientationHint);

当我们收到第一帧时我们开始混合

//...
else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
    MediaFormat videoFormat = videoEncoder.getOutputFormat();
    MediaFormat audioFormat = audioEncoder.getOutputFormat();
    videoTrackIndex = mMuxer.addTrack(videoFormat);
    audioTrackIndex = mMuxer.addTrack(audioFormat);
    mMuxer.start();
}

检查受影响设备上的详细日志,在点击“停止录制”按钮后,我能够找到以下感兴趣的行:

2021-03-08 14:52:12.658 20015-20241/com.xx.xx V/Audio:VideoEncoderCore: Sending EOS to encoder!
2021-03-08 14:52:12.670 20015-20241/com.xx.xx D/MPEG4Writer: reset()
**2021-03-08 14:52:12.670 20015-20259/com.xx.xx E/MPEG4Writer: Missing codec specific data**
2021-03-08 14:52:12.670 20015-20259/com.xx.xx E/MPEG4Writer: 0 frames to dump timeStamps in Audio track 
**2021-03-08 14:52:12.670 20015-20258/com.xx.xx V/MediaWriter: Track event err/info msg:101, trackId:1, type:1000,val:-1011 **
2021-03-08 14:52:12.670 20015-20258/com.xx.xx I/MPEG4Writer: Received total/0-length (69/0) buffers and encoded 69 frames. - Video
2021-03-08 14:52:12.670 20015-20241/com.xx.xx D/MPEG4Writer: Video track stopping. Stop source
2021-03-08 14:52:12.670 20015-20241/com.xx.xx D/MPEG4Writer: Video track source stopping
2021-03-08 14:52:12.670 20015-20241/com.xx.xx D/MPEG4Writer: Video track source stopped
2021-03-08 14:52:12.670 20015-20241/com.xx.xx D/MPEG4Writer: Video track stopped. Status:0. Stop source
2021-03-08 14:52:12.670 20015-20241/com.xx.xx D/MPEG4Writer: Audio track stopping. Stop source
2021-03-08 14:52:12.670 20015-20241/com.xx.xx D/MPEG4Writer: Audio track source stopping
2021-03-08 14:52:12.670 20015-20241/com.xx.xx D/MPEG4Writer: Audio track source stopped
2021-03-08 14:52:12.670 20015-20259/com.xx.xx V/MediaWriter: Track event err/info msg:100, trackId:2, type:100,val:-1007
2021-03-08 14:52:12.670 20015-20259/com.xx.xx I/MPEG4Writer: Received total/0-length (87/0) buffers and encoded 87 frames. - Audio
2021-03-08 14:52:12.670 20015-20259/com.xx.xx I/MPEG4Writer: Audio track drift time: 0 us
2021-03-08 14:52:12.670 20015-20262/com.xx.xx I/hw-BpHwBinder: onLastStrongRef automatically unlinking death recipients
**2021-03-08 14:52:12.671 20015-20241/com.xx.xx D/MPEG4Writer: Audio track stopped. Status:-1007. Stop source **
**2021-03-08 14:52:12.671 20015-20241/com.xx.xx W/MPEG4Writer: Condition trackErr == OK failed Audio track stopped with an error **
2021-03-08 14:52:12.671 20015-20241/com.xx.xx D/MPEG4Writer: Duration from tracks range is [2050653, 2293393] us
2021-03-08 14:52:12.671 20015-20256/com.xx.xx D/MPEG4Writer: 0 chunks are written in the last batch
2021-03-08 14:52:12.671 20015-20241/com.xx.xx D/MPEG4Writer: WriterThread stopped. Status:0
2021-03-08 14:52:12.671 20015-20241/com.xx.xx I/MPEG4Writer: Adjust the moov start time from 0 us -> 0 us
2021-03-08 14:52:12.671 20015-20241/com.xx.xx I/MPEG4Writer: MOOV atom was written to the file
2021-03-08 14:52:12.671 20015-20241/com.xx.xx D/MPEG4Writer: release()

以下错误帮助我解决了这个问题:

2021-03-08 14:52:12.670 20015-20259/com.xx.xx E/MPEG4Writer: Missing codec specific data

有关编解码器特定数据及其内容的更多信息。

我仍然不知道为什么这只是在 Android 11 推送之后才开始,但我知道原因以及如何解决它。 最初,我会在接收到第一帧视频后从视频线程中的音频和视频编码器中提取MediaFormat ,然后调用MediaMuxer.start() 在 Android 11 之前,这种方法运行良好。 但是,更新后,我的音频格式附加了内容特定的数据,这些数据需要提供给复用器。 不幸的是,只有在接收到第一帧声音(不是第一帧视频)后,音频编码器才能获得此数据。 因此,我以前的方法不起作用,因为在接收到第一帧视频之前我没有传递音频帧,并且我在从我的音频编码器接收编解码器特定数据之前启动了我的复用器。

解决方案

等待接收第一帧声音并在音频线程中调用MediaCodec.getMediaFormat() 对视频线程中的视频执行相同操作。 包含逻辑以检查是否已首先接收到音频和视频格式,然后在视频线程中启动多路复用器。 我所有的 output 文件现在都有视频和音频。

我在处理一些混合的东西时遇到了同样的问题。 您的解决方案的坏处在于,您将丢失所有由摄像头提供给 mediamuxer 的视频帧,直到您收到第一个音频帧。 我想在编码开始时提供一些虚拟音频帧会更好吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM