Fix assertion error when using high quality targeting API.

Add test that verifies SSIM with API enabled.

#minor-release

PiperOrigin-RevId: 460692420
This commit is contained in:
samrobinson 2022-07-13 12:48:02 +00:00 committed by Rohit Singh
parent bd8723e35a
commit f903869eb8
2 changed files with 38 additions and 23 deletions

View File

@ -23,10 +23,12 @@ import android.net.Uri;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.MimeTypes; import androidx.media3.common.MimeTypes;
import androidx.media3.transformer.AndroidTestUtil; import androidx.media3.transformer.AndroidTestUtil;
import androidx.media3.transformer.DefaultEncoderFactory;
import androidx.media3.transformer.TransformationRequest; import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.TransformationTestResult; import androidx.media3.transformer.TransformationTestResult;
import androidx.media3.transformer.Transformer; import androidx.media3.transformer.Transformer;
import androidx.media3.transformer.TransformerAndroidTestRunner; import androidx.media3.transformer.TransformerAndroidTestRunner;
import androidx.media3.transformer.VideoEncoderSettings;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test; import org.junit.Test;
@ -36,9 +38,10 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public final class TranscodeQualityTest { public final class TranscodeQualityTest {
@Test @Test
public void transformWithDecodeEncode_ssimIsGreaterThan90Percent() throws Exception { public void transformHighQualityTargetingAvcToAvc1920x1080_ssimIsGreaterThan95Percent()
throws Exception {
Context context = ApplicationProvider.getApplicationContext(); Context context = ApplicationProvider.getApplicationContext();
String testId = "transformWithDecodeEncode_ssim"; String testId = "transformHighQualityTargetingAvcToAvc1920x1080_ssim";
if (AndroidTestUtil.skipAndLogIfInsufficientCodecSupport( if (AndroidTestUtil.skipAndLogIfInsufficientCodecSupport(
context, context,
@ -52,7 +55,13 @@ public final class TranscodeQualityTest {
new Transformer.Builder(context) new Transformer.Builder(context)
.setTransformationRequest( .setTransformationRequest(
new TransformationRequest.Builder().setVideoMimeType(MimeTypes.VIDEO_H264).build()) new TransformationRequest.Builder().setVideoMimeType(MimeTypes.VIDEO_H264).build())
.setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory(context)) .setEncoderFactory(
new DefaultEncoderFactory.Builder(context)
.setRequestedVideoEncoderSettings(
new VideoEncoderSettings.Builder()
.setEnableHighQualityTargeting(true)
.build())
.build())
.setRemoveAudio(true) .setRemoveAudio(true)
.build(); .build();

View File

@ -241,27 +241,27 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
mimeType, encoderSupportedFormat.width, encoderSupportedFormat.height); mimeType, encoderSupportedFormat.width, encoderSupportedFormat.height);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, round(encoderSupportedFormat.frameRate)); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, round(encoderSupportedFormat.frameRate));
int bitrate;
if (supportedVideoEncoderSettings.enableHighQualityTargeting) { if (supportedVideoEncoderSettings.enableHighQualityTargeting) {
bitrate = int bitrate =
new DeviceMappedEncoderBitrateProvider() new DeviceMappedEncoderBitrateProvider()
.getBitrate( .getBitrate(
encoderInfo.getName(), encoderInfo.getName(),
encoderSupportedFormat.width, encoderSupportedFormat.width,
encoderSupportedFormat.height, encoderSupportedFormat.height,
encoderSupportedFormat.frameRate); encoderSupportedFormat.frameRate);
} else if (supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE) { encoderSupportedFormat =
bitrate = supportedVideoEncoderSettings.bitrate; encoderSupportedFormat.buildUpon().setAverageBitrate(bitrate).build();
} else { } else if (encoderSupportedFormat.bitrate == Format.NO_VALUE) {
bitrate = int bitrate =
getSuggestedBitrate( getSuggestedBitrate(
encoderSupportedFormat.width, encoderSupportedFormat.width,
encoderSupportedFormat.height, encoderSupportedFormat.height,
encoderSupportedFormat.frameRate); encoderSupportedFormat.frameRate);
encoderSupportedFormat =
encoderSupportedFormat.buildUpon().setAverageBitrate(bitrate).build();
} }
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, encoderSupportedFormat.averageBitrate);
mediaFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, supportedVideoEncoderSettings.bitrateMode); mediaFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, supportedVideoEncoderSettings.bitrateMode);
if (supportedVideoEncoderSettings.profile != VideoEncoderSettings.NO_VALUE if (supportedVideoEncoderSettings.profile != VideoEncoderSettings.NO_VALUE
@ -391,11 +391,23 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
return null; return null;
} }
// TODO(b/238094555): Check encoder supports bitrate targeted by high quality.
MediaCodecInfo pickedEncoderInfo = filteredEncoderInfos.get(0); MediaCodecInfo pickedEncoderInfo = filteredEncoderInfos.get(0);
int closestSupportedBitrate = int closestSupportedBitrate =
EncoderUtil.getSupportedBitrateRange(pickedEncoderInfo, mimeType).clamp(requestedBitrate); EncoderUtil.getSupportedBitrateRange(pickedEncoderInfo, mimeType).clamp(requestedBitrate);
VideoEncoderSettings.Builder supportedEncodingSettingBuilder =
videoEncoderSettings.buildUpon().setBitrate(closestSupportedBitrate); VideoEncoderSettings.Builder supportedEncodingSettingBuilder = videoEncoderSettings.buildUpon();
Format.Builder encoderSupportedFormatBuilder =
requestedFormat
.buildUpon()
.setSampleMimeType(mimeType)
.setWidth(finalResolution.getWidth())
.setHeight(finalResolution.getHeight());
if (!videoEncoderSettings.enableHighQualityTargeting) {
supportedEncodingSettingBuilder.setBitrate(closestSupportedBitrate);
encoderSupportedFormatBuilder.setAverageBitrate(closestSupportedBitrate);
}
if (videoEncoderSettings.profile == VideoEncoderSettings.NO_VALUE if (videoEncoderSettings.profile == VideoEncoderSettings.NO_VALUE
|| videoEncoderSettings.level == VideoEncoderSettings.NO_VALUE || videoEncoderSettings.level == VideoEncoderSettings.NO_VALUE
@ -406,16 +418,10 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
VideoEncoderSettings.NO_VALUE, VideoEncoderSettings.NO_VALUE); VideoEncoderSettings.NO_VALUE, VideoEncoderSettings.NO_VALUE);
} }
Format encoderSupportedFormat =
requestedFormat
.buildUpon()
.setSampleMimeType(mimeType)
.setWidth(finalResolution.getWidth())
.setHeight(finalResolution.getHeight())
.setAverageBitrate(closestSupportedBitrate)
.build();
return new VideoEncoderQueryResult( return new VideoEncoderQueryResult(
pickedEncoderInfo, encoderSupportedFormat, supportedEncodingSettingBuilder.build()); pickedEncoderInfo,
encoderSupportedFormatBuilder.build(),
supportedEncodingSettingBuilder.build());
} }
/** Returns a list of encoders that support the requested resolution most closely. */ /** Returns a list of encoders that support the requested resolution most closely. */
@ -650,7 +656,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
* </ul> * </ul>
*/ */
private static int getSuggestedBitrate(int width, int height, float frameRate) { private static int getSuggestedBitrate(int width, int height, float frameRate) {
// TODO(b/210591626) Refactor into a BitrateProvider. // TODO(b/238094555) Refactor into a BitrateProvider.
// Assume medium motion factor. // Assume medium motion factor.
// 1080p60 -> 16.6Mbps, 720p30 -> 3.7Mbps. // 1080p60 -> 16.6Mbps, 720p30 -> 3.7Mbps.
return (int) (width * height * frameRate * 0.07 * 2); return (int) (width * height * frameRate * 0.07 * 2);