mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Allow RawAssetLoader
media to have unset duration
This will be useful for recording use cases, including screen recording with audio queued via `RawAssetLoader`, where the duration is unknown. PiperOrigin-RevId: 712895577
This commit is contained in:
parent
871381288c
commit
e11aabb794
@ -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<RawAssetLoader> 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<ExportResult> 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(
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user