mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Remove unused experimental quality targeting mode
PiperOrigin-RevId: 727817967
This commit is contained in:
parent
6d408c2d31
commit
2f9fcfd238
@ -27,12 +27,10 @@ import androidx.media3.common.MediaItem;
|
|||||||
import androidx.media3.common.MimeTypes;
|
import androidx.media3.common.MimeTypes;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.transformer.AndroidTestUtil;
|
import androidx.media3.transformer.AndroidTestUtil;
|
||||||
import androidx.media3.transformer.DefaultEncoderFactory;
|
|
||||||
import androidx.media3.transformer.EditedMediaItem;
|
import androidx.media3.transformer.EditedMediaItem;
|
||||||
import androidx.media3.transformer.ExportTestResult;
|
import androidx.media3.transformer.ExportTestResult;
|
||||||
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.Before;
|
import org.junit.Before;
|
||||||
@ -53,49 +51,6 @@ public final class TranscodeQualityTest {
|
|||||||
testId = testName.getMethodName();
|
testId = testName.getMethodName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void exportHighQualityTargetingAvcToAvc1920x1080_ssimIsGreaterThan95Percent()
|
|
||||||
throws Exception {
|
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
|
||||||
|
|
||||||
assumeFormatsSupported(
|
|
||||||
context,
|
|
||||||
testId,
|
|
||||||
/* inputFormat= */ AndroidTestUtil.MP4_ASSET_WITH_INCREASING_TIMESTAMPS.videoFormat,
|
|
||||||
/* outputFormat= */ AndroidTestUtil.MP4_ASSET_WITH_INCREASING_TIMESTAMPS.videoFormat);
|
|
||||||
// Skip on specific pre-API 34 devices where calculating SSIM fails.
|
|
||||||
assumeFalse(
|
|
||||||
(Util.SDK_INT < 33 && (Build.MODEL.equals("SM-F711U1") || Build.MODEL.equals("SM-F926U1")))
|
|
||||||
|| (Util.SDK_INT == 33 && Build.MODEL.equals("LE2121")));
|
|
||||||
// Skip on specific API 21 devices that aren't able to decode and encode at this resolution.
|
|
||||||
assumeFalse(Util.SDK_INT == 21 && Build.MODEL.equals("Nexus 7"));
|
|
||||||
Transformer transformer =
|
|
||||||
new Transformer.Builder(context)
|
|
||||||
.setVideoMimeType(MimeTypes.VIDEO_H264)
|
|
||||||
.setEncoderFactory(
|
|
||||||
new DefaultEncoderFactory.Builder(context)
|
|
||||||
.setRequestedVideoEncoderSettings(
|
|
||||||
new VideoEncoderSettings.Builder()
|
|
||||||
.experimentalSetEnableHighQualityTargeting(true)
|
|
||||||
.build())
|
|
||||||
.build())
|
|
||||||
.build();
|
|
||||||
MediaItem mediaItem =
|
|
||||||
MediaItem.fromUri(Uri.parse(AndroidTestUtil.MP4_ASSET_WITH_INCREASING_TIMESTAMPS.uri));
|
|
||||||
EditedMediaItem editedMediaItem =
|
|
||||||
new EditedMediaItem.Builder(mediaItem).setRemoveAudio(true).build();
|
|
||||||
|
|
||||||
ExportTestResult result =
|
|
||||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
|
||||||
.setRequestCalculateSsim(true)
|
|
||||||
.build()
|
|
||||||
.run(testId, editedMediaItem);
|
|
||||||
|
|
||||||
if (result.ssim != ExportTestResult.SSIM_UNSET) {
|
|
||||||
assertThat(result.ssim).isGreaterThan(0.90);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void transcodeAvcToHevc_ssimIsGreaterThan90Percent() throws Exception {
|
public void transcodeAvcToHevc_ssimIsGreaterThan90Percent() throws Exception {
|
||||||
Context context = ApplicationProvider.getApplicationContext();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
@ -251,8 +251,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
*
|
*
|
||||||
* <p>Use {@link Builder#setRequestedVideoEncoderSettings} with {@link
|
* <p>Use {@link Builder#setRequestedVideoEncoderSettings} with {@link
|
||||||
* VideoEncoderSettings#bitrate} set to request for a specific encoding bitrate. Bitrate settings
|
* VideoEncoderSettings#bitrate} set to request for a specific encoding bitrate. Bitrate settings
|
||||||
* in {@link Format} are ignored when {@link VideoEncoderSettings#bitrate} or {@link
|
* in {@link Format} are ignored when {@link VideoEncoderSettings#bitrate} is set.
|
||||||
* VideoEncoderSettings#enableHighQualityTargeting} is set.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public DefaultCodec createForVideoEncoding(Format format) throws ExportException {
|
public DefaultCodec createForVideoEncoding(Format format) throws ExportException {
|
||||||
@ -292,14 +291,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
// supportedVideoEncoderSettings is identical to requestedVideoEncoderSettings.
|
// supportedVideoEncoderSettings is identical to requestedVideoEncoderSettings.
|
||||||
if (supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE) {
|
if (supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE) {
|
||||||
finalBitrate = supportedVideoEncoderSettings.bitrate;
|
finalBitrate = supportedVideoEncoderSettings.bitrate;
|
||||||
} else if (supportedVideoEncoderSettings.enableHighQualityTargeting) {
|
|
||||||
finalBitrate =
|
|
||||||
new DeviceMappedEncoderBitrateProvider()
|
|
||||||
.getBitrate(
|
|
||||||
encoderInfo.getName(),
|
|
||||||
encoderSupportedFormat.width,
|
|
||||||
encoderSupportedFormat.height,
|
|
||||||
encoderSupportedFormat.frameRate);
|
|
||||||
} else if (encoderSupportedFormat.averageBitrate != Format.NO_VALUE) {
|
} else if (encoderSupportedFormat.averageBitrate != Format.NO_VALUE) {
|
||||||
finalBitrate = encoderSupportedFormat.averageBitrate;
|
finalBitrate = encoderSupportedFormat.averageBitrate;
|
||||||
} else {
|
} else {
|
||||||
@ -462,10 +453,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
requestedFormat.width,
|
requestedFormat.width,
|
||||||
requestedFormat.height));
|
requestedFormat.height));
|
||||||
|
|
||||||
int requestedBitrate = Format.NO_VALUE;
|
int requestedBitrate =
|
||||||
// Encoders are not filtered by bitrate if high quality targeting is enabled.
|
|
||||||
if (!videoEncoderSettings.enableHighQualityTargeting) {
|
|
||||||
requestedBitrate =
|
|
||||||
videoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE
|
videoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE
|
||||||
? videoEncoderSettings.bitrate
|
? videoEncoderSettings.bitrate
|
||||||
: requestedFormat.averageBitrate != Format.NO_VALUE
|
: requestedFormat.averageBitrate != Format.NO_VALUE
|
||||||
@ -479,7 +467,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
if (filteredEncoderInfos.isEmpty()) {
|
if (filteredEncoderInfos.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
filteredEncoderInfos =
|
filteredEncoderInfos =
|
||||||
filterEncodersByBitrateMode(
|
filterEncodersByBitrateMode(
|
||||||
@ -496,18 +483,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
.setWidth(finalResolution.getWidth())
|
.setWidth(finalResolution.getWidth())
|
||||||
.setHeight(finalResolution.getHeight());
|
.setHeight(finalResolution.getHeight());
|
||||||
MediaCodecInfo pickedEncoderInfo = filteredEncoderInfos.get(0);
|
MediaCodecInfo pickedEncoderInfo = filteredEncoderInfos.get(0);
|
||||||
if (videoEncoderSettings.enableHighQualityTargeting) {
|
|
||||||
requestedBitrate =
|
|
||||||
new DeviceMappedEncoderBitrateProvider()
|
|
||||||
.getBitrate(
|
|
||||||
pickedEncoderInfo.getName(),
|
|
||||||
finalResolution.getWidth(),
|
|
||||||
finalResolution.getHeight(),
|
|
||||||
requestedFormat.frameRate);
|
|
||||||
// Resets the flag after getting a targeted bitrate, so that supportedEncodingSetting can have
|
|
||||||
// bitrate set.
|
|
||||||
supportedEncodingSettingBuilder.experimentalSetEnableHighQualityTargeting(false);
|
|
||||||
}
|
|
||||||
int closestSupportedBitrate =
|
int closestSupportedBitrate =
|
||||||
EncoderUtil.getSupportedBitrateRange(pickedEncoderInfo, mimeType).clamp(requestedBitrate);
|
EncoderUtil.getSupportedBitrateRange(pickedEncoderInfo, mimeType).clamp(requestedBitrate);
|
||||||
supportedEncodingSettingBuilder.setBitrate(closestSupportedBitrate);
|
supportedEncodingSettingBuilder.setBitrate(closestSupportedBitrate);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,6 @@ package androidx.media3.transformer;
|
|||||||
import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR;
|
import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR;
|
||||||
import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR;
|
import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR;
|
||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
|
||||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
@ -83,7 +82,6 @@ public final class VideoEncoderSettings {
|
|||||||
private int operatingRate;
|
private int operatingRate;
|
||||||
private int priority;
|
private int priority;
|
||||||
private long repeatPreviousFrameIntervalUs;
|
private long repeatPreviousFrameIntervalUs;
|
||||||
private boolean enableHighQualityTargeting;
|
|
||||||
|
|
||||||
/** Creates a new instance. */
|
/** Creates a new instance. */
|
||||||
public Builder() {
|
public Builder() {
|
||||||
@ -106,14 +104,11 @@ public final class VideoEncoderSettings {
|
|||||||
this.operatingRate = videoEncoderSettings.operatingRate;
|
this.operatingRate = videoEncoderSettings.operatingRate;
|
||||||
this.priority = videoEncoderSettings.priority;
|
this.priority = videoEncoderSettings.priority;
|
||||||
this.repeatPreviousFrameIntervalUs = videoEncoderSettings.repeatPreviousFrameIntervalUs;
|
this.repeatPreviousFrameIntervalUs = videoEncoderSettings.repeatPreviousFrameIntervalUs;
|
||||||
this.enableHighQualityTargeting = videoEncoderSettings.enableHighQualityTargeting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets {@link VideoEncoderSettings#bitrate}. The default value is {@link #NO_VALUE}.
|
* Sets {@link VideoEncoderSettings#bitrate}. The default value is {@link #NO_VALUE}.
|
||||||
*
|
*
|
||||||
* <p>Can not be set if enabling {@link #experimentalSetEnableHighQualityTargeting(boolean)}.
|
|
||||||
*
|
|
||||||
* @param bitrate The {@link VideoEncoderSettings#bitrate} in bits per second.
|
* @param bitrate The {@link VideoEncoderSettings#bitrate} in bits per second.
|
||||||
* @return This builder.
|
* @return This builder.
|
||||||
*/
|
*/
|
||||||
@ -208,31 +203,8 @@ public final class VideoEncoderSettings {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether to enable automatic adjustment of the bitrate to target a high quality encoding.
|
|
||||||
*
|
|
||||||
* <p>This method is experimental and may be removed or changed without warning.
|
|
||||||
*
|
|
||||||
* <p>Default value is {@code false}.
|
|
||||||
*
|
|
||||||
* <p>Requires {@link android.media.MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR}.
|
|
||||||
*
|
|
||||||
* <p>Can not be enabled alongside setting a custom bitrate with {@link #setBitrate(int)}.
|
|
||||||
*/
|
|
||||||
@CanIgnoreReturnValue
|
|
||||||
public Builder experimentalSetEnableHighQualityTargeting(boolean enableHighQualityTargeting) {
|
|
||||||
this.enableHighQualityTargeting = enableHighQualityTargeting;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Builds the instance. */
|
/** Builds the instance. */
|
||||||
public VideoEncoderSettings build() {
|
public VideoEncoderSettings build() {
|
||||||
checkState(
|
|
||||||
!enableHighQualityTargeting || bitrate == NO_VALUE,
|
|
||||||
"Bitrate can not be set if enabling high quality targeting.");
|
|
||||||
checkState(
|
|
||||||
!enableHighQualityTargeting || bitrateMode == BITRATE_MODE_VBR,
|
|
||||||
"Bitrate mode must be VBR if enabling high quality targeting.");
|
|
||||||
return new VideoEncoderSettings(
|
return new VideoEncoderSettings(
|
||||||
bitrate,
|
bitrate,
|
||||||
bitrateMode,
|
bitrateMode,
|
||||||
@ -241,8 +213,7 @@ public final class VideoEncoderSettings {
|
|||||||
iFrameIntervalSeconds,
|
iFrameIntervalSeconds,
|
||||||
operatingRate,
|
operatingRate,
|
||||||
priority,
|
priority,
|
||||||
repeatPreviousFrameIntervalUs,
|
repeatPreviousFrameIntervalUs);
|
||||||
enableHighQualityTargeting);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,9 +244,6 @@ public final class VideoEncoderSettings {
|
|||||||
*/
|
*/
|
||||||
public final long repeatPreviousFrameIntervalUs;
|
public final long repeatPreviousFrameIntervalUs;
|
||||||
|
|
||||||
/** Whether the encoder should automatically set the bitrate to target a high quality encoding. */
|
|
||||||
public final boolean enableHighQualityTargeting;
|
|
||||||
|
|
||||||
private VideoEncoderSettings(
|
private VideoEncoderSettings(
|
||||||
int bitrate,
|
int bitrate,
|
||||||
int bitrateMode,
|
int bitrateMode,
|
||||||
@ -284,8 +252,7 @@ public final class VideoEncoderSettings {
|
|||||||
float iFrameIntervalSeconds,
|
float iFrameIntervalSeconds,
|
||||||
int operatingRate,
|
int operatingRate,
|
||||||
int priority,
|
int priority,
|
||||||
long repeatPreviousFrameIntervalUs,
|
long repeatPreviousFrameIntervalUs) {
|
||||||
boolean enableHighQualityTargeting) {
|
|
||||||
this.bitrate = bitrate;
|
this.bitrate = bitrate;
|
||||||
this.bitrateMode = bitrateMode;
|
this.bitrateMode = bitrateMode;
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
@ -294,7 +261,6 @@ public final class VideoEncoderSettings {
|
|||||||
this.operatingRate = operatingRate;
|
this.operatingRate = operatingRate;
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
this.repeatPreviousFrameIntervalUs = repeatPreviousFrameIntervalUs;
|
this.repeatPreviousFrameIntervalUs = repeatPreviousFrameIntervalUs;
|
||||||
this.enableHighQualityTargeting = enableHighQualityTargeting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -320,8 +286,7 @@ public final class VideoEncoderSettings {
|
|||||||
&& iFrameIntervalSeconds == that.iFrameIntervalSeconds
|
&& iFrameIntervalSeconds == that.iFrameIntervalSeconds
|
||||||
&& operatingRate == that.operatingRate
|
&& operatingRate == that.operatingRate
|
||||||
&& priority == that.priority
|
&& priority == that.priority
|
||||||
&& repeatPreviousFrameIntervalUs == that.repeatPreviousFrameIntervalUs
|
&& repeatPreviousFrameIntervalUs == that.repeatPreviousFrameIntervalUs;
|
||||||
&& enableHighQualityTargeting == that.enableHighQualityTargeting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -337,7 +302,6 @@ public final class VideoEncoderSettings {
|
|||||||
result =
|
result =
|
||||||
31 * result
|
31 * result
|
||||||
+ (int) (repeatPreviousFrameIntervalUs ^ (repeatPreviousFrameIntervalUs >>> 32));
|
+ (int) (repeatPreviousFrameIntervalUs ^ (repeatPreviousFrameIntervalUs >>> 32));
|
||||||
result = 31 * result + (enableHighQualityTargeting ? 1 : 0);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,30 +186,6 @@ public class DefaultEncoderFactoryTest {
|
|||||||
assertThat(actualVideoFormat.averageBitrate).isEqualTo(8_709_120);
|
assertThat(actualVideoFormat.averageBitrate).isEqualTo(8_709_120);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void
|
|
||||||
createForVideoEncoding_setFormatAverageBitrateAndSetVideoEncoderSettingHighQualityTargeting_configuresEncoderUsingHighQualityTargeting()
|
|
||||||
throws Exception {
|
|
||||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
|
||||||
requestedVideoFormat = requestedVideoFormat.buildUpon().setAverageBitrate(5_000_000).build();
|
|
||||||
Format actualVideoFormat =
|
|
||||||
new DefaultEncoderFactory.Builder(context)
|
|
||||||
.setRequestedVideoEncoderSettings(
|
|
||||||
new VideoEncoderSettings.Builder()
|
|
||||||
.experimentalSetEnableHighQualityTargeting(true)
|
|
||||||
.build())
|
|
||||||
.build()
|
|
||||||
.createForVideoEncoding(requestedVideoFormat)
|
|
||||||
.getConfigurationFormat();
|
|
||||||
|
|
||||||
assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264);
|
|
||||||
assertThat(actualVideoFormat.width).isEqualTo(1920);
|
|
||||||
assertThat(actualVideoFormat.height).isEqualTo(1080);
|
|
||||||
// DeviceMappedEncoderBitrateProvider will produce 1920 * 1080 * 30 * 1.4, but the value is
|
|
||||||
// clampped down to the encoder's maximum, 25_000_000.
|
|
||||||
assertThat(actualVideoFormat.averageBitrate).isEqualTo(25_000_000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
createForVideoEncoding_setFormatAverageBitrateAndVideoEncoderSettingsBitrate_configuresEncoderUsingVideoEncoderSettingsBitrate()
|
createForVideoEncoding_setFormatAverageBitrateAndVideoEncoderSettingsBitrate_configuresEncoderUsingVideoEncoderSettingsBitrate()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user