mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add EditingMetricsCollector
test for export success
PiperOrigin-RevId: 727826326 (cherry picked from commit 3ce6a2e6b8b0b7147a06c5ec38aaf2ee36282720)
This commit is contained in:
parent
e58d9120bc
commit
16add9922d
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright 2025 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
|
||||
*
|
||||
* https://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 androidx.media3.transformer;
|
||||
|
||||
import static androidx.media3.common.util.Util.usToMs;
|
||||
import static androidx.media3.transformer.AndroidTestUtil.JPG_ASSET;
|
||||
import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET;
|
||||
import static androidx.media3.transformer.AndroidTestUtil.assumeFormatsSupported;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.metrics.EditingEndedEvent;
|
||||
import android.media.metrics.MediaItemInfo;
|
||||
import android.util.Size;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MediaLibraryInfo;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/** Instrumentation tests for metrics reporting using {@link EditingMetricsCollector} */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class EditingMetricsCollectorTest {
|
||||
private static final String EXPORTER_NAME =
|
||||
"androidx.media3.media3-transformer:" + MediaLibraryInfo.VERSION;
|
||||
|
||||
@Rule public final TestName testName = new TestName();
|
||||
private final Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
private String testId;
|
||||
|
||||
@Before
|
||||
public void setUpTestId() {
|
||||
testId = testName.getMethodName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exportSuccess_populatesEditingEndedEvent() throws Exception {
|
||||
assumeTrue("Reporting metrics requires API 35", Util.SDK_INT >= 35);
|
||||
assumeFormatsSupported(
|
||||
context,
|
||||
testId,
|
||||
/* inputFormat= */ MP4_ASSET.videoFormat,
|
||||
/* outputFormat= */ MP4_ASSET.videoFormat);
|
||||
AtomicReference<EditingEndedEvent> editingEndedEventAtomicReference = new AtomicReference<>();
|
||||
Transformer transformer =
|
||||
new Transformer.Builder(context)
|
||||
.setUsePlatformDiagnostics(true)
|
||||
.setMetricsReporterFactory(
|
||||
new TestMetricsReporterFactory(context, editingEndedEventAtomicReference::set))
|
||||
.build();
|
||||
EditedMediaItem audioVideoItem =
|
||||
new EditedMediaItem.Builder(MediaItem.fromUri(MP4_ASSET.uri)).build();
|
||||
EditedMediaItem imageItem =
|
||||
new EditedMediaItem.Builder(
|
||||
new MediaItem.Builder().setUri(JPG_ASSET.uri).setImageDurationMs(1500).build())
|
||||
.setFrameRate(30)
|
||||
.build();
|
||||
EditedMediaItemSequence videoImageSequence =
|
||||
new EditedMediaItemSequence.Builder(audioVideoItem, imageItem).build();
|
||||
EditedMediaItemSequence audioSequence =
|
||||
new EditedMediaItemSequence.Builder(
|
||||
new EditedMediaItem.Builder(MediaItem.fromUri(MP4_ASSET.uri))
|
||||
.setRemoveVideo(true)
|
||||
.build())
|
||||
.build();
|
||||
Composition composition = new Composition.Builder(videoImageSequence, audioSequence).build();
|
||||
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, composition);
|
||||
|
||||
EditingEndedEvent editingEndedEvent = editingEndedEventAtomicReference.get();
|
||||
assertThat(editingEndedEvent.getFinalState())
|
||||
.isEqualTo(EditingEndedEvent.FINAL_STATE_SUCCEEDED);
|
||||
assertThat(editingEndedEvent.getTimeSinceCreatedMillis()).isAtLeast(0);
|
||||
assertThat(editingEndedEvent.getExporterName()).isEqualTo(EXPORTER_NAME);
|
||||
assertThat(editingEndedEvent.getMuxerName()).isEqualTo(DefaultMuxer.MUXER_NAME);
|
||||
assertThat(editingEndedEvent.getFinalProgressPercent()).isEqualTo(100);
|
||||
// Assert video input media item information
|
||||
MediaItemInfo firstMediaItemInfo = editingEndedEvent.getInputMediaItemInfos().get(0);
|
||||
ExportResult.ProcessedInput firstProcessedInput =
|
||||
exportTestResult.exportResult.processedInputs.get(0);
|
||||
assertThat(firstMediaItemInfo.getClipDurationMillis())
|
||||
.isEqualTo(usToMs(firstProcessedInput.durationUs));
|
||||
assertThat(firstMediaItemInfo.getDataTypes())
|
||||
.isEqualTo(MediaItemInfo.DATA_TYPE_VIDEO | MediaItemInfo.DATA_TYPE_AUDIO);
|
||||
assertThat(firstMediaItemInfo.getContainerMimeType())
|
||||
.isEqualTo(firstProcessedInput.videoFormat.containerMimeType);
|
||||
assertThat(firstMediaItemInfo.getSampleMimeTypes().get(0))
|
||||
.isEqualTo(firstProcessedInput.videoFormat.sampleMimeType);
|
||||
assertThat(firstMediaItemInfo.getVideoFrameRate())
|
||||
.isEqualTo(firstProcessedInput.videoFormat.frameRate);
|
||||
assertThat(firstMediaItemInfo.getVideoSize())
|
||||
.isEqualTo(
|
||||
new Size(
|
||||
firstProcessedInput.videoFormat.width, firstProcessedInput.videoFormat.height));
|
||||
assertThat(firstMediaItemInfo.getSampleMimeTypes().get(1))
|
||||
.isEqualTo(firstProcessedInput.audioFormat.sampleMimeType);
|
||||
assertThat(firstMediaItemInfo.getAudioChannelCount())
|
||||
.isEqualTo(firstProcessedInput.audioFormat.channelCount);
|
||||
assertThat(firstMediaItemInfo.getAudioSampleRateHz())
|
||||
.isEqualTo(firstProcessedInput.audioFormat.sampleRate);
|
||||
// Assert image input media item and its silent audio
|
||||
MediaItemInfo secondMediaItemInfo = editingEndedEvent.getInputMediaItemInfos().get(1);
|
||||
ExportResult.ProcessedInput secondProcessedInput =
|
||||
exportTestResult.exportResult.processedInputs.get(1);
|
||||
assertThat(secondMediaItemInfo.getClipDurationMillis())
|
||||
.isEqualTo(usToMs(secondProcessedInput.durationUs));
|
||||
assertThat(secondMediaItemInfo.getDataTypes())
|
||||
.isEqualTo(MediaItemInfo.DATA_TYPE_IMAGE | MediaItemInfo.DATA_TYPE_AUDIO);
|
||||
assertThat(secondMediaItemInfo.getContainerMimeType())
|
||||
.isEqualTo(secondProcessedInput.videoFormat.containerMimeType);
|
||||
assertThat(secondMediaItemInfo.getSampleMimeTypes().get(0))
|
||||
.isEqualTo(secondProcessedInput.videoFormat.sampleMimeType);
|
||||
assertThat(secondMediaItemInfo.getVideoFrameRate())
|
||||
.isEqualTo(secondProcessedInput.videoFormat.frameRate);
|
||||
assertThat(secondMediaItemInfo.getVideoSize())
|
||||
.isEqualTo(
|
||||
new Size(
|
||||
secondProcessedInput.videoFormat.width, secondProcessedInput.videoFormat.height));
|
||||
assertThat(secondMediaItemInfo.getSampleMimeTypes().get(1))
|
||||
.isEqualTo(secondProcessedInput.audioFormat.sampleMimeType);
|
||||
assertThat(secondMediaItemInfo.getAudioChannelCount())
|
||||
.isEqualTo(secondProcessedInput.audioFormat.channelCount);
|
||||
assertThat(secondMediaItemInfo.getAudioSampleRateHz())
|
||||
.isEqualTo(secondProcessedInput.audioFormat.sampleRate);
|
||||
// Assert audio input media item information
|
||||
MediaItemInfo thirdMediaItemInfo = editingEndedEvent.getInputMediaItemInfos().get(2);
|
||||
ExportResult.ProcessedInput thirdProcessedInput =
|
||||
exportTestResult.exportResult.processedInputs.get(2);
|
||||
assertThat(thirdMediaItemInfo.getClipDurationMillis())
|
||||
.isEqualTo(usToMs(thirdProcessedInput.durationUs));
|
||||
assertThat(thirdMediaItemInfo.getDataTypes()).isEqualTo(MediaItemInfo.DATA_TYPE_AUDIO);
|
||||
assertThat(thirdMediaItemInfo.getSampleMimeTypes().get(0))
|
||||
.isEqualTo(thirdProcessedInput.audioFormat.sampleMimeType);
|
||||
assertThat(thirdMediaItemInfo.getAudioChannelCount())
|
||||
.isEqualTo(thirdProcessedInput.audioFormat.channelCount);
|
||||
assertThat(thirdMediaItemInfo.getAudioSampleRateHz())
|
||||
.isEqualTo(thirdProcessedInput.audioFormat.sampleRate);
|
||||
// Assert output media item information
|
||||
MediaItemInfo outputMediaItemInfo = editingEndedEvent.getOutputMediaItemInfo();
|
||||
assertThat(outputMediaItemInfo).isNotNull();
|
||||
assertThat(outputMediaItemInfo.getDurationMillis())
|
||||
.isEqualTo(exportTestResult.exportResult.durationMs);
|
||||
assertThat(outputMediaItemInfo.getSampleMimeTypes()).isNotEmpty();
|
||||
assertThat(outputMediaItemInfo.getAudioChannelCount())
|
||||
.isEqualTo(exportTestResult.exportResult.channelCount);
|
||||
assertThat(outputMediaItemInfo.getAudioSampleRateHz())
|
||||
.isEqualTo(exportTestResult.exportResult.sampleRate);
|
||||
assertThat(outputMediaItemInfo.getCodecNames().get(0))
|
||||
.isEqualTo(exportTestResult.exportResult.audioEncoderName);
|
||||
assertThat(outputMediaItemInfo.getCodecNames().get(1))
|
||||
.isEqualTo(exportTestResult.exportResult.videoEncoderName);
|
||||
assertThat(outputMediaItemInfo.getVideoSampleCount())
|
||||
.isEqualTo(exportTestResult.exportResult.videoFrameCount);
|
||||
assertThat(outputMediaItemInfo.getVideoSize())
|
||||
.isEqualTo(
|
||||
new Size(exportTestResult.exportResult.width, exportTestResult.exportResult.height));
|
||||
}
|
||||
|
||||
private static final class TestMetricsReporterFactory
|
||||
implements EditingMetricsCollector.MetricsReporter.Factory {
|
||||
|
||||
private final EditingMetricsCollector.MetricsReporter.Factory wrappedMetricsReporterFactory;
|
||||
private final TestMetricsReporter.Listener listener;
|
||||
|
||||
public TestMetricsReporterFactory(Context context, TestMetricsReporter.Listener listener) {
|
||||
this.wrappedMetricsReporterFactory =
|
||||
new EditingMetricsCollector.DefaultMetricsReporter.Factory(context);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditingMetricsCollector.MetricsReporter create() {
|
||||
return new TestMetricsReporter(wrappedMetricsReporterFactory.create(), listener);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TestMetricsReporter
|
||||
implements EditingMetricsCollector.MetricsReporter {
|
||||
public interface Listener {
|
||||
void onMetricsReported(EditingEndedEvent editingEndedEvent);
|
||||
}
|
||||
|
||||
private final EditingMetricsCollector.MetricsReporter wrappedMetricsReporter;
|
||||
private final TestMetricsReporter.Listener listener;
|
||||
|
||||
private TestMetricsReporter(
|
||||
EditingMetricsCollector.MetricsReporter metricsReporter,
|
||||
TestMetricsReporter.Listener listener) {
|
||||
this.wrappedMetricsReporter = metricsReporter;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportMetrics(EditingEndedEvent editingEndedEvent) {
|
||||
listener.onMetricsReported(editingEndedEvent);
|
||||
wrappedMetricsReporter.reportMetrics(editingEndedEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
wrappedMetricsReporter.close();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user