mirror of
https://github.com/samsonjs/media.git
synced 2026-04-10 12:05:47 +00:00
Output from the Transformer the average audio & video bitrates.
PiperOrigin-RevId: 426956151
This commit is contained in:
parent
60d9ae4758
commit
a3f981ae86
10 changed files with 244 additions and 70 deletions
|
|
@ -39,6 +39,7 @@ import com.google.android.exoplayer2.MediaItem;
|
|||
import com.google.android.exoplayer2.transformer.ProgressHolder;
|
||||
import com.google.android.exoplayer2.transformer.TransformationException;
|
||||
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.ui.AspectRatioFrameLayout;
|
||||
import com.google.android.exoplayer2.ui.StyledPlayerView;
|
||||
|
|
@ -223,7 +224,8 @@ public final class TransformerActivity extends AppCompatActivity {
|
|||
.addListener(
|
||||
new Transformer.Listener() {
|
||||
@Override
|
||||
public void onTransformationCompleted(MediaItem mediaItem) {
|
||||
public void onTransformationCompleted(
|
||||
MediaItem mediaItem, TransformationResult transformationResult) {
|
||||
TransformerActivity.this.onTransformationCompleted(filePath);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ app is notified of events via the listener passed to the `Transformer` builder.
|
|||
Transformer.Listener transformerListener =
|
||||
new Transformer.Listener() {
|
||||
@Override
|
||||
public void onTransformationCompleted(MediaItem inputMediaItem) {
|
||||
public void onTransformationCompleted(MediaItem inputMediaItem, TransformationResult transformationResult) {
|
||||
playOutput();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ public final class C {
|
|||
/** Represents an unset or unknown rate. */
|
||||
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. */
|
||||
public static final int LENGTH_UNSET = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
|
|
@ -39,50 +40,6 @@ public final class AndroidTestUtil {
|
|||
public static final String REMOTE_MP4_10_SECONDS_URI_STRING =
|
||||
"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}.
|
||||
*
|
||||
|
|
@ -98,6 +55,7 @@ public final class AndroidTestUtil {
|
|||
Context context, String testId, Transformer transformer, String uriString, int timeoutSeconds)
|
||||
throws Exception {
|
||||
AtomicReference<@NullableType Exception> exceptionReference = new AtomicReference<>();
|
||||
AtomicReference<TransformationResult> resultReference = new AtomicReference<>();
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
|
||||
Transformer testTransformer =
|
||||
|
|
@ -106,7 +64,9 @@ public final class AndroidTestUtil {
|
|||
.addListener(
|
||||
new Transformer.Listener() {
|
||||
@Override
|
||||
public void onTransformationCompleted(MediaItem inputMediaItem) {
|
||||
public void onTransformationCompleted(
|
||||
MediaItem inputMediaItem, TransformationResult result) {
|
||||
resultReference.set(result);
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
|
||||
|
|
@ -141,19 +101,21 @@ public final class AndroidTestUtil {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private static void writeTransformationResultToFile(Context context, TransformationResult result)
|
||||
private static void writeResultToFile(Context context, String testId, TransformationResult result)
|
||||
throws IOException {
|
||||
File analysisFile =
|
||||
createExternalCacheFile(context, /* fileName= */ result.testId + "-result.txt");
|
||||
File analysisFile = createExternalCacheFile(context, /* fileName= */ testId + "-result.txt");
|
||||
try (FileWriter fileWriter = new FileWriter(analysisFile)) {
|
||||
String fileContents =
|
||||
result.getFormattedAnalysis()
|
||||
"test="
|
||||
+ testId
|
||||
+ ", "
|
||||
+ getFormattedResult(result)
|
||||
+ ", deviceFingerprint="
|
||||
+ Build.FINGERPRINT
|
||||
+ ", deviceBrand="
|
||||
|
|
@ -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 {
|
||||
File file = new File(context.getExternalCacheDir(), fileName);
|
||||
checkState(!file.exists() || file.delete(), "Could not delete file: " + file.getAbsolutePath());
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import androidx.test.core.app.ApplicationProvider;
|
|||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.transformer.AndroidTestUtil;
|
||||
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.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
|
|
@ -57,7 +58,7 @@ public final class RepeatedTranscodeTransformationTest {
|
|||
Set<Long> differentOutputSizesBytes = new HashSet<>();
|
||||
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.
|
||||
AndroidTestUtil.TransformationResult result =
|
||||
TransformationResult result =
|
||||
runTransformer(
|
||||
context,
|
||||
/* testId= */ "repeatedTranscode_givesConsistentLengthOutput_" + i,
|
||||
|
|
@ -91,7 +92,7 @@ public final class RepeatedTranscodeTransformationTest {
|
|||
Set<Long> differentOutputSizesBytes = new HashSet<>();
|
||||
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.
|
||||
AndroidTestUtil.TransformationResult result =
|
||||
TransformationResult result =
|
||||
runTransformer(
|
||||
context,
|
||||
/* testId= */ "repeatedTranscodeNoAudio_givesConsistentLengthOutput_" + i,
|
||||
|
|
@ -122,7 +123,7 @@ public final class RepeatedTranscodeTransformationTest {
|
|||
Set<Long> differentOutputSizesBytes = new HashSet<>();
|
||||
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.
|
||||
AndroidTestUtil.TransformationResult result =
|
||||
TransformationResult result =
|
||||
runTransformer(
|
||||
context,
|
||||
/* testId= */ "repeatedTranscodeNoVideo_givesConsistentLengthOutput_" + i,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ import java.nio.ByteBuffer;
|
|||
private final Muxer.Factory muxerFactory;
|
||||
private final SparseIntArray trackTypeToIndex;
|
||||
private final SparseLongArray trackTypeToTimeUs;
|
||||
private final SparseLongArray trackTypeToBytesWritten;
|
||||
private final String containerMimeType;
|
||||
|
||||
private int trackCount;
|
||||
|
|
@ -62,6 +63,7 @@ import java.nio.ByteBuffer;
|
|||
this.containerMimeType = containerMimeType;
|
||||
trackTypeToIndex = new SparseIntArray();
|
||||
trackTypeToTimeUs = new SparseLongArray();
|
||||
trackTypeToBytesWritten = new SparseLongArray();
|
||||
previousTrackType = C.TRACK_TYPE_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +123,7 @@ import java.nio.ByteBuffer;
|
|||
int trackIndex = muxer.addTrack(format);
|
||||
trackTypeToIndex.put(trackType, trackIndex);
|
||||
trackTypeToTimeUs.put(trackType, 0L);
|
||||
trackTypeToBytesWritten.put(trackType, 0L);
|
||||
trackFormatCount++;
|
||||
if (trackFormatCount == trackCount) {
|
||||
isReady = true;
|
||||
|
|
@ -154,8 +157,11 @@ import java.nio.ByteBuffer;
|
|||
return false;
|
||||
}
|
||||
|
||||
muxer.writeSampleData(trackIndex, data, isKeyFrame, presentationTimeUs);
|
||||
trackTypeToBytesWritten.put(
|
||||
trackType, trackTypeToBytesWritten.get(trackType) + data.remaining());
|
||||
trackTypeToTimeUs.put(trackType, presentationTimeUs);
|
||||
|
||||
muxer.writeSampleData(trackIndex, data, isKeyFrame, presentationTimeUs);
|
||||
previousTrackType = trackType;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -168,7 +174,6 @@ import java.nio.ByteBuffer;
|
|||
*/
|
||||
public void endTrack(@C.TrackType int trackType) {
|
||||
trackTypeToIndex.delete(trackType);
|
||||
trackTypeToTimeUs.delete(trackType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -191,6 +196,25 @@ import java.nio.ByteBuffer;
|
|||
return trackCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
@ -208,7 +232,7 @@ import java.nio.ByteBuffer;
|
|||
if (!isReady) {
|
||||
return false;
|
||||
}
|
||||
if (trackTypeToTimeUs.size() == 1) {
|
||||
if (trackTypeToIndex.size() == 1) {
|
||||
return true;
|
||||
}
|
||||
if (trackType != previousTrackType) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -443,12 +443,22 @@ public final class Transformer {
|
|||
/** A listener for the transformation events. */
|
||||
public interface Listener {
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onTransformationCompleted(MediaItem, TransformationResult)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationCompleted(MediaItem inputMediaItem) {}
|
||||
|
||||
/**
|
||||
* Called when the transformation is completed successfully.
|
||||
*
|
||||
* @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
|
||||
|
|
@ -733,8 +743,9 @@ public final class Transformer {
|
|||
* Returns the current {@link ProgressState} and updates {@code progressHolder} with the current
|
||||
* progress if it is {@link #PROGRESS_STATE_AVAILABLE available}.
|
||||
*
|
||||
* <p>After a transformation {@link Listener#onTransformationCompleted(MediaItem) completes}, this
|
||||
* method returns {@link #PROGRESS_STATE_NO_TRANSFORMATION}.
|
||||
* <p>After a transformation {@link Listener#onTransformationCompleted(MediaItem,
|
||||
* TransformationResult) completes}, this method returns {@link
|
||||
* #PROGRESS_STATE_NO_TRANSFORMATION}.
|
||||
*
|
||||
* @param progressHolder A {@link ProgressHolder}, updated to hold the percentage progress if
|
||||
* {@link #PROGRESS_STATE_AVAILABLE available}.
|
||||
|
|
@ -950,9 +961,14 @@ public final class Transformer {
|
|||
/* eventFlag= */ C.INDEX_UNSET,
|
||||
listener -> listener.onTransformationError(mediaItem, finalException));
|
||||
} else {
|
||||
TransformationResult result =
|
||||
new TransformationResult.Builder()
|
||||
.setAverageAudioBitrate(muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_AUDIO))
|
||||
.setAverageVideoBitrate(muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_VIDEO))
|
||||
.build();
|
||||
listeners.queueEvent(
|
||||
/* eventFlag= */ C.INDEX_UNSET,
|
||||
listener -> listener.onTransformationCompleted(mediaItem));
|
||||
listener -> listener.onTransformationCompleted(mediaItem, result));
|
||||
}
|
||||
listeners.flushEvents();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.common.truth.Truth.assertThat;
|
||||
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.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
|
@ -57,6 +59,7 @@ import java.util.concurrent.CountDownLatch;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
|
@ -239,9 +242,9 @@ public final class TransformerEndToEndTest {
|
|||
transformer.startTransformation(mediaItem, outputPath);
|
||||
TransformerTestRunner.runUntilCompleted(transformer);
|
||||
|
||||
verify(mockListener1, times(1)).onTransformationCompleted(mediaItem);
|
||||
verify(mockListener2, times(1)).onTransformationCompleted(mediaItem);
|
||||
verify(mockListener3, times(1)).onTransformationCompleted(mediaItem);
|
||||
verify(mockListener1, times(1)).onTransformationCompleted(eq(mediaItem), any());
|
||||
verify(mockListener2, times(1)).onTransformationCompleted(eq(mediaItem), any());
|
||||
verify(mockListener3, times(1)).onTransformationCompleted(eq(mediaItem), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -313,9 +316,9 @@ public final class TransformerEndToEndTest {
|
|||
transformer2.startTransformation(mediaItem, outputPath);
|
||||
TransformerTestRunner.runUntilCompleted(transformer2);
|
||||
|
||||
verify(mockListener1, times(1)).onTransformationCompleted(mediaItem);
|
||||
verify(mockListener2, never()).onTransformationCompleted(mediaItem);
|
||||
verify(mockListener3, times(1)).onTransformationCompleted(mediaItem);
|
||||
verify(mockListener1, times(1)).onTransformationCompleted(eq(mediaItem), any());
|
||||
verify(mockListener2, never()).onTransformationCompleted(eq(mediaItem), any());
|
||||
verify(mockListener3, times(1)).onTransformationCompleted(eq(mediaItem), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -333,6 +336,30 @@ public final class TransformerEndToEndTest {
|
|||
DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_WITH_SEF_SLOW_MOTION));
|
||||
}
|
||||
|
||||
@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()
|
||||
throws Exception {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ public final class TransformerTestRunner {
|
|||
transformer.addListener(
|
||||
new Transformer.Listener() {
|
||||
@Override
|
||||
public void onTransformationCompleted(MediaItem inputMediaItem) {
|
||||
public void onTransformationCompleted(
|
||||
MediaItem inputMediaItem, TransformationResult transformationResult) {
|
||||
transformationCompleted.set(true);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue