mirror of
https://github.com/androidx/media.git
synced 2025-05-09 16:40:55 +08:00
Add ImageAssetLoader tests.
PiperOrigin-RevId: 514431184
This commit is contained in:
parent
55f2d1a5e2
commit
6188952682
@ -53,6 +53,9 @@ public final class AndroidTestUtil {
|
||||
*/
|
||||
public static final int MEDIA_CODEC_PRIORITY_NON_REALTIME = 1;
|
||||
|
||||
public static final String PNG_ASSET_URI_STRING =
|
||||
"asset:///media/bitmap/input_images/media3test.png";
|
||||
|
||||
public static final String MP4_ASSET_URI_STRING = "asset:///media/mp4/sample.mp4";
|
||||
public static final Format MP4_ASSET_FORMAT =
|
||||
new Format.Builder()
|
||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.transformer;
|
||||
|
||||
import static com.google.android.exoplayer2.transformer.AndroidTestUtil.MP4_ASSET_URI_STRING;
|
||||
import static com.google.android.exoplayer2.transformer.AndroidTestUtil.MP4_ASSET_WITH_INCREASING_TIMESTAMPS_320W_240H_15S_URI_STRING;
|
||||
import static com.google.android.exoplayer2.transformer.AndroidTestUtil.PNG_ASSET_URI_STRING;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
@ -24,6 +25,7 @@ import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.effect.Presentation;
|
||||
@ -41,6 +43,53 @@ public class TransformerEndToEndTest {
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@Test
|
||||
public void videoEditing_withImageInput_completesWithCorrectFrameCountAndDuration()
|
||||
throws Exception {
|
||||
String testId = "videoEditing_withImageInput_completesWithCorrectFrameCountAndDuration";
|
||||
Transformer transformer = new Transformer.Builder(context).build();
|
||||
ImmutableList<Effect> videoEffects = ImmutableList.of(Presentation.createForHeight(480));
|
||||
Effects effects = new Effects(/* audioProcessors= */ ImmutableList.of(), videoEffects);
|
||||
int expectedFrameCount = 40;
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(MediaItem.fromUri(PNG_ASSET_URI_STRING))
|
||||
.setDurationUs(C.MICROS_PER_SECOND)
|
||||
.setFrameRate(expectedFrameCount)
|
||||
.setEffects(effects)
|
||||
.build();
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
|
||||
assertThat(result.exportResult.videoFrameCount).isEqualTo(expectedFrameCount);
|
||||
// Expected timestamp of the last frame.
|
||||
assertThat(result.exportResult.durationMs)
|
||||
.isEqualTo((C.MILLIS_PER_SECOND / expectedFrameCount) * (expectedFrameCount - 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void videoTranscoding_withImageInput_completesWithCorrectFrameCountAndDuration()
|
||||
throws Exception {
|
||||
String testId = "videoTranscoding_withImageInput_completesWithCorrectFrameCountAndDuration";
|
||||
Transformer transformer = new Transformer.Builder(context).build();
|
||||
int expectedFrameCount = 40;
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(MediaItem.fromUri(PNG_ASSET_URI_STRING))
|
||||
.setDurationUs(C.MICROS_PER_SECOND)
|
||||
.setFrameRate(expectedFrameCount)
|
||||
.build();
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
|
||||
assertThat(result.exportResult.videoFrameCount).isEqualTo(expectedFrameCount);
|
||||
// Expected timestamp of the last frame.
|
||||
assertThat(result.exportResult.durationMs)
|
||||
.isEqualTo((C.MILLIS_PER_SECOND / expectedFrameCount) * (expectedFrameCount - 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void videoEditing_completesWithConsistentFrameCount() throws Exception {
|
||||
Transformer transformer =
|
||||
|
@ -253,22 +253,4 @@ public class ExportTest {
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exportImage() throws Exception {
|
||||
// TODO(b/262693274): consider removing this test when Robolectric tests have been added for
|
||||
// image input.
|
||||
String testId = TAG + "_exportImage";
|
||||
Context context = ApplicationProvider.getApplicationContext();
|
||||
Transformer transformer = new Transformer.Builder(context).build();
|
||||
String imageUri = "https://storage.googleapis.com/exoplayer-test-media-1/jpg/london.jpg";
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(MediaItem.fromUri(imageUri))
|
||||
.setDurationUs(1_000_000)
|
||||
.setFrameRate(30)
|
||||
.build();
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.transformer;
|
||||
|
||||
import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runLooperUntil;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.shadows.ShadowSystemClock;
|
||||
|
||||
/** Unit tests for {@link ExoPlayerAssetLoader}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ImageAssetLoaderTest {
|
||||
|
||||
@Test
|
||||
public void imageAssetLoader_callsListenerCallbacksInRightOrder() throws Exception {
|
||||
HandlerThread assetLoaderThread = new HandlerThread("AssetLoaderThread");
|
||||
assetLoaderThread.start();
|
||||
Looper assetLoaderLooper = assetLoaderThread.getLooper();
|
||||
AtomicReference<Exception> exceptionRef = new AtomicReference<>();
|
||||
AtomicBoolean isOutputFormatSet = new AtomicBoolean();
|
||||
AssetLoader.Listener listener =
|
||||
new AssetLoader.Listener() {
|
||||
|
||||
private volatile boolean isDurationSet;
|
||||
private volatile boolean isTrackCountSet;
|
||||
private volatile boolean isTrackAdded;
|
||||
|
||||
@Override
|
||||
public void onDurationUs(long durationUs) {
|
||||
sleep();
|
||||
isDurationSet = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackCount(int trackCount) {
|
||||
// Sleep to increase the chances of the test failing.
|
||||
sleep();
|
||||
isTrackCountSet = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTrackAdded(
|
||||
Format inputFormat,
|
||||
@AssetLoader.SupportedOutputTypes int supportedOutputTypes,
|
||||
long streamStartPositionUs,
|
||||
long streamOffsetUs) {
|
||||
if (!isTrackCountSet) {
|
||||
exceptionRef.set(
|
||||
new IllegalStateException("onTrackAdded() called before onTrackCount()"));
|
||||
}
|
||||
sleep();
|
||||
isTrackAdded = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleConsumer onOutputFormat(Format format) {
|
||||
|
||||
if (!isDurationSet) {
|
||||
exceptionRef.set(
|
||||
new IllegalStateException("onTrackAdded() called before onDurationUs()"));
|
||||
} else if (!isTrackAdded) {
|
||||
exceptionRef.set(
|
||||
new IllegalStateException("onOutputFormat() called before onTrackAdded()"));
|
||||
}
|
||||
isOutputFormatSet.set(true);
|
||||
return new FakeSampleConsumer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ExportException e) {
|
||||
exceptionRef.set(e);
|
||||
}
|
||||
|
||||
void sleep() {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
exceptionRef.set(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
AssetLoader assetLoader = getAssetLoader(assetLoaderLooper, listener);
|
||||
|
||||
new Handler(assetLoaderLooper).post(assetLoader::start);
|
||||
runLooperUntil(
|
||||
Looper.myLooper(),
|
||||
() -> {
|
||||
ShadowSystemClock.advanceBy(Duration.ofMillis(10));
|
||||
return isOutputFormatSet.get() || exceptionRef.get() != null;
|
||||
});
|
||||
|
||||
assertThat(exceptionRef.get()).isNull();
|
||||
}
|
||||
|
||||
private static AssetLoader getAssetLoader(Looper looper, AssetLoader.Listener listener) {
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(
|
||||
MediaItem.fromUri("asset:///media/bitmap/input_images/media3test.png"))
|
||||
.setDurationUs(1_000_000)
|
||||
.setFrameRate(30)
|
||||
.build();
|
||||
return new ImageAssetLoader.Factory(ApplicationProvider.getApplicationContext())
|
||||
.createAssetLoader(editedMediaItem, looper, listener);
|
||||
}
|
||||
|
||||
private static final class FakeSampleConsumer implements SampleConsumer {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DecoderInputBuffer getInputBuffer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueInputBuffer() {}
|
||||
|
||||
@Override
|
||||
public void queueInputBitmap(Bitmap inputBitmap, long durationUs, int frameRate) {}
|
||||
|
||||
@Override
|
||||
public void signalEndOfVideoInput() {}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user