diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/RawAssetLoaderAndroidTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/RawAssetLoaderAndroidTest.java index fa4ba1480f..3fc7efd818 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/RawAssetLoaderAndroidTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/RawAssetLoaderAndroidTest.java @@ -101,8 +101,36 @@ public class RawAssetLoaderAndroidTest { // See b/324245196. // Audio encoders on different API versions seems to output slightly different durations, so add // 50ms tolerance. - assertThat(exportResult.durationMs).isAtLeast(975); - assertThat(exportResult.durationMs).isAtMost(1025); + assertThat(exportResult.durationMs).isWithin(25).of(1000); + } + + @Test + public void audioTranscoding_withRawAudioAndUnsetDuration_completesWithCorrectDuration() + throws Exception { + SettableFuture rawAssetLoaderFuture = SettableFuture.create(); + Transformer transformer = + new Transformer.Builder(context) + .setAssetLoaderFactory( + new TestRawAssetLoaderFactory( + AUDIO_FORMAT, /* videoFormat= */ null, rawAssetLoaderFuture)) + .build(); + EditedMediaItem editedMediaItem = + new EditedMediaItem.Builder(MediaItem.fromUri(Uri.EMPTY)).build(); + ListenableFuture exportCompletionFuture = + new TransformerAndroidTestRunner.Builder(context, transformer) + .build() + .runAsync(testId, editedMediaItem); + + RawAssetLoader rawAssetLoader = rawAssetLoaderFuture.get(); + feedRawAudioDataToAssetLoader( + rawAssetLoader, AUDIO_FORMAT, /* durationUs= */ C.MICROS_PER_SECOND); + + ExportResult exportResult = exportCompletionFuture.get(); + // The durationMs is the timestamp of the last sample and not the total duration. + // See b/324245196. + // Audio encoders on different API versions seems to output slightly different durations, so add + // 50ms tolerance. + assertThat(exportResult.durationMs).isWithin(25).of(1000); } @Test @@ -242,8 +270,7 @@ public class RawAssetLoaderAndroidTest { // See b/324245196. // Audio encoders on different API versions seems to output slightly different durations, so add // 50ms tolerance. - assertThat(exportResult.durationMs).isAtLeast(975); - assertThat(exportResult.durationMs).isAtMost(1025); + assertThat(exportResult.durationMs).isWithin(25).of(1000); } private void feedRawAudioDataToAssetLoader( diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/RawAssetLoader.java b/libraries/transformer/src/main/java/androidx/media3/transformer/RawAssetLoader.java index 44eac1ef16..0abb48fc25 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/RawAssetLoader.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/RawAssetLoader.java @@ -23,6 +23,7 @@ import static androidx.media3.transformer.SampleConsumer.INPUT_RESULT_END_OF_STR import static androidx.media3.transformer.SampleConsumer.INPUT_RESULT_TRY_AGAIN_LATER; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED; +import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE; import static androidx.media3.transformer.TransformerUtil.getValidColor; import static java.lang.Math.min; import static java.lang.Math.round; @@ -96,7 +97,6 @@ public final class RawAssetLoader implements AssetLoader { @Nullable Format videoFormat, @Nullable OnInputFrameProcessedListener frameProcessedListener) { checkArgument(audioFormat != null || videoFormat != null); - checkArgument(editedMediaItem.durationUs != C.TIME_UNSET); checkArgument( videoFormat == null || (videoFormat.height != Format.NO_VALUE && videoFormat.width != Format.NO_VALUE)); @@ -119,7 +119,10 @@ public final class RawAssetLoader implements AssetLoader { @Override public void start() { - progressState = PROGRESS_STATE_AVAILABLE; + progressState = + editedMediaItem.durationUs == C.TIME_UNSET + ? PROGRESS_STATE_UNAVAILABLE + : PROGRESS_STATE_AVAILABLE; assetLoaderListener.onDurationUs(editedMediaItem.durationUs); // The constructor guarantees at least one track is present. int trackCount = 1; diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/RawAssetLoaderTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/RawAssetLoaderTest.java index 62600d6f4f..e9af7f3a73 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/RawAssetLoaderTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/RawAssetLoaderTest.java @@ -16,6 +16,7 @@ package androidx.media3.transformer; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE; +import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE; import static com.google.common.truth.Truth.assertThat; import static java.lang.Math.min; import static java.lang.Math.round; @@ -121,6 +122,30 @@ public class RawAssetLoaderTest { .isEqualTo(round(audioSamplePresentationTimeUs * 100 / (float) audioDurationUs)); } + @Test + public void getProgress_withOnlyAudioDataAndUnsetDuration_returnsUnavailableProgress() { + long audioSamplePresentationTimeUs = 100; + AssetLoader.Listener fakeAssetLoaderListener = + new FakeAssetLoaderListener(new FakeAudioSampleConsumer(), /* videoSampleConsumer= */ null); + ProgressHolder progressHolder = new ProgressHolder(); + + RawAssetLoader rawAssetLoader = + new RawAssetLoader( + new EditedMediaItem.Builder(new MediaItem.Builder().build()).build(), + fakeAssetLoaderListener, + FAKE_AUDIO_FORMAT, + /* videoFormat= */ null, + /* frameProcessedListener= */ null); + rawAssetLoader.start(); + boolean queuedAudioData = + rawAssetLoader.queueAudioData( + ByteBuffer.wrap(FAKE_AUDIO_DATA), audioSamplePresentationTimeUs, /* isLast= */ false); + @Transformer.ProgressState int progressState = rawAssetLoader.getProgress(progressHolder); + + assertThat(queuedAudioData).isTrue(); + assertThat(progressState).isEqualTo(PROGRESS_STATE_UNAVAILABLE); + } + @Test public void getProgress_withOnlyVideoData_returnsExpectedProgress() throws ExportException { long videoDurationUs = 1_000;