Skip to content

Commit 600db98

Browse files
ivanbupercopybara-github
authored andcommitted
Configure AudioProcessingPipeline with the current pendingStartTimeUs
Before this change, AudioGraph would ignore the last set pendingStartTimeUs when configuring the AudioProcessingPipeline for the first time, which happens when the AudioGraph registers its first input. PiperOrigin-RevId: 785868112
1 parent 34f9d1b commit 600db98

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

libraries/transformer/src/main/java/androidx/media3/transformer/AudioGraph.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ public static boolean isInputAudioFormatValid(AudioFormat format) {
8080
/**
8181
* Returns a new {@link AudioGraphInput} instance.
8282
*
83-
* <p>This method assumes the new input will start queueing its stream from the beginning.
84-
*
8583
* <p>Must be called before {@linkplain #getOutput() accessing output}.
8684
*/
8785
public AudioGraphInput registerInput(EditedMediaItem editedMediaItem, Format format)
@@ -93,7 +91,7 @@ public AudioGraphInput registerInput(EditedMediaItem editedMediaItem, Format for
9391
if (Objects.equals(mixerAudioFormat, AudioFormat.NOT_SET)) {
9492
this.mixerAudioFormat = audioGraphInput.getOutputAudioFormat();
9593
audioProcessingPipeline.configure(mixerAudioFormat);
96-
audioProcessingPipeline.flush(new StreamMetadata(/* positionOffsetUs= */ 0));
94+
audioProcessingPipeline.flush(new StreamMetadata(pendingStartTimeUs));
9795
}
9896
} catch (UnhandledAudioFormatException e) {
9997
throw ExportException.createForAudioProcessing(
@@ -122,7 +120,7 @@ public AudioFormat getOutputAudioFormat() {
122120
* Returns a {@link ByteBuffer} containing output data between the position and limit.
123121
*
124122
* <p>The same buffer is returned until it has been fully consumed ({@code position == limit}),
125-
* unless the graph was {@linkplain #flush() flushed}.
123+
* unless the graph was {@linkplain #flush flushed}.
126124
*/
127125
public ByteBuffer getOutput() throws ExportException {
128126
if (!ensureMixerReady()) {

libraries/transformer/src/test/java/androidx/media3/transformer/AudioGraphTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,70 @@ protected void onFlush(StreamMetadata streamMetadata) {
463463
assertThat(lastPositionOffsetUs.get()).isEqualTo(500_000);
464464
}
465465

466+
@Test
467+
public void flush_beforeRegisteringFirstInput_maintainsPreviousPositionOffset() throws Exception {
468+
AtomicLong lastPositionOffsetUs = new AtomicLong(C.TIME_UNSET);
469+
BaseAudioProcessor fakeProcessor =
470+
new PassthroughAudioProcessor() {
471+
@Override
472+
protected void onFlush(StreamMetadata streamMetadata) {
473+
lastPositionOffsetUs.set(streamMetadata.positionOffsetUs);
474+
}
475+
};
476+
AudioGraph audioGraph =
477+
new AudioGraph(
478+
new DefaultAudioMixer.Factory(), /* effects= */ ImmutableList.of(fakeProcessor));
479+
480+
audioGraph.flush(/* positionOffsetUs= */ 500_000);
481+
lastPositionOffsetUs.set(C.TIME_UNSET);
482+
audioGraph.registerInput(FAKE_ITEM, getPcmFormat(MONO_44100));
483+
484+
assertThat(lastPositionOffsetUs.get()).isEqualTo(500_000);
485+
}
486+
487+
@Test
488+
public void flush_multipleTimes_propagatesLastPositionOffsetAfterFirstInput() throws Exception {
489+
AtomicLong lastPositionOffsetUs = new AtomicLong(C.TIME_UNSET);
490+
BaseAudioProcessor fakeProcessor =
491+
new PassthroughAudioProcessor() {
492+
@Override
493+
protected void onFlush(StreamMetadata streamMetadata) {
494+
lastPositionOffsetUs.set(streamMetadata.positionOffsetUs);
495+
}
496+
};
497+
AudioGraph audioGraph =
498+
new AudioGraph(
499+
new DefaultAudioMixer.Factory(), /* effects= */ ImmutableList.of(fakeProcessor));
500+
501+
audioGraph.flush(/* positionOffsetUs= */ 500_000);
502+
audioGraph.flush(/* positionOffsetUs= */ 600_000);
503+
audioGraph.flush(/* positionOffsetUs= */ 700_000);
504+
audioGraph.registerInput(FAKE_ITEM, getPcmFormat(MONO_44100));
505+
506+
assertThat(lastPositionOffsetUs.get()).isEqualTo(700_000);
507+
}
508+
509+
@Test
510+
public void flush_afterRegisteringFirstInput_updatesPositionOffset() throws Exception {
511+
AtomicLong lastPositionOffsetUs = new AtomicLong(C.TIME_UNSET);
512+
BaseAudioProcessor fakeProcessor =
513+
new PassthroughAudioProcessor() {
514+
@Override
515+
protected void onFlush(StreamMetadata streamMetadata) {
516+
lastPositionOffsetUs.set(streamMetadata.positionOffsetUs);
517+
}
518+
};
519+
AudioGraph audioGraph =
520+
new AudioGraph(
521+
new DefaultAudioMixer.Factory(), /* effects= */ ImmutableList.of(fakeProcessor));
522+
523+
audioGraph.registerInput(FAKE_ITEM, getPcmFormat(MONO_44100));
524+
assertThat(lastPositionOffsetUs.get()).isEqualTo(0);
525+
audioGraph.flush(/* positionOffsetUs= */ 500_000);
526+
527+
assertThat(lastPositionOffsetUs.get()).isEqualTo(500_000);
528+
}
529+
466530
/** Drains the graph and returns the number of bytes output. */
467531
private static int drainAudioGraph(AudioGraph audioGraph) throws ExportException {
468532
int bytesOutput = 0;

0 commit comments

Comments
 (0)