Commit a3f981ae by samrobinson Committed by Ian Baker

Output from the Transformer the average audio & video bitrates.

PiperOrigin-RevId: 426956151
parent 60d9ae47
...@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.MediaItem; ...@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.transformer.ProgressHolder; import com.google.android.exoplayer2.transformer.ProgressHolder;
import com.google.android.exoplayer2.transformer.TransformationException; import com.google.android.exoplayer2.transformer.TransformationException;
import com.google.android.exoplayer2.transformer.TransformationRequest; import com.google.android.exoplayer2.transformer.TransformationRequest;
import com.google.android.exoplayer2.transformer.TransformationResult;
import com.google.android.exoplayer2.transformer.Transformer; import com.google.android.exoplayer2.transformer.Transformer;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.StyledPlayerView; import com.google.android.exoplayer2.ui.StyledPlayerView;
...@@ -223,7 +224,8 @@ public final class TransformerActivity extends AppCompatActivity { ...@@ -223,7 +224,8 @@ public final class TransformerActivity extends AppCompatActivity {
.addListener( .addListener(
new Transformer.Listener() { new Transformer.Listener() {
@Override @Override
public void onTransformationCompleted(MediaItem mediaItem) { public void onTransformationCompleted(
MediaItem mediaItem, TransformationResult transformationResult) {
TransformerActivity.this.onTransformationCompleted(filePath); TransformerActivity.this.onTransformationCompleted(filePath);
} }
......
...@@ -65,7 +65,7 @@ app is notified of events via the listener passed to the `Transformer` builder. ...@@ -65,7 +65,7 @@ app is notified of events via the listener passed to the `Transformer` builder.
Transformer.Listener transformerListener = Transformer.Listener transformerListener =
new Transformer.Listener() { new Transformer.Listener() {
@Override @Override
public void onTransformationCompleted(MediaItem inputMediaItem) { public void onTransformationCompleted(MediaItem inputMediaItem, TransformationResult transformationResult) {
playOutput(); playOutput();
} }
......
...@@ -69,6 +69,9 @@ public final class C { ...@@ -69,6 +69,9 @@ public final class C {
/** Represents an unset or unknown rate. */ /** Represents an unset or unknown rate. */
public static final float RATE_UNSET = -Float.MAX_VALUE; public static final float RATE_UNSET = -Float.MAX_VALUE;
/** Represents an unset or unknown integer rate. */
public static final int RATE_UNSET_INT = Integer.MIN_VALUE + 1;
/** Represents an unset or unknown length. */ /** Represents an unset or unknown length. */
public static final int LENGTH_UNSET = -1; public static final int LENGTH_UNSET = -1;
......
...@@ -24,6 +24,7 @@ import android.net.Uri; ...@@ -24,6 +24,7 @@ import android.net.Uri;
import android.os.Build; import android.os.Build;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.platform.app.InstrumentationRegistry;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
...@@ -39,50 +40,6 @@ public final class AndroidTestUtil { ...@@ -39,50 +40,6 @@ public final class AndroidTestUtil {
public static final String REMOTE_MP4_10_SECONDS_URI_STRING = public static final String REMOTE_MP4_10_SECONDS_URI_STRING =
"https://storage.googleapis.com/exoplayer-test-media-1/mp4/android-screens-10s.mp4"; "https://storage.googleapis.com/exoplayer-test-media-1/mp4/android-screens-10s.mp4";
/** Information about the result of successfully running a transformer. */
public static final class TransformationResult {
/** A builder for {@link TransformationResult} instances. */
public static final class Builder {
private final String testId;
@Nullable private Long fileSizeBytes;
public Builder(String testId) {
this.testId = testId;
}
public Builder setFileSizeBytes(long fileSizeBytes) {
this.fileSizeBytes = fileSizeBytes;
return this;
}
public TransformationResult build() {
return new TransformationResult(testId, fileSizeBytes);
}
}
public final String testId;
@Nullable public final Long fileSizeBytes;
private TransformationResult(String testId, @Nullable Long fileSizeBytes) {
this.testId = testId;
this.fileSizeBytes = fileSizeBytes;
}
/**
* Returns all the analysis data from the test.
*
* <p>If a value was not generated, it will not be part of the return value.
*/
public String getFormattedAnalysis() {
String analysis = "test=" + testId;
if (fileSizeBytes != null) {
analysis += ", fileSizeBytes=" + fileSizeBytes;
}
return analysis;
}
}
/** /**
* Transforms the {@code uriString} with the {@link Transformer}. * Transforms the {@code uriString} with the {@link Transformer}.
* *
...@@ -98,6 +55,7 @@ public final class AndroidTestUtil { ...@@ -98,6 +55,7 @@ public final class AndroidTestUtil {
Context context, String testId, Transformer transformer, String uriString, int timeoutSeconds) Context context, String testId, Transformer transformer, String uriString, int timeoutSeconds)
throws Exception { throws Exception {
AtomicReference<@NullableType Exception> exceptionReference = new AtomicReference<>(); AtomicReference<@NullableType Exception> exceptionReference = new AtomicReference<>();
AtomicReference<TransformationResult> resultReference = new AtomicReference<>();
CountDownLatch countDownLatch = new CountDownLatch(1); CountDownLatch countDownLatch = new CountDownLatch(1);
Transformer testTransformer = Transformer testTransformer =
...@@ -106,7 +64,9 @@ public final class AndroidTestUtil { ...@@ -106,7 +64,9 @@ public final class AndroidTestUtil {
.addListener( .addListener(
new Transformer.Listener() { new Transformer.Listener() {
@Override @Override
public void onTransformationCompleted(MediaItem inputMediaItem) { public void onTransformationCompleted(
MediaItem inputMediaItem, TransformationResult result) {
resultReference.set(result);
countDownLatch.countDown(); countDownLatch.countDown();
} }
...@@ -141,19 +101,21 @@ public final class AndroidTestUtil { ...@@ -141,19 +101,21 @@ public final class AndroidTestUtil {
} }
TransformationResult result = TransformationResult result =
new TransformationResult.Builder(testId).setFileSizeBytes(outputVideoFile.length()).build(); resultReference.get().buildUpon().setFileSizeBytes(outputVideoFile.length()).build();
writeTransformationResultToFile(context, result); writeResultToFile(context, testId, result);
return result; return result;
} }
private static void writeTransformationResultToFile(Context context, TransformationResult result) private static void writeResultToFile(Context context, String testId, TransformationResult result)
throws IOException { throws IOException {
File analysisFile = File analysisFile = createExternalCacheFile(context, /* fileName= */ testId + "-result.txt");
createExternalCacheFile(context, /* fileName= */ result.testId + "-result.txt");
try (FileWriter fileWriter = new FileWriter(analysisFile)) { try (FileWriter fileWriter = new FileWriter(analysisFile)) {
String fileContents = String fileContents =
result.getFormattedAnalysis() "test="
+ testId
+ ", "
+ getFormattedResult(result)
+ ", deviceFingerprint=" + ", deviceFingerprint="
+ Build.FINGERPRINT + Build.FINGERPRINT
+ ", deviceBrand=" + ", deviceBrand="
...@@ -166,6 +128,22 @@ public final class AndroidTestUtil { ...@@ -166,6 +128,22 @@ public final class AndroidTestUtil {
} }
} }
/** Formats a {@link TransformationResult} into a comma separated String. */
public static String getFormattedResult(TransformationResult result) {
String analysis = "";
if (result.fileSizeBytes != C.LENGTH_UNSET) {
analysis += "fileSizeBytes=" + result.fileSizeBytes;
}
if (result.averageAudioBitrate != C.RATE_UNSET_INT) {
analysis += ", averageAudioBitrate=" + result.averageAudioBitrate;
}
if (result.averageVideoBitrate != C.RATE_UNSET_INT) {
analysis += ", averageVideoBitrate=" + result.averageVideoBitrate;
}
return analysis;
}
private static File createExternalCacheFile(Context context, String fileName) throws IOException { private static File createExternalCacheFile(Context context, String fileName) throws IOException {
File file = new File(context.getExternalCacheDir(), fileName); File file = new File(context.getExternalCacheDir(), fileName);
checkState(!file.exists() || file.delete(), "Could not delete file: " + file.getAbsolutePath()); checkState(!file.exists() || file.delete(), "Could not delete file: " + file.getAbsolutePath());
......
...@@ -24,6 +24,7 @@ import androidx.test.core.app.ApplicationProvider; ...@@ -24,6 +24,7 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.transformer.AndroidTestUtil; import com.google.android.exoplayer2.transformer.AndroidTestUtil;
import com.google.android.exoplayer2.transformer.TransformationRequest; import com.google.android.exoplayer2.transformer.TransformationRequest;
import com.google.android.exoplayer2.transformer.TransformationResult;
import com.google.android.exoplayer2.transformer.Transformer; import com.google.android.exoplayer2.transformer.Transformer;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
...@@ -57,7 +58,7 @@ public final class RepeatedTranscodeTransformationTest { ...@@ -57,7 +58,7 @@ public final class RepeatedTranscodeTransformationTest {
Set<Long> differentOutputSizesBytes = new HashSet<>(); Set<Long> differentOutputSizesBytes = new HashSet<>();
for (int i = 0; i < TRANSCODE_COUNT; i++) { for (int i = 0; i < TRANSCODE_COUNT; i++) {
// Use a long video in case an error occurs a while after the start of the video. // Use a long video in case an error occurs a while after the start of the video.
AndroidTestUtil.TransformationResult result = TransformationResult result =
runTransformer( runTransformer(
context, context,
/* testId= */ "repeatedTranscode_givesConsistentLengthOutput_" + i, /* testId= */ "repeatedTranscode_givesConsistentLengthOutput_" + i,
...@@ -91,7 +92,7 @@ public final class RepeatedTranscodeTransformationTest { ...@@ -91,7 +92,7 @@ public final class RepeatedTranscodeTransformationTest {
Set<Long> differentOutputSizesBytes = new HashSet<>(); Set<Long> differentOutputSizesBytes = new HashSet<>();
for (int i = 0; i < TRANSCODE_COUNT; i++) { for (int i = 0; i < TRANSCODE_COUNT; i++) {
// Use a long video in case an error occurs a while after the start of the video. // Use a long video in case an error occurs a while after the start of the video.
AndroidTestUtil.TransformationResult result = TransformationResult result =
runTransformer( runTransformer(
context, context,
/* testId= */ "repeatedTranscodeNoAudio_givesConsistentLengthOutput_" + i, /* testId= */ "repeatedTranscodeNoAudio_givesConsistentLengthOutput_" + i,
...@@ -122,7 +123,7 @@ public final class RepeatedTranscodeTransformationTest { ...@@ -122,7 +123,7 @@ public final class RepeatedTranscodeTransformationTest {
Set<Long> differentOutputSizesBytes = new HashSet<>(); Set<Long> differentOutputSizesBytes = new HashSet<>();
for (int i = 0; i < TRANSCODE_COUNT; i++) { for (int i = 0; i < TRANSCODE_COUNT; i++) {
// Use a long video in case an error occurs a while after the start of the video. // Use a long video in case an error occurs a while after the start of the video.
AndroidTestUtil.TransformationResult result = TransformationResult result =
runTransformer( runTransformer(
context, context,
/* testId= */ "repeatedTranscodeNoVideo_givesConsistentLengthOutput_" + i, /* testId= */ "repeatedTranscodeNoVideo_givesConsistentLengthOutput_" + i,
......
...@@ -48,6 +48,7 @@ import java.nio.ByteBuffer; ...@@ -48,6 +48,7 @@ import java.nio.ByteBuffer;
private final Muxer.Factory muxerFactory; private final Muxer.Factory muxerFactory;
private final SparseIntArray trackTypeToIndex; private final SparseIntArray trackTypeToIndex;
private final SparseLongArray trackTypeToTimeUs; private final SparseLongArray trackTypeToTimeUs;
private final SparseLongArray trackTypeToBytesWritten;
private final String containerMimeType; private final String containerMimeType;
private int trackCount; private int trackCount;
...@@ -62,6 +63,7 @@ import java.nio.ByteBuffer; ...@@ -62,6 +63,7 @@ import java.nio.ByteBuffer;
this.containerMimeType = containerMimeType; this.containerMimeType = containerMimeType;
trackTypeToIndex = new SparseIntArray(); trackTypeToIndex = new SparseIntArray();
trackTypeToTimeUs = new SparseLongArray(); trackTypeToTimeUs = new SparseLongArray();
trackTypeToBytesWritten = new SparseLongArray();
previousTrackType = C.TRACK_TYPE_NONE; previousTrackType = C.TRACK_TYPE_NONE;
} }
...@@ -121,6 +123,7 @@ import java.nio.ByteBuffer; ...@@ -121,6 +123,7 @@ import java.nio.ByteBuffer;
int trackIndex = muxer.addTrack(format); int trackIndex = muxer.addTrack(format);
trackTypeToIndex.put(trackType, trackIndex); trackTypeToIndex.put(trackType, trackIndex);
trackTypeToTimeUs.put(trackType, 0L); trackTypeToTimeUs.put(trackType, 0L);
trackTypeToBytesWritten.put(trackType, 0L);
trackFormatCount++; trackFormatCount++;
if (trackFormatCount == trackCount) { if (trackFormatCount == trackCount) {
isReady = true; isReady = true;
...@@ -154,8 +157,11 @@ import java.nio.ByteBuffer; ...@@ -154,8 +157,11 @@ import java.nio.ByteBuffer;
return false; return false;
} }
muxer.writeSampleData(trackIndex, data, isKeyFrame, presentationTimeUs); trackTypeToBytesWritten.put(
trackType, trackTypeToBytesWritten.get(trackType) + data.remaining());
trackTypeToTimeUs.put(trackType, presentationTimeUs); trackTypeToTimeUs.put(trackType, presentationTimeUs);
muxer.writeSampleData(trackIndex, data, isKeyFrame, presentationTimeUs);
previousTrackType = trackType; previousTrackType = trackType;
return true; return true;
} }
...@@ -168,7 +174,6 @@ import java.nio.ByteBuffer; ...@@ -168,7 +174,6 @@ import java.nio.ByteBuffer;
*/ */
public void endTrack(@C.TrackType int trackType) { public void endTrack(@C.TrackType int trackType) {
trackTypeToIndex.delete(trackType); trackTypeToIndex.delete(trackType);
trackTypeToTimeUs.delete(trackType);
} }
/** /**
...@@ -192,6 +197,25 @@ import java.nio.ByteBuffer; ...@@ -192,6 +197,25 @@ import java.nio.ByteBuffer;
} }
/** /**
* Returns the average bitrate of data written to the track of the provided {@code trackType}, or
* {@link C#RATE_UNSET_INT} if there is no track data.
*/
public int getTrackAverageBitrate(@C.TrackType int trackType) {
long trackDurationUs = trackTypeToTimeUs.get(trackType, /* valueIfKeyNotFound= */ -1);
long trackBytes = trackTypeToBytesWritten.get(trackType, /* valueIfKeyNotFound= */ -1);
if (trackDurationUs <= 0 || trackBytes <= 0) {
return C.RATE_UNSET_INT;
}
// The number of bytes written is not a timestamp, however this utility method provides
// overflow-safe multiplication & division.
return (int)
Util.scaleLargeTimestamp(
/* timestamp= */ trackBytes,
/* multiplier= */ C.BITS_PER_BYTE * C.MICROS_PER_SECOND,
/* divisor= */ trackDurationUs);
}
/**
* Returns whether the muxer can write a sample of the given track type. * Returns whether the muxer can write a sample of the given track type.
* *
* @param trackType The track type, defined by the {@code TRACK_TYPE_*} constants in {@link C}. * @param trackType The track type, defined by the {@code TRACK_TYPE_*} constants in {@link C}.
...@@ -208,7 +232,7 @@ import java.nio.ByteBuffer; ...@@ -208,7 +232,7 @@ import java.nio.ByteBuffer;
if (!isReady) { if (!isReady) {
return false; return false;
} }
if (trackTypeToTimeUs.size() == 1) { if (trackTypeToIndex.size() == 1) {
return true; return true;
} }
if (trackType != previousTrackType) { if (trackType != previousTrackType) {
......
/*
* Copyright 2022 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.util.Assertions.checkArgument;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
/** Information about the result of a successful transformation. */
public final class TransformationResult {
/** A builder for {@link TransformationResult} instances. */
public static final class Builder {
private long fileSizeBytes;
private int averageAudioBitrate;
private int averageVideoBitrate;
public Builder() {
fileSizeBytes = C.LENGTH_UNSET;
averageAudioBitrate = C.RATE_UNSET_INT;
averageVideoBitrate = C.RATE_UNSET_INT;
}
/**
* Sets the file size in bytes.
*
* <p>Input must be positive or {@link C#LENGTH_UNSET}.
*/
public Builder setFileSizeBytes(long fileSizeBytes) {
checkArgument(fileSizeBytes > 0 || fileSizeBytes == C.LENGTH_UNSET);
this.fileSizeBytes = fileSizeBytes;
return this;
}
/**
* Sets the average audio bitrate.
*
* <p>Input must be positive or {@link C#RATE_UNSET_INT}.
*/
public Builder setAverageAudioBitrate(int averageAudioBitrate) {
checkArgument(averageAudioBitrate > 0 || averageAudioBitrate == C.RATE_UNSET_INT);
this.averageAudioBitrate = averageAudioBitrate;
return this;
}
/**
* Sets the average video bitrate.
*
* <p>Input must be positive or {@link C#RATE_UNSET_INT}.
*/
public Builder setAverageVideoBitrate(int averageVideoBitrate) {
checkArgument(averageVideoBitrate > 0 || averageVideoBitrate == C.RATE_UNSET_INT);
this.averageVideoBitrate = averageVideoBitrate;
return this;
}
public TransformationResult build() {
return new TransformationResult(fileSizeBytes, averageAudioBitrate, averageVideoBitrate);
}
}
/** The size of the file in bytes, or {@link C#LENGTH_UNSET} if unset or unknown. */
public final long fileSizeBytes;
/**
* The average bitrate of the audio track data, or {@link C#RATE_UNSET_INT} if unset or unknown.
*/
public final int averageAudioBitrate;
/**
* The average bitrate of the video track data, or {@link C#RATE_UNSET_INT} if unset or unknown.
*/
public final int averageVideoBitrate;
private TransformationResult(
long fileSizeBytes, int averageAudioBitrate, int averageVideoBitrate) {
this.fileSizeBytes = fileSizeBytes;
this.averageAudioBitrate = averageAudioBitrate;
this.averageVideoBitrate = averageVideoBitrate;
}
public Builder buildUpon() {
return new Builder()
.setFileSizeBytes(fileSizeBytes)
.setAverageAudioBitrate(averageAudioBitrate)
.setAverageVideoBitrate(averageVideoBitrate);
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (!(o instanceof TransformationResult)) {
return false;
}
TransformationResult result = (TransformationResult) o;
return fileSizeBytes == result.fileSizeBytes
&& averageAudioBitrate == result.averageAudioBitrate
&& averageVideoBitrate == result.averageVideoBitrate;
}
@Override
public int hashCode() {
int result = (int) fileSizeBytes;
result = 31 * result + averageAudioBitrate;
result = 31 * result + averageVideoBitrate;
return result;
}
}
...@@ -444,11 +444,21 @@ public final class Transformer { ...@@ -444,11 +444,21 @@ public final class Transformer {
public interface Listener { public interface Listener {
/** /**
* @deprecated Use {@link #onTransformationCompleted(MediaItem, TransformationResult)} instead.
*/
@Deprecated
default void onTransformationCompleted(MediaItem inputMediaItem) {}
/**
* Called when the transformation is completed successfully. * Called when the transformation is completed successfully.
* *
* @param inputMediaItem The {@link MediaItem} for which the transformation is completed. * @param inputMediaItem The {@link MediaItem} for which the transformation is completed.
* @param transformationResult The {@link TransformationResult} of the transformation.
*/ */
default void onTransformationCompleted(MediaItem inputMediaItem) {} default void onTransformationCompleted(
MediaItem inputMediaItem, TransformationResult transformationResult) {
onTransformationCompleted(inputMediaItem);
}
/** @deprecated Use {@link #onTransformationError(MediaItem, TransformationException)}. */ /** @deprecated Use {@link #onTransformationError(MediaItem, TransformationException)}. */
@Deprecated @Deprecated
...@@ -733,8 +743,9 @@ public final class Transformer { ...@@ -733,8 +743,9 @@ public final class Transformer {
* Returns the current {@link ProgressState} and updates {@code progressHolder} with the current * Returns the current {@link ProgressState} and updates {@code progressHolder} with the current
* progress if it is {@link #PROGRESS_STATE_AVAILABLE available}. * progress if it is {@link #PROGRESS_STATE_AVAILABLE available}.
* *
* <p>After a transformation {@link Listener#onTransformationCompleted(MediaItem) completes}, this * <p>After a transformation {@link Listener#onTransformationCompleted(MediaItem,
* method returns {@link #PROGRESS_STATE_NO_TRANSFORMATION}. * TransformationResult) completes}, this method returns {@link
* #PROGRESS_STATE_NO_TRANSFORMATION}.
* *
* @param progressHolder A {@link ProgressHolder}, updated to hold the percentage progress if * @param progressHolder A {@link ProgressHolder}, updated to hold the percentage progress if
* {@link #PROGRESS_STATE_AVAILABLE available}. * {@link #PROGRESS_STATE_AVAILABLE available}.
...@@ -950,9 +961,14 @@ public final class Transformer { ...@@ -950,9 +961,14 @@ public final class Transformer {
/* eventFlag= */ C.INDEX_UNSET, /* eventFlag= */ C.INDEX_UNSET,
listener -> listener.onTransformationError(mediaItem, finalException)); listener -> listener.onTransformationError(mediaItem, finalException));
} else { } else {
TransformationResult result =
new TransformationResult.Builder()
.setAverageAudioBitrate(muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_AUDIO))
.setAverageVideoBitrate(muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_VIDEO))
.build();
listeners.queueEvent( listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET, /* eventFlag= */ C.INDEX_UNSET,
listener -> listener.onTransformationCompleted(mediaItem)); listener -> listener.onTransformationCompleted(mediaItem, result));
} }
listeners.flushEvents(); listeners.flushEvents();
} }
......
...@@ -22,6 +22,8 @@ import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STA ...@@ -22,6 +22,8 @@ import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STA
import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_WAITING_FOR_AVAILABILITY; import static com.google.android.exoplayer2.transformer.Transformer.PROGRESS_STATE_WAITING_FOR_AVAILABILITY;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
...@@ -57,6 +59,7 @@ import java.util.concurrent.CountDownLatch; ...@@ -57,6 +59,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -239,9 +242,9 @@ public final class TransformerEndToEndTest { ...@@ -239,9 +242,9 @@ public final class TransformerEndToEndTest {
transformer.startTransformation(mediaItem, outputPath); transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer); TransformerTestRunner.runUntilCompleted(transformer);
verify(mockListener1, times(1)).onTransformationCompleted(mediaItem); verify(mockListener1, times(1)).onTransformationCompleted(eq(mediaItem), any());
verify(mockListener2, times(1)).onTransformationCompleted(mediaItem); verify(mockListener2, times(1)).onTransformationCompleted(eq(mediaItem), any());
verify(mockListener3, times(1)).onTransformationCompleted(mediaItem); verify(mockListener3, times(1)).onTransformationCompleted(eq(mediaItem), any());
} }
@Test @Test
...@@ -313,9 +316,9 @@ public final class TransformerEndToEndTest { ...@@ -313,9 +316,9 @@ public final class TransformerEndToEndTest {
transformer2.startTransformation(mediaItem, outputPath); transformer2.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer2); TransformerTestRunner.runUntilCompleted(transformer2);
verify(mockListener1, times(1)).onTransformationCompleted(mediaItem); verify(mockListener1, times(1)).onTransformationCompleted(eq(mediaItem), any());
verify(mockListener2, never()).onTransformationCompleted(mediaItem); verify(mockListener2, never()).onTransformationCompleted(eq(mediaItem), any());
verify(mockListener3, times(1)).onTransformationCompleted(mediaItem); verify(mockListener3, times(1)).onTransformationCompleted(eq(mediaItem), any());
} }
@Test @Test
...@@ -334,6 +337,30 @@ public final class TransformerEndToEndTest { ...@@ -334,6 +337,30 @@ public final class TransformerEndToEndTest {
} }
@Test @Test
public void startTransformation_completesWithValidBitrate() throws Exception {
AtomicReference<@NullableType TransformationResult> resultReference = new AtomicReference<>();
Transformer.Listener listener =
new Transformer.Listener() {
@Override
public void onTransformationCompleted(
MediaItem inputMediaItem, TransformationResult transformationResult) {
resultReference.set(transformationResult);
}
};
Transformer transformer =
createTransformerBuilder(/* disableFallback= */ true).addListener(listener).build();
MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_AUDIO_VIDEO);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
@Nullable TransformationResult result = resultReference.get();
assertThat(result).isNotNull();
assertThat(result.averageAudioBitrate).isGreaterThan(0);
assertThat(result.averageVideoBitrate).isGreaterThan(0);
}
@Test
public void startTransformation_withAudioEncoderFormatUnsupported_completesWithError() public void startTransformation_withAudioEncoderFormatUnsupported_completesWithError()
throws Exception { throws Exception {
Transformer transformer = Transformer transformer =
......
...@@ -78,7 +78,8 @@ public final class TransformerTestRunner { ...@@ -78,7 +78,8 @@ public final class TransformerTestRunner {
transformer.addListener( transformer.addListener(
new Transformer.Listener() { new Transformer.Listener() {
@Override @Override
public void onTransformationCompleted(MediaItem inputMediaItem) { public void onTransformationCompleted(
MediaItem inputMediaItem, TransformationResult transformationResult) {
transformationCompleted.set(true); transformationCompleted.set(true);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment