【问题标题】:MediaCodec - Missing codec specific dataMediaCodec - 缺少编解码器特定数据
【发布时间】:2021-06-06 08:06:31
【问题描述】:

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

【问题讨论】:

  • It worked perfectly up until Android 11 update 你指的是哪个更新?你的手机更新了吗?还是安卓工作室?还是图书馆?还是编译vbersion?还是什么?
  • @blackapps Android 11 更新是指更新到 Android 11 的设备。

标签: android opengl-es android-mediacodec mediamuxer


【解决方案1】:

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

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

更多关于codec specific data 及其含义的信息。

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

解决方案

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 感谢您的评论。当然,我们可能会丢失一些帧,但用户不会注意到它并且不会引起任何问题,因此我们将保持原样。同样,如果在开始时也缺少几帧音频,这可能会很奇怪。在我们的例子中,我们更喜欢视频从一开始就同时有声音/视频。
    猜你喜欢
    • 2020-06-08
    • 2019-06-21
    • 1970-01-01
    • 2020-05-27
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 2013-02-22
    相关资源
    最近更新 更多