mirror of
https://github.com/androidx/media.git
synced 2025-04-29 22:36:54 +08:00
Update DefaultEncoderFactory to set GOP parameters
If set on the requested VideoEncoderSettings, then these parameters are passed into the MediaFormat used by the DefaultEncoderFactory to configure the underlying codec. PiperOrigin-RevId: 751059914
This commit is contained in:
parent
910b6ab884
commit
dae5ebb820
@ -46,6 +46,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
/** A default implementation of {@link Codec.EncoderFactory}. */
|
||||
@ -395,6 +396,33 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
||||
}
|
||||
}
|
||||
|
||||
int maxBFrames = supportedVideoEncoderSettings.maxBFrames;
|
||||
if (SDK_INT >= 29 && maxBFrames != VideoEncoderSettings.NO_VALUE) {
|
||||
mediaFormat.setInteger(MediaFormat.KEY_MAX_B_FRAMES, maxBFrames);
|
||||
}
|
||||
|
||||
int numNonBidirectionalTemporalLayers =
|
||||
supportedVideoEncoderSettings.numNonBidirectionalTemporalLayers;
|
||||
int numBidirectionalTemporalLayers =
|
||||
supportedVideoEncoderSettings.numBidirectionalTemporalLayers;
|
||||
if (SDK_INT >= 25 && numNonBidirectionalTemporalLayers >= 0) {
|
||||
String temporalSchema;
|
||||
if (numNonBidirectionalTemporalLayers == 0) {
|
||||
temporalSchema = "none";
|
||||
} else if (numBidirectionalTemporalLayers > 0) {
|
||||
temporalSchema =
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"android.generic.%d+%d",
|
||||
numNonBidirectionalTemporalLayers,
|
||||
numBidirectionalTemporalLayers);
|
||||
} else {
|
||||
temporalSchema =
|
||||
String.format(Locale.ROOT, "android.generic.%d", numNonBidirectionalTemporalLayers);
|
||||
}
|
||||
mediaFormat.setString(MediaFormat.KEY_TEMPORAL_LAYERING, temporalSchema);
|
||||
}
|
||||
|
||||
return new DefaultCodec(
|
||||
context,
|
||||
encoderSupportedFormat,
|
||||
|
@ -337,6 +337,164 @@ public class DefaultEncoderFactoryTest {
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(sdk = 29)
|
||||
public void createForVideoEncoding_withMaxBFrames_configuresEncoderWithMaxBFrames()
|
||||
throws Exception {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
||||
DefaultCodec videoEncoder =
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.setRequestedVideoEncoderSettings(
|
||||
new VideoEncoderSettings.Builder().setMaxBFrames(3).build())
|
||||
.build()
|
||||
.createForVideoEncoding(requestedVideoFormat, /* logSessionId= */ null);
|
||||
|
||||
assertThat(videoEncoder.getConfigurationMediaFormat().getInteger(MediaFormat.KEY_MAX_B_FRAMES))
|
||||
.isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(sdk = 23)
|
||||
public void createForVideoEncoding_withMaxBFramesOnApi23_doesNotConfigureMaxBFrames()
|
||||
throws Exception {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
||||
DefaultCodec videoEncoder =
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.setRequestedVideoEncoderSettings(
|
||||
new VideoEncoderSettings.Builder().setMaxBFrames(3).build())
|
||||
.build()
|
||||
.createForVideoEncoding(requestedVideoFormat, /* logSessionId= */ null);
|
||||
|
||||
assertThat(videoEncoder.getConfigurationMediaFormat().containsKey(MediaFormat.KEY_MAX_B_FRAMES))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(sdk = 29)
|
||||
public void createForVideoEncoding_withDefaultEncoderSettings_doesNotConfigureMaxBFrames()
|
||||
throws Exception {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
||||
DefaultCodec videoEncoder =
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.build()
|
||||
.createForVideoEncoding(requestedVideoFormat, /* logSessionId= */ null);
|
||||
|
||||
assertThat(videoEncoder.getConfigurationMediaFormat().containsKey(MediaFormat.KEY_MAX_B_FRAMES))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Config(sdk = 29)
|
||||
@Test
|
||||
public void
|
||||
createForVideoEncoding_withTemporalLayeringSchemaWithZeroLayers_configuresEncoderWithTemporalLayeringSchema()
|
||||
throws Exception {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
||||
DefaultCodec videoEncoder =
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.setRequestedVideoEncoderSettings(
|
||||
new VideoEncoderSettings.Builder()
|
||||
.setTemporalLayers(
|
||||
/* numNonBidirectionalLayers= */ 0, /* numBidirectionalLayers= */ 0)
|
||||
.build())
|
||||
.build()
|
||||
.createForVideoEncoding(requestedVideoFormat, /* logSessionId= */ null);
|
||||
|
||||
assertThat(
|
||||
videoEncoder.getConfigurationMediaFormat().getString(MediaFormat.KEY_TEMPORAL_LAYERING))
|
||||
.isEqualTo("none");
|
||||
}
|
||||
|
||||
@Config(sdk = 29)
|
||||
@Test
|
||||
public void
|
||||
createForVideoEncoding_withTemporalLayeringSchemaWithoutBidirectionalLayers_configuresEncoderWithTemporalLayeringSchema()
|
||||
throws Exception {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
||||
DefaultCodec videoEncoder =
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.setRequestedVideoEncoderSettings(
|
||||
new VideoEncoderSettings.Builder()
|
||||
.setTemporalLayers(
|
||||
/* numNonBidirectionalLayers= */ 1, /* numBidirectionalLayers= */ 0)
|
||||
.build())
|
||||
.build()
|
||||
.createForVideoEncoding(requestedVideoFormat, /* logSessionId= */ null);
|
||||
|
||||
assertThat(
|
||||
videoEncoder.getConfigurationMediaFormat().getString(MediaFormat.KEY_TEMPORAL_LAYERING))
|
||||
.isEqualTo("android.generic.1");
|
||||
}
|
||||
|
||||
@Config(sdk = 29)
|
||||
@Test
|
||||
public void
|
||||
createForVideoEncoding_withTemporalLayeringSchemaWithBidirectionalLayers_configuresEncoderWithTemporalLayeringSchema()
|
||||
throws Exception {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
||||
DefaultCodec videoEncoder =
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.setRequestedVideoEncoderSettings(
|
||||
new VideoEncoderSettings.Builder()
|
||||
.setTemporalLayers(
|
||||
/* numNonBidirectionalLayers= */ 1, /* numBidirectionalLayers= */ 2)
|
||||
.build())
|
||||
.build()
|
||||
.createForVideoEncoding(requestedVideoFormat, /* logSessionId= */ null);
|
||||
|
||||
assertThat(
|
||||
videoEncoder.getConfigurationMediaFormat().getString(MediaFormat.KEY_TEMPORAL_LAYERING))
|
||||
.isEqualTo("android.generic.1+2");
|
||||
}
|
||||
|
||||
@Config(sdk = 23)
|
||||
@Test
|
||||
public void
|
||||
createForVideoEncoding_withTemporalLayeringSchemaOnApi23_doesNotConfigureTemporalLayeringSchema()
|
||||
throws Exception {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
||||
DefaultCodec videoEncoder =
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.setRequestedVideoEncoderSettings(
|
||||
new VideoEncoderSettings.Builder()
|
||||
.setTemporalLayers(
|
||||
/* numNonBidirectionalLayers= */ 1, /* numBidirectionalLayers= */ 2)
|
||||
.build())
|
||||
.build()
|
||||
.createForVideoEncoding(requestedVideoFormat, /* logSessionId= */ null);
|
||||
|
||||
assertThat(
|
||||
videoEncoder
|
||||
.getConfigurationMediaFormat()
|
||||
.containsKey(MediaFormat.KEY_TEMPORAL_LAYERING))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Config(sdk = 29)
|
||||
@Test
|
||||
public void
|
||||
createForVideoEncoding_withDefaultEncoderSettings_doesNotConfigureTemporalLayeringSchema()
|
||||
throws Exception {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
||||
DefaultCodec videoEncoder =
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.build()
|
||||
.createForVideoEncoding(requestedVideoFormat, /* logSessionId= */ null);
|
||||
|
||||
assertThat(
|
||||
videoEncoder
|
||||
.getConfigurationMediaFormat()
|
||||
.containsKey(MediaFormat.KEY_TEMPORAL_LAYERING))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createForVideoEncoding_withNoAvailableEncoderFromEncoderSelector_throws() {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
|
Loading…
x
Reference in New Issue
Block a user