Pass initializationData to EncoderFactory when requested

PiperOrigin-RevId: 580098432
This commit is contained in:
tofunmi 2023-11-07 02:01:46 -08:00 committed by Copybara-Service
parent 14fb45626d
commit ba0724ca78
5 changed files with 75 additions and 10 deletions

View File

@ -55,7 +55,8 @@ import org.checkerframework.dataflow.qual.Pure;
AudioMixer.Factory mixerFactory, AudioMixer.Factory mixerFactory,
Codec.EncoderFactory encoderFactory, Codec.EncoderFactory encoderFactory,
MuxerWrapper muxerWrapper, MuxerWrapper muxerWrapper,
FallbackListener fallbackListener) FallbackListener fallbackListener,
boolean matchInitializationData)
throws ExportException { throws ExportException {
super(firstAssetLoaderTrackFormat, muxerWrapper); super(firstAssetLoaderTrackFormat, muxerWrapper);
audioGraph = new AudioGraph(mixerFactory); audioGraph = new AudioGraph(mixerFactory);
@ -74,6 +75,8 @@ import org.checkerframework.dataflow.qual.Pure;
.setChannelCount(encoderInputAudioFormat.channelCount) .setChannelCount(encoderInputAudioFormat.channelCount)
.setPcmEncoding(encoderInputAudioFormat.encoding) .setPcmEncoding(encoderInputAudioFormat.encoding)
.setAverageBitrate(DEFAULT_ENCODER_BITRATE) .setAverageBitrate(DEFAULT_ENCODER_BITRATE)
.setInitializationData(
matchInitializationData ? firstInputFormat.initializationData : null)
.build(); .build();
encoder = encoder =

View File

@ -1206,7 +1206,8 @@ public final class Transformer {
applicationHandler, applicationHandler,
debugViewProvider, debugViewProvider,
clock, clock,
initialTimestampOffsetUs); initialTimestampOffsetUs,
/* matchInitializationData= */ false);
transformerInternal.start(); transformerInternal.start();
} }

View File

@ -129,6 +129,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final List<SampleExporter> sampleExporters; private final List<SampleExporter> sampleExporters;
private final Object setMaxSequenceDurationUsLock; private final Object setMaxSequenceDurationUsLock;
private final MuxerWrapper muxerWrapper; private final MuxerWrapper muxerWrapper;
private final boolean matchInitializationData;
private final ConditionVariable transformerConditionVariable; private final ConditionVariable transformerConditionVariable;
private boolean isDrainingExporters; private boolean isDrainingExporters;
@ -153,7 +154,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
HandlerWrapper applicationHandler, HandlerWrapper applicationHandler,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
Clock clock, Clock clock,
long videoSampleTimestampOffsetUs) { long videoSampleTimestampOffsetUs,
boolean matchInitializationData) {
this.context = context; this.context = context;
this.composition = composition; this.composition = composition;
this.encoderFactory = new CapturingEncoderFactory(encoderFactory); this.encoderFactory = new CapturingEncoderFactory(encoderFactory);
@ -162,6 +164,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.clock = clock; this.clock = clock;
this.videoSampleTimestampOffsetUs = videoSampleTimestampOffsetUs; this.videoSampleTimestampOffsetUs = videoSampleTimestampOffsetUs;
this.muxerWrapper = muxerWrapper; this.muxerWrapper = muxerWrapper;
this.matchInitializationData = matchInitializationData;
internalHandlerThread = new HandlerThread("Transformer:Internal"); internalHandlerThread = new HandlerThread("Transformer:Internal");
internalHandlerThread.start(); internalHandlerThread.start();
sequenceAssetLoaders = new ArrayList<>(); sequenceAssetLoaders = new ArrayList<>();
@ -582,7 +585,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
audioMixerFactory, audioMixerFactory,
encoderFactory, encoderFactory,
muxerWrapper, muxerWrapper,
fallbackListener)); fallbackListener,
matchInitializationData));
} else { } else {
// TODO(b/267301878): Pass firstAssetLoaderOutputFormat once surface creation not in VSP. // TODO(b/267301878): Pass firstAssetLoaderOutputFormat once surface creation not in VSP.
assetLoaderInputTracker.registerSampleExporter( assetLoaderInputTracker.registerSampleExporter(
@ -600,8 +604,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
fallbackListener, fallbackListener,
debugViewProvider, debugViewProvider,
videoSampleTimestampOffsetUs, videoSampleTimestampOffsetUs,
/* hasMultipleInputs= */ assetLoaderInputTracker /* hasMultipleInputs= */ assetLoaderInputTracker.hasMultipleConcurrentVideoTracks(),
.hasMultipleConcurrentVideoTracks())); matchInitializationData));
} }
} }

View File

@ -88,7 +88,8 @@ import org.checkerframework.dataflow.qual.Pure;
FallbackListener fallbackListener, FallbackListener fallbackListener,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
long initialTimestampOffsetUs, long initialTimestampOffsetUs,
boolean hasMultipleInputs) boolean hasMultipleInputs,
boolean matchInitializationData)
throws ExportException { throws ExportException {
// TODO(b/278259383) Consider delaying configuration of VideoSampleExporter to use the decoder // TODO(b/278259383) Consider delaying configuration of VideoSampleExporter to use the decoder
// output format instead of the extractor output format, to match AudioSampleExporter behavior. // output format instead of the extractor output format, to match AudioSampleExporter behavior.
@ -109,7 +110,8 @@ import org.checkerframework.dataflow.qual.Pure;
firstInputFormat.buildUpon().setColorInfo(decoderInputColor).build(), firstInputFormat.buildUpon().setColorInfo(decoderInputColor).build(),
muxerWrapper.getSupportedSampleMimeTypes(C.TRACK_TYPE_VIDEO), muxerWrapper.getSupportedSampleMimeTypes(C.TRACK_TYPE_VIDEO),
transformationRequest, transformationRequest,
fallbackListener); fallbackListener,
matchInitializationData);
encoderOutputBuffer = encoderOutputBuffer =
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
@ -239,6 +241,7 @@ import org.checkerframework.dataflow.qual.Pure;
private final FallbackListener fallbackListener; private final FallbackListener fallbackListener;
private final String requestedOutputMimeType; private final String requestedOutputMimeType;
private final @Composition.HdrMode int hdrModeAfterFallback; private final @Composition.HdrMode int hdrModeAfterFallback;
private final boolean matchInitializationData;
private @MonotonicNonNull SurfaceInfo encoderSurfaceInfo; private @MonotonicNonNull SurfaceInfo encoderSurfaceInfo;
@ -251,13 +254,15 @@ import org.checkerframework.dataflow.qual.Pure;
Format inputFormat, Format inputFormat,
List<String> muxerSupportedMimeTypes, List<String> muxerSupportedMimeTypes,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
FallbackListener fallbackListener) { FallbackListener fallbackListener,
boolean matchInitializationData) {
checkArgument(inputFormat.colorInfo != null); checkArgument(inputFormat.colorInfo != null);
this.encoderFactory = encoderFactory; this.encoderFactory = encoderFactory;
this.inputFormat = inputFormat; this.inputFormat = inputFormat;
this.muxerSupportedMimeTypes = muxerSupportedMimeTypes; this.muxerSupportedMimeTypes = muxerSupportedMimeTypes;
this.transformationRequest = transformationRequest; this.transformationRequest = transformationRequest;
this.fallbackListener = fallbackListener; this.fallbackListener = fallbackListener;
this.matchInitializationData = matchInitializationData;
Pair<String, Integer> outputMimeTypeAndHdrModeAfterFallback = Pair<String, Integer> outputMimeTypeAndHdrModeAfterFallback =
getRequestedOutputMimeTypeAndHdrModeAfterFallback(inputFormat, transformationRequest); getRequestedOutputMimeTypeAndHdrModeAfterFallback(inputFormat, transformationRequest);
requestedOutputMimeType = outputMimeTypeAndHdrModeAfterFallback.first; requestedOutputMimeType = outputMimeTypeAndHdrModeAfterFallback.first;
@ -332,6 +337,8 @@ import org.checkerframework.dataflow.qual.Pure;
.setFrameRate(inputFormat.frameRate) .setFrameRate(inputFormat.frameRate)
.setSampleMimeType(requestedOutputMimeType) .setSampleMimeType(requestedOutputMimeType)
.setColorInfo(getSupportedInputColor()) .setColorInfo(getSupportedInputColor())
.setInitializationData(
matchInitializationData ? inputFormat.initializationData : null)
.build(); .build();
encoder = encoder =

View File

@ -68,7 +68,8 @@ public final class VideoEncoderWrapperTest {
.build(), .build(),
/* muxerSupportedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264), /* muxerSupportedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264),
emptyTransformationRequest, emptyTransformationRequest,
fallbackListener); fallbackListener,
/* matchInitializationData= */ false);
@Before @Before
public void setUp() { public void setUp() {
@ -134,6 +135,52 @@ public final class VideoEncoderWrapperTest {
assertThat(surfaceInfo.height).isEqualTo(fallbackHeight); assertThat(surfaceInfo.height).isEqualTo(fallbackHeight);
} }
@Test
public void matchInitializationData_setToFalse_initializationDataNotPassedToEncoderFactory()
throws Exception {
VideoSampleExporter.EncoderWrapper encoderWrapper =
new VideoSampleExporter.EncoderWrapper(
fakeEncoderFactory,
/* inputFormat= */ new Format.Builder()
.setSampleMimeType(MimeTypes.VIDEO_H264)
.setColorInfo(ColorInfo.SDR_BT709_LIMITED)
.setInitializationData(ImmutableList.of(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))
.build(),
/* muxerSupportedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264),
emptyTransformationRequest,
fallbackListener,
/* matchInitializationData= */ false);
// Create the video encoder.
encoderWrapper.getSurfaceInfo(/* requestedWidth= */ 150, /* requestedHeight= */ 200);
assertThat(fakeEncoderFactory.format.initializationData).isEmpty();
}
@Test
public void matchInitializationData_setToTrue_initializationDataIsPassedToEncoderFactory()
throws Exception {
Format inputFormat =
new Format.Builder()
.setSampleMimeType(MimeTypes.VIDEO_H264)
.setColorInfo(ColorInfo.SDR_BT709_LIMITED)
.setInitializationData(ImmutableList.of(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))
.build();
VideoSampleExporter.EncoderWrapper encoderWrapper =
new VideoSampleExporter.EncoderWrapper(
fakeEncoderFactory,
inputFormat,
/* muxerSupportedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264),
emptyTransformationRequest,
fallbackListener,
/* matchInitializationData= */ true);
// Create the video encoder.
encoderWrapper.getSurfaceInfo(/* requestedWidth= */ 150, /* requestedHeight= */ 200);
assertThat(fakeEncoderFactory.format.initializationDataEquals(inputFormat)).isTrue();
}
private static void createShadowH264Encoder() { private static void createShadowH264Encoder() {
MediaFormat avcFormat = new MediaFormat(); MediaFormat avcFormat = new MediaFormat();
avcFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); avcFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC);
@ -169,6 +216,8 @@ public final class VideoEncoderWrapperTest {
private static class FakeVideoEncoderFactory implements Codec.EncoderFactory { private static class FakeVideoEncoderFactory implements Codec.EncoderFactory {
public Format format;
private int fallbackWidth; private int fallbackWidth;
private int fallbackHeight; private int fallbackHeight;
@ -189,6 +238,7 @@ public final class VideoEncoderWrapperTest {
@Override @Override
public Codec createForVideoEncoding(Format format) { public Codec createForVideoEncoding(Format format) {
this.format = format;
Codec mockEncoder = mock(Codec.class); Codec mockEncoder = mock(Codec.class);
if (fallbackWidth != C.LENGTH_UNSET) { if (fallbackWidth != C.LENGTH_UNSET) {
format = format.buildUpon().setWidth(fallbackWidth).build(); format = format.buildUpon().setWidth(fallbackWidth).build();