Как проверить, поддерживает ли Android MediaCodec режим постоянного качества

У меня есть приложение для записи экрана, которое использует кодировщик MediaCodec для кодирования видеокадров. Вот один из способов получения видео-кодера:

videoCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);

Затем я пытаюсь определить наилучший режим битрейта, который поддерживает этот кодировщик, с моим порядком предпочтения: режим "Постоянное качество", режим с переменным битрейтом, режим с постоянным битрейтом. Вот как я пытаюсь это сделать:

MediaCodecInfo.CodecCapabilities capabilities = videoCodec.getCodecInfo().getCapabilitiesForType(MediaFormat.MIMETYPE_VIDEO_AVC);
MediaCodecInfo.EncoderCapabilities encoderCapabilities = capabilities.getEncoderCapabilities();

if (encoderCapabilities.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ)) {
    Timber.i("Setting bitrate mode to constant quality");
    videoFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ);
} else if (encoderCapabilities.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR)) {
    Timber.w("Setting bitrate mode to variable bitrate");
    videoFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR);
} else if (encoderCapabilities.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR)) {
    Timber.w("Setting bitrate mode to constant bitrate");
    videoFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR);
}

Запуск этого на моем Samsung Galaxy S7 приводит к выбору режима VBR, то есть режим постоянного качества, предположительно, не поддерживается. Тем не менее, если я просто установлю BITRATE_MODE на постоянное качество, он не только будет работать, но и фактически создаст видео лучшего качества, чем режим VBR.

Итак, если этот кодировщик явно поддерживает режим постоянного качества, почему я получаю ложный минус от isBitrateModeSupported()? Я что-то здесь упускаю?

1 ответ

Работая с устройствами MediaCodec и Samsung, я понял, что в этих устройствах есть странное поведение. Я не знаю, как это исправить, но, возможно, вам нужно подумать о чем-то особенном для них. Так что используйте:

if(android.os.Build.MANUFACTURER.toLowerCase().equals("samsumg"))
// your code

Уже очень поздно, но, может быть, я смогу помочь людям, которые приедут сюда в будущем.

Что касается android 26, MediaCodec класс примет только BITRATE_MODE_CQ за MIMETYPE_AUDIO_FLAC кодеки.

Не знаю почему, но это жестко закодировано в классе:

    /**
             * Query whether a bitrate mode is supported.
             */
            public boolean isBitrateModeSupported(int mode) {
                for (Feature feat: bitrates) {
                    if (mode == feat.mValue) {
                        return (mBitControl & (1 << mode)) != 0;
                    }
                }
                return false;
            }

private void applyLevelLimits() {
            String mime = mParent.getMimeType();
            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
                mComplexityRange = Range.create(0, 8);
                mBitControl = (1 << BITRATE_MODE_CQ);
            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)
                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)
                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
                mBitControl = (1 << BITRATE_MODE_CBR);
            }
        }

учитывая, что BITRATE_MODE_CQ 0 isBitrateModeSupported вернет только истинный случай MIMETYPE_AUDIO_FLAC выбрано.

Это ответ, почему он возвращает false до уровня Android 26,
почему он так закодирован, я не знаю.

Я думаю, простой способ проверить - попытаться создать кодировщик с желаемым форматом и поймать любое возможное исключение.

Другие вопросы по тегам