From 18617b8a6005809be62e1a05fd77d2d1d5c8ff59 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Mon, 22 Jan 2024 04:53:11 -0800 Subject: [PATCH] Prevent using high profile on problematic devices [Android best practices](https://developer.android.com/media/optimize/sharing#android_8_81_and_9) recommend disabling B-frames on API 27, but some devices output B-frames anyway when H.264/AVC High profile is selected. Add a workaround to force these devices not to use high profile, to prevent B-frames being output. `MediaMuxer` likely handles B-frames on these specific devices, but this change allows the migration to default to in-app muxing to take place without introducing errors, and it's a temporary workaround until B-frames are properly supported in the in-app muxer. PiperOrigin-RevId: 600422238 (cherry picked from commit 60295218985952a627764e1c3a6fce919f52ed4c) --- .../media3/transformer/DefaultEncoderFactory.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java index dfa03c9911..904f803399 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java @@ -570,7 +570,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { mediaFormat.setInteger(MediaFormat.KEY_PROFILE, expectedEncodingProfile); mediaFormat.setInteger(MediaFormat.KEY_LEVEL, supportedEncodingLevel); } - } else if (Util.SDK_INT >= 26) { + } else if (Util.SDK_INT >= 26 && !deviceNeedsNoH264HighProfileWorkaround()) { int expectedEncodingProfile = MediaCodecInfo.CodecProfileLevel.AVCProfileHigh; int supportedEncodingLevel = EncoderUtil.findHighestSupportedEncodingLevel( @@ -581,8 +581,8 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { // system versions. mediaFormat.setInteger(MediaFormat.KEY_PROFILE, expectedEncodingProfile); mediaFormat.setInteger(MediaFormat.KEY_LEVEL, supportedEncodingLevel); - // TODO(b/210593256): Set KEY_LATENCY to 2 to enable B-frame production after switching to - // in-app muxing. + // TODO(b/210593256): Set KEY_LATENCY to 2 to enable B-frame production after in-app muxing + // is the default and it supports B-frames. mediaFormat.setInteger(MediaFormat.KEY_LATENCY, 1); } } else if (Util.SDK_INT >= 24) { @@ -678,4 +678,11 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { // Redmi Note 9 Pro fails if KEY_FRAME_RATE is set too high (see b/278076311). return SDK_INT < 30 && Util.DEVICE.equals("joyeuse"); } + + private static boolean deviceNeedsNoH264HighProfileWorkaround() { + // The H.264/AVC encoder produces B-frames when high profile is chosen despite configuration to + // turn them off, so force not using high profile on these devices (see b/306617392). + // TODO(b/229420356): Remove once the in-app muxer is the default and B-frames are supported. + return Util.SDK_INT == 27 && (Util.DEVICE.equals("ASUS_X00T_3") || Util.DEVICE.equals("TC77")); + } }