diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/FrameworkMuxer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/FrameworkMuxer.java
new file mode 100644
index 0000000000..d5d04dd579
--- /dev/null
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/FrameworkMuxer.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2021 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.checkNotNull;
+import static com.google.android.exoplayer2.util.Util.SDK_INT;
+import static com.google.android.exoplayer2.util.Util.castNonNull;
+
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.os.ParcelFileDescriptor;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.mediacodec.MediaFormatUtil;
+import com.google.android.exoplayer2.util.MimeTypes;
+import com.google.android.exoplayer2.util.Util;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+
+/** Muxer implementation that uses a {@link MediaMuxer}. */
+@RequiresApi(18)
+/* package */ final class FrameworkMuxer implements Muxer {
+
+ public static final class Factory implements Muxer.Factory {
+ @Override
+ public FrameworkMuxer create(String path, String outputMimeType) throws IOException {
+ MediaMuxer mediaMuxer = new MediaMuxer(path, mimeTypeToMuxerOutputFormat(outputMimeType));
+ return new FrameworkMuxer(mediaMuxer, outputMimeType);
+ }
+
+ @RequiresApi(26)
+ @Override
+ public FrameworkMuxer create(ParcelFileDescriptor parcelFileDescriptor, String outputMimeType)
+ throws IOException {
+ MediaMuxer mediaMuxer =
+ new MediaMuxer(
+ parcelFileDescriptor.getFileDescriptor(),
+ mimeTypeToMuxerOutputFormat(outputMimeType));
+ return new FrameworkMuxer(mediaMuxer, outputMimeType);
+ }
+
+ @Override
+ public boolean supportsOutputMimeType(String mimeType) {
+ try {
+ mimeTypeToMuxerOutputFormat(mimeType);
+ } catch (IllegalStateException e) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private final MediaMuxer mediaMuxer;
+ private final String outputMimeType;
+ private final MediaCodec.BufferInfo bufferInfo;
+
+ private boolean isStarted;
+
+ private FrameworkMuxer(MediaMuxer mediaMuxer, String outputMimeType) {
+ this.mediaMuxer = mediaMuxer;
+ this.outputMimeType = outputMimeType;
+ bufferInfo = new MediaCodec.BufferInfo();
+ }
+
+ @Override
+ public boolean supportsSampleMimeType(@Nullable String mimeType) {
+ // MediaMuxer supported sample formats are documented in MediaMuxer.addTrack(MediaFormat).
+ boolean isAudio = MimeTypes.isAudio(mimeType);
+ boolean isVideo = MimeTypes.isVideo(mimeType);
+ if (outputMimeType.equals(MimeTypes.VIDEO_MP4)) {
+ if (isVideo) {
+ return MimeTypes.VIDEO_H263.equals(mimeType)
+ || MimeTypes.VIDEO_H264.equals(mimeType)
+ || MimeTypes.VIDEO_MP4V.equals(mimeType)
+ || (Util.SDK_INT >= 24 && MimeTypes.VIDEO_H265.equals(mimeType));
+ } else if (isAudio) {
+ return MimeTypes.AUDIO_AAC.equals(mimeType)
+ || MimeTypes.AUDIO_AMR_NB.equals(mimeType)
+ || MimeTypes.AUDIO_AMR_WB.equals(mimeType);
+ }
+ } else if (outputMimeType.equals(MimeTypes.VIDEO_WEBM) && SDK_INT >= 21) {
+ if (isVideo) {
+ return MimeTypes.VIDEO_VP8.equals(mimeType)
+ || (Util.SDK_INT >= 24 && MimeTypes.VIDEO_VP9.equals(mimeType));
+ } else if (isAudio) {
+ return MimeTypes.AUDIO_VORBIS.equals(mimeType);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int addTrack(Format format) {
+ String sampleMimeType = checkNotNull(format.sampleMimeType);
+ MediaFormat mediaFormat;
+ if (MimeTypes.isAudio(sampleMimeType)) {
+ mediaFormat =
+ MediaFormat.createAudioFormat(
+ castNonNull(sampleMimeType), format.sampleRate, format.channelCount);
+ } else {
+ mediaFormat =
+ MediaFormat.createVideoFormat(castNonNull(sampleMimeType), format.width, format.height);
+ mediaMuxer.setOrientationHint(format.rotationDegrees);
+ }
+ MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
+ return mediaMuxer.addTrack(mediaFormat);
+ }
+
+ @Override
+ public void writeSampleData(
+ int trackIndex, ByteBuffer data, boolean isKeyFrame, long presentationTimeUs) {
+ if (!isStarted) {
+ isStarted = true;
+ mediaMuxer.start();
+ }
+ int offset = data.position();
+ int size = data.limit() - offset;
+ int flags = isKeyFrame ? C.BUFFER_FLAG_KEY_FRAME : 0;
+ bufferInfo.set(offset, size, presentationTimeUs, flags);
+ mediaMuxer.writeSampleData(trackIndex, data, bufferInfo);
+ }
+
+ @Override
+ public void release() {
+ if (isStarted) {
+ isStarted = false;
+ try {
+ mediaMuxer.stop();
+ } catch (IllegalStateException e) {
+ if (SDK_INT < 30) {
+ // Set the muxer state to stopped even if mediaMuxer.stop() failed so that
+ // mediaMuxer.release() doesn't attempt to stop the muxer and therefore doesn't throw the
+ // same exception without releasing its resources. This is already implemented in
+ // MediaMuxer
+ // from API level 30.
+ try {
+ Field muxerStoppedStateField = MediaMuxer.class.getDeclaredField("MUXER_STATE_STOPPED");
+ muxerStoppedStateField.setAccessible(true);
+ int muxerStoppedState = castNonNull((Integer) muxerStoppedStateField.get(mediaMuxer));
+ Field muxerStateField = MediaMuxer.class.getDeclaredField("mState");
+ muxerStateField.setAccessible(true);
+ muxerStateField.set(mediaMuxer, muxerStoppedState);
+ } catch (Exception reflectionException) {
+ // Do nothing.
+ }
+ }
+ throw e;
+ }
+ }
+ mediaMuxer.release();
+ }
+
+ /**
+ * Converts a {@link MimeTypes MIME type} into a {@link MediaMuxer.OutputFormat MediaMuxer output
+ * format}.
+ *
+ * @param mimeType The {@link MimeTypes MIME type} to convert.
+ * @return The corresponding {@link MediaMuxer.OutputFormat MediaMuxer output format}.
+ * @throws IllegalArgumentException If the {@link MimeTypes MIME type} is not supported as output
+ * format.
+ */
+ private static int mimeTypeToMuxerOutputFormat(String mimeType) {
+ if (mimeType.equals(MimeTypes.VIDEO_MP4)) {
+ return MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
+ } else if (SDK_INT >= 21 && mimeType.equals(MimeTypes.VIDEO_WEBM)) {
+ return MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM;
+ } else {
+ throw new IllegalArgumentException("Unsupported output MIME type: " + mimeType);
+ }
+ }
+}
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Muxer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Muxer.java
new file mode 100644
index 0000000000..24e71215fa
--- /dev/null
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Muxer.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2021 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 android.os.ParcelFileDescriptor;
+import androidx.annotation.Nullable;
+import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.util.MimeTypes;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Abstracts media muxing operations.
+ *
+ *
Query whether {@link #supportsSampleMimeType(String) sample MIME types are supported} and
+ * {@link #addTrack(Format) add all tracks}, then {@link #writeSampleData(int, ByteBuffer, boolean,
+ * long) write sample data} to mux samples. Once any sample data has been written, it is not
+ * possible to add tracks. After writing all sample data, {@link #release() release} the instance to
+ * finish writing to the output and return any resources to the system.
+ */
+/* package */ interface Muxer {
+
+ /** Factory for muxers. */
+ interface Factory {
+ /**
+ * Returns a new muxer writing to a file.
+ *
+ * @param path The path to the output file.
+ * @param outputMimeType The container {@link MimeTypes MIME type} of the output file.
+ * @throws IllegalArgumentException If the path is invalid or the MIME type is not supported.
+ * @throws IOException If an error occurs opening the output file for writing.
+ */
+ Muxer create(String path, String outputMimeType) throws IOException;
+
+ /**
+ * Returns a new muxer writing to a file descriptor.
+ *
+ * @param parcelFileDescriptor A readable and writable {@link ParcelFileDescriptor} of the
+ * output. The file referenced by this ParcelFileDescriptor should not be used before the
+ * muxer is released. It is the responsibility of the caller to close the
+ * ParcelFileDescriptor. This can be done after this method returns.
+ * @param outputMimeType The {@link MimeTypes MIME type} of the output.
+ * @throws IllegalArgumentException If the file descriptor is invalid or the MIME type is not
+ * supported.
+ * @throws IOException If an error occurs opening the output file descriptor for writing.
+ */
+ Muxer create(ParcelFileDescriptor parcelFileDescriptor, String outputMimeType)
+ throws IOException;
+
+ /** Returns whether the {@link MimeTypes MIME type} provided is a supported output format. */
+ boolean supportsOutputMimeType(String mimeType);
+ }
+
+ /** Returns whether the sample {@link MimeTypes MIME type} is supported. */
+ boolean supportsSampleMimeType(@Nullable String mimeType);
+
+ /**
+ * Adds a track with the specified format, and returns its index (to be passed in subsequent calls
+ * to {@link #writeSampleData(int, ByteBuffer, boolean, long)}).
+ */
+ int addTrack(Format format);
+
+ /**
+ * Writes the specified sample.
+ *
+ * @param trackIndex The index of the track, previously returned by {@link #addTrack(Format)}.
+ * @param data Buffer containing the sample data to write to the container.
+ * @param isKeyFrame Whether the sample is a key frame.
+ * @param presentationTimeUs The presentation time of the sample in microseconds.
+ */
+ void writeSampleData(
+ int trackIndex, ByteBuffer data, boolean isKeyFrame, long presentationTimeUs);
+
+ /** Releases any resources associated with muxing. */
+ void release();
+}
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MuxerWrapper.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MuxerWrapper.java
index 274a4857cb..3d9dc45b6f 100644
--- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MuxerWrapper.java
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MuxerWrapper.java
@@ -17,25 +17,15 @@
package com.google.android.exoplayer2.transformer;
import static com.google.android.exoplayer2.util.Assertions.checkState;
-import static com.google.android.exoplayer2.util.Util.SDK_INT;
-import static com.google.android.exoplayer2.util.Util.castNonNull;
import static com.google.android.exoplayer2.util.Util.minValue;
-import android.media.MediaCodec;
-import android.media.MediaFormat;
-import android.media.MediaMuxer;
-import android.os.ParcelFileDescriptor;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.mediacodec.MediaFormatUtil;
import com.google.android.exoplayer2.util.MimeTypes;
-import com.google.android.exoplayer2.util.Util;
-import java.io.IOException;
-import java.lang.reflect.Field;
import java.nio.ByteBuffer;
/**
@@ -54,11 +44,9 @@ import java.nio.ByteBuffer;
*/
private static final long MAX_TRACK_WRITE_AHEAD_US = C.msToUs(500);
- private final MediaMuxer mediaMuxer;
- private final String outputMimeType;
+ private final Muxer muxer;
private final SparseIntArray trackTypeToIndex;
private final SparseLongArray trackTypeToTimeUs;
- private final MediaCodec.BufferInfo bufferInfo;
private int trackCount;
private int trackFormatCount;
@@ -66,45 +54,10 @@ import java.nio.ByteBuffer;
private int previousTrackType;
private long minTrackTimeUs;
- /**
- * Constructs an instance.
- *
- * @param path The path to the output file.
- * @param outputMimeType The {@link MimeTypes MIME type} of the output.
- * @throws IllegalArgumentException If the path is invalid or the MIME type is not supported.
- * @throws IOException If an error occurs opening the output file for writing.
- */
- public MuxerWrapper(String path, String outputMimeType) throws IOException {
- this(new MediaMuxer(path, mimeTypeToMuxerOutputFormat(outputMimeType)), outputMimeType);
- }
-
- /**
- * Constructs an instance.
- *
- * @param parcelFileDescriptor A readable and writable {@link ParcelFileDescriptor} of the output.
- * The file referenced by this ParcelFileDescriptor should not be used before the muxer is
- * released. It is the responsibility of the caller to close the ParcelFileDescriptor. This
- * can be done after this constructor returns.
- * @param outputMimeType The {@link MimeTypes MIME type} of the output.
- * @throws IllegalArgumentException If the file descriptor is invalid or the MIME type is not
- * supported.
- * @throws IOException If an error occurs opening the output file for writing.
- */
- @RequiresApi(26)
- public MuxerWrapper(ParcelFileDescriptor parcelFileDescriptor, String outputMimeType)
- throws IOException {
- this(
- new MediaMuxer(
- parcelFileDescriptor.getFileDescriptor(), mimeTypeToMuxerOutputFormat(outputMimeType)),
- outputMimeType);
- }
-
- private MuxerWrapper(MediaMuxer mediaMuxer, String outputMimeType) {
- this.mediaMuxer = mediaMuxer;
- this.outputMimeType = outputMimeType;
+ public MuxerWrapper(Muxer muxer) {
+ this.muxer = muxer;
trackTypeToIndex = new SparseIntArray();
trackTypeToTimeUs = new SparseLongArray();
- bufferInfo = new MediaCodec.BufferInfo();
previousTrackType = C.TRACK_TYPE_NONE;
}
@@ -123,6 +76,11 @@ import java.nio.ByteBuffer;
trackCount++;
}
+ /** Returns whether the sample {@link MimeTypes MIME type} is supported. */
+ public boolean supportsSampleMimeType(@Nullable String mimeType) {
+ return muxer.supportsSampleMimeType(mimeType);
+ }
+
/**
* Adds a track format to the muxer.
*
@@ -131,9 +89,8 @@ import java.nio.ByteBuffer;
* long) written}.
*
* @param format The {@link Format} to be added.
- * @throws IllegalArgumentException If the format is invalid.
- * @throws IllegalStateException If the format is unsupported, if there is already a track format
- * of the same type (audio or video) or if the muxer is in the wrong state.
+ * @throws IllegalStateException If the format is unsupported or if there is already a track
+ * format of the same type (audio or video).
*/
public void addTrackFormat(Format format) {
checkState(trackCount > 0, "All tracks should be registered before the formats are added.");
@@ -147,23 +104,11 @@ import java.nio.ByteBuffer;
trackTypeToIndex.get(trackType, /* valueIfKeyNotFound= */ C.INDEX_UNSET) == C.INDEX_UNSET,
"There is already a track of type " + trackType);
- MediaFormat mediaFormat;
- if (isAudio) {
- mediaFormat =
- MediaFormat.createAudioFormat(
- castNonNull(sampleMimeType), format.sampleRate, format.channelCount);
- } else {
- mediaFormat =
- MediaFormat.createVideoFormat(castNonNull(sampleMimeType), format.width, format.height);
- mediaMuxer.setOrientationHint(format.rotationDegrees);
- }
- MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
- int trackIndex = mediaMuxer.addTrack(mediaFormat);
+ int trackIndex = muxer.addTrack(format);
trackTypeToIndex.put(trackType, trackIndex);
trackTypeToTimeUs.put(trackType, 0L);
trackFormatCount++;
if (trackFormatCount == trackCount) {
- mediaMuxer.start();
isReady = true;
}
}
@@ -180,9 +125,8 @@ import java.nio.ByteBuffer;
* {@link #addTrackFormat(Format) received a format} for every {@link #registerTrack()
* registered track}, or if it should write samples of other track types first to ensure a
* good interleaving.
- * @throws IllegalArgumentException If the sample in {@code buffer} is invalid.
* @throws IllegalStateException If the muxer doesn't have any {@link #endTrack(int) non-ended}
- * track of the given track type or if the muxer is in the wrong state.
+ * track of the given track type.
*/
public boolean writeSample(
int trackType, @Nullable ByteBuffer data, boolean isKeyFrame, long presentationTimeUs) {
@@ -197,11 +141,7 @@ import java.nio.ByteBuffer;
return true;
}
- int offset = data.position();
- int size = data.limit() - offset;
- int flags = isKeyFrame ? C.BUFFER_FLAG_KEY_FRAME : 0;
- bufferInfo.set(offset, size, presentationTimeUs, flags);
- mediaMuxer.writeSampleData(trackIndex, data, bufferInfo);
+ muxer.writeSampleData(trackIndex, data, isKeyFrame, presentationTimeUs);
trackTypeToTimeUs.put(trackType, presentationTimeUs);
previousTrackType = trackType;
return true;
@@ -222,35 +162,10 @@ import java.nio.ByteBuffer;
* Stops the muxer.
*
*
The muxer cannot be used anymore once it is stopped.
- *
- * @throws IllegalStateException If the muxer is in the wrong state (for example if it didn't
- * receive any samples).
*/
public void stop() {
- if (!isReady) {
- return;
- }
- isReady = false;
- try {
- mediaMuxer.stop();
- } catch (IllegalStateException e) {
- if (SDK_INT < 30) {
- // Set the muxer state to stopped even if mediaMuxer.stop() failed so that
- // mediaMuxer.release() doesn't attempt to stop the muxer and therefore doesn't throw the
- // same exception without releasing its resources. This is already implemented in MediaMuxer
- // from API level 30.
- try {
- Field muxerStoppedStateField = MediaMuxer.class.getDeclaredField("MUXER_STATE_STOPPED");
- muxerStoppedStateField.setAccessible(true);
- int muxerStoppedState = castNonNull((Integer) muxerStoppedStateField.get(mediaMuxer));
- Field muxerStateField = MediaMuxer.class.getDeclaredField("mState");
- muxerStateField.setAccessible(true);
- muxerStateField.set(mediaMuxer, muxerStoppedState);
- } catch (Exception reflectionException) {
- // Do nothing.
- }
- }
- throw e;
+ if (isReady) {
+ isReady = false;
}
}
@@ -261,7 +176,7 @@ import java.nio.ByteBuffer;
*/
public void release() {
isReady = false;
- mediaMuxer.release();
+ muxer.release();
}
/** Returns the number of {@link #registerTrack() registered} tracks. */
@@ -269,48 +184,6 @@ import java.nio.ByteBuffer;
return trackCount;
}
- /**
- * Returns whether the sample {@link MimeTypes MIME type} is supported.
- *
- *
Supported sample formats are documented in {@link MediaMuxer#addTrack(MediaFormat)}.
- */
- public boolean supportsSampleMimeType(@Nullable String mimeType) {
- boolean isAudio = MimeTypes.isAudio(mimeType);
- boolean isVideo = MimeTypes.isVideo(mimeType);
- if (outputMimeType.equals(MimeTypes.VIDEO_MP4)) {
- if (isVideo) {
- return MimeTypes.VIDEO_H263.equals(mimeType)
- || MimeTypes.VIDEO_H264.equals(mimeType)
- || MimeTypes.VIDEO_MP4V.equals(mimeType)
- || (Util.SDK_INT >= 24 && MimeTypes.VIDEO_H265.equals(mimeType));
- } else if (isAudio) {
- return MimeTypes.AUDIO_AAC.equals(mimeType)
- || MimeTypes.AUDIO_AMR_NB.equals(mimeType)
- || MimeTypes.AUDIO_AMR_WB.equals(mimeType);
- }
- } else if (outputMimeType.equals(MimeTypes.VIDEO_WEBM) && SDK_INT >= 21) {
- if (isVideo) {
- return MimeTypes.VIDEO_VP8.equals(mimeType)
- || (Util.SDK_INT >= 24 && MimeTypes.VIDEO_VP9.equals(mimeType));
- } else if (isAudio) {
- return MimeTypes.AUDIO_VORBIS.equals(mimeType);
- }
- }
- return false;
- }
-
- /**
- * Returns whether the {@link MimeTypes MIME type} provided is a supported muxer output format.
- */
- public static boolean supportsOutputMimeType(String mimeType) {
- try {
- mimeTypeToMuxerOutputFormat(mimeType);
- } catch (IllegalStateException e) {
- return false;
- }
- return true;
- }
-
/**
* Returns whether the muxer can write a sample of the given track type.
*
@@ -337,22 +210,4 @@ import java.nio.ByteBuffer;
return trackTimeUs - minTrackTimeUs <= MAX_TRACK_WRITE_AHEAD_US;
}
- /**
- * Converts a {@link MimeTypes MIME type} into a {@link MediaMuxer.OutputFormat MediaMuxer output
- * format}.
- *
- * @param mimeType The {@link MimeTypes MIME type} to convert.
- * @return The corresponding {@link MediaMuxer.OutputFormat MediaMuxer output format}.
- * @throws IllegalArgumentException If the {@link MimeTypes MIME type} is not supported as output
- * format.
- */
- private static int mimeTypeToMuxerOutputFormat(String mimeType) {
- if (mimeType.equals(MimeTypes.VIDEO_MP4)) {
- return MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
- } else if (SDK_INT >= 21 && mimeType.equals(MimeTypes.VIDEO_WEBM)) {
- return MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM;
- } else {
- throw new IllegalArgumentException("Unsupported output MIME type: " + mimeType);
- }
- }
}
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java
index 8546c84027..0c88b32f80 100644
--- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java
@@ -79,7 +79,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* of the application's main thread is used. In all cases the Looper of the thread from which the
* transformer must be accessed can be queried using {@link #getApplicationLooper()}.
*/
-
@RequiresApi(18)
public final class Transformer {
@@ -88,6 +87,7 @@ public final class Transformer {
private @MonotonicNonNull Context context;
private @MonotonicNonNull MediaSourceFactory mediaSourceFactory;
+ private Muxer.Factory muxerFactory;
private boolean removeAudio;
private boolean removeVideo;
private boolean flattenForSlowMotion;
@@ -98,6 +98,7 @@ public final class Transformer {
/** Creates a builder with default values. */
public Builder() {
+ muxerFactory = new FrameworkMuxer.Factory();
outputMimeType = MimeTypes.VIDEO_MP4;
listener = new Listener() {};
looper = Util.getCurrentOrMainLooper();
@@ -108,6 +109,7 @@ public final class Transformer {
private Builder(Transformer transformer) {
this.context = transformer.context;
this.mediaSourceFactory = transformer.mediaSourceFactory;
+ this.muxerFactory = transformer.muxerFactory;
this.removeAudio = transformer.transformation.removeAudio;
this.removeVideo = transformer.transformation.removeVideo;
this.flattenForSlowMotion = transformer.transformation.flattenForSlowMotion;
@@ -212,12 +214,8 @@ public final class Transformer {
*
* @param outputMimeType The MIME type of the output.
* @return This builder.
- * @throws IllegalArgumentException If the MIME type is not supported.
*/
public Builder setOutputMimeType(String outputMimeType) {
- if (!MuxerWrapper.supportsOutputMimeType(outputMimeType)) {
- throw new IllegalArgumentException("Unsupported output MIME type: " + outputMimeType);
- }
this.outputMimeType = outputMimeType;
return this;
}
@@ -262,12 +260,25 @@ public final class Transformer {
return this;
}
+ /**
+ * Sets the factory for muxers that write the media container.
+ *
+ * @param muxerFactory A {@link Muxer.Factory}.
+ * @return This builder.
+ */
+ @VisibleForTesting
+ /* package */ Builder setMuxerFactory(Muxer.Factory muxerFactory) {
+ this.muxerFactory = muxerFactory;
+ return this;
+ }
+
/**
* Builds a {@link Transformer} instance.
*
* @throws IllegalStateException If the {@link Context} has not been provided.
* @throws IllegalStateException If both audio and video have been removed (otherwise the output
* would not contain any samples).
+ * @throws IllegalStateException If the muxer doesn't support the requested output MIME type.
*/
public Transformer build() {
checkStateNotNull(context);
@@ -278,9 +289,13 @@ public final class Transformer {
}
mediaSourceFactory = new DefaultMediaSourceFactory(context, defaultExtractorsFactory);
}
+ checkState(
+ muxerFactory.supportsOutputMimeType(outputMimeType),
+ "Unsupported output MIME type: " + outputMimeType);
Transformation transformation =
new Transformation(removeAudio, removeVideo, flattenForSlowMotion, outputMimeType);
- return new Transformer(context, mediaSourceFactory, transformation, listener, looper, clock);
+ return new Transformer(
+ context, mediaSourceFactory, muxerFactory, transformation, listener, looper, clock);
}
}
@@ -332,6 +347,7 @@ public final class Transformer {
private final Context context;
private final MediaSourceFactory mediaSourceFactory;
+ private final Muxer.Factory muxerFactory;
private final Transformation transformation;
private final Looper looper;
private final Clock clock;
@@ -344,6 +360,7 @@ public final class Transformer {
private Transformer(
Context context,
MediaSourceFactory mediaSourceFactory,
+ Muxer.Factory muxerFactory,
Transformation transformation,
Transformer.Listener listener,
Looper looper,
@@ -353,6 +370,7 @@ public final class Transformer {
"Audio and video cannot both be removed.");
this.context = context;
this.mediaSourceFactory = mediaSourceFactory;
+ this.muxerFactory = muxerFactory;
this.transformation = transformation;
this.listener = listener;
this.looper = looper;
@@ -397,7 +415,7 @@ public final class Transformer {
* @throws IOException If an error occurs opening the output file for writing.
*/
public void startTransformation(MediaItem mediaItem, String path) throws IOException {
- startTransformation(mediaItem, new MuxerWrapper(path, transformation.outputMimeType));
+ startTransformation(mediaItem, muxerFactory.create(path, transformation.outputMimeType));
}
/**
@@ -427,17 +445,17 @@ public final class Transformer {
public void startTransformation(MediaItem mediaItem, ParcelFileDescriptor parcelFileDescriptor)
throws IOException {
startTransformation(
- mediaItem, new MuxerWrapper(parcelFileDescriptor, transformation.outputMimeType));
+ mediaItem, muxerFactory.create(parcelFileDescriptor, transformation.outputMimeType));
}
- private void startTransformation(MediaItem mediaItem, MuxerWrapper muxerWrapper) {
+ private void startTransformation(MediaItem mediaItem, Muxer muxer) {
verifyApplicationThread();
if (player != null) {
throw new IllegalStateException("There is already a transformation in progress.");
}
+ MuxerWrapper muxerWrapper = new MuxerWrapper(muxer);
this.muxerWrapper = muxerWrapper;
-
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
trackSelector.setParameters(
new DefaultTrackSelector.ParametersBuilder(context)
diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java
index 445a91723a..33888226b8 100644
--- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java
+++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java
@@ -50,7 +50,7 @@ import com.google.android.exoplayer2.util.MimeTypes;
@C.FormatSupport
public final int supportsFormat(Format format) {
@Nullable String sampleMimeType = format.sampleMimeType;
- if (MimeTypes.getTrackType(format.sampleMimeType) != getTrackType()) {
+ if (MimeTypes.getTrackType(sampleMimeType) != getTrackType()) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
} else if (muxerWrapper.supportsSampleMimeType(sampleMimeType)) {
return RendererCapabilities.create(C.FORMAT_HANDLED);
diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TestMuxer.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TestMuxer.java
new file mode 100644
index 0000000000..1c43f7ccc9
--- /dev/null
+++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TestMuxer.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2021 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 com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.testutil.DumpableFormat;
+import com.google.android.exoplayer2.testutil.Dumper;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * An implementation of {@link Muxer} that supports dumping information about all interactions (for
+ * testing purposes) and delegates the actual muxing operations to a {@link FrameworkMuxer}.
+ */
+public final class TestMuxer implements Muxer, Dumper.Dumpable {
+
+ private final Muxer frameworkMuxer;
+ private final List dumpables;
+
+ /** Creates a new test muxer. */
+ public TestMuxer(String path, String outputMimeType) throws IOException {
+ frameworkMuxer = new FrameworkMuxer.Factory().create(path, outputMimeType);
+ dumpables = new ArrayList<>();
+ dumpables.add(dumper -> dumper.add("containerMimeType", outputMimeType));
+ }
+
+ // Muxer implementation.
+
+ @Override
+ public boolean supportsSampleMimeType(String mimeType) {
+ return frameworkMuxer.supportsSampleMimeType(mimeType);
+ }
+
+ @Override
+ public int addTrack(Format format) {
+ int trackIndex = frameworkMuxer.addTrack(format);
+ dumpables.add(new DumpableFormat(format, trackIndex));
+ return trackIndex;
+ }
+
+ @Override
+ public void writeSampleData(
+ int trackIndex, ByteBuffer data, boolean isKeyFrame, long presentationTimeUs) {
+ dumpables.add(new DumpableSample(trackIndex, data, isKeyFrame, presentationTimeUs));
+ frameworkMuxer.writeSampleData(trackIndex, data, isKeyFrame, presentationTimeUs);
+ }
+
+ @Override
+ public void release() {
+ dumpables.add(dumper -> dumper.add("released", true));
+ frameworkMuxer.release();
+ }
+
+ // Dumper.Dumpable implementation.
+
+ @Override
+ public void dump(Dumper dumper) {
+ for (Dumper.Dumpable dumpable : dumpables) {
+ dumpable.dump(dumper);
+ }
+ }
+
+ private static final class DumpableSample implements Dumper.Dumpable {
+
+ private final int trackIndex;
+ private final long presentationTimeUs;
+ private final boolean isKeyFrame;
+ private final int sampleDataHashCode;
+
+ public DumpableSample(
+ int trackIndex, ByteBuffer sample, boolean isKeyFrame, long presentationTimeUs) {
+ this.trackIndex = trackIndex;
+ this.presentationTimeUs = presentationTimeUs;
+ this.isKeyFrame = isKeyFrame;
+ int initialPosition = sample.position();
+ byte[] data = new byte[sample.remaining()];
+ sample.get(data);
+ sample.position(initialPosition);
+ sampleDataHashCode = Arrays.hashCode(data);
+ }
+
+ @Override
+ public void dump(Dumper dumper) {
+ dumper
+ .startBlock("sample")
+ .add("trackIndex", trackIndex)
+ .add("dataHashCode", sampleDataHashCode)
+ .add("isKeyFrame", isKeyFrame)
+ .add("presentationTimeUs", presentationTimeUs)
+ .endBlock();
+ }
+ }
+}
diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerBuilderTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerBuilderTest.java
index 7d787be2e8..8cfba3156d 100644
--- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerBuilderTest.java
+++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerBuilderTest.java
@@ -32,8 +32,8 @@ public class TransformerBuilderTest {
@Test
public void setOutputMimeType_unsupportedMimeType_throws() {
assertThrows(
- IllegalArgumentException.class,
- () -> new Transformer.Builder().setOutputMimeType(MimeTypes.VIDEO_FLV));
+ IllegalStateException.class,
+ () -> new Transformer.Builder().setOutputMimeType(MimeTypes.VIDEO_FLV).build());
}
@Test
diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerTest.java
index d3ef423217..9dc96421c0 100644
--- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerTest.java
+++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerTest.java
@@ -28,15 +28,16 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.testutil.AutoAdvancingFakeClock;
+import com.google.android.exoplayer2.testutil.DumpFileAsserts;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.Iterables;
-import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -56,18 +57,20 @@ import org.robolectric.shadows.ShadowMediaCodec;
@RunWith(AndroidJUnit4.class)
public final class TransformerTest {
- private static final String FILE_VIDEO_ONLY = "asset:///media/mkv/sample.mkv";
- private static final String FILE_AUDIO_ONLY = "asset:///media/amr/sample_nb.amr";
- private static final String FILE_AUDIO_VIDEO = "asset:///media/mp4/sample.mp4";
-
- // The ShadowMediaMuxer only outputs sample data to the output file.
- private static final int FILE_VIDEO_ONLY_SAMPLE_DATA_LENGTH = 89_502;
- private static final int FILE_AUDIO_ONLY_SAMPLE_DATA_LENGTH = 2834;
- private static final int FILE_AUDIO_VIDEO_AUDIO_SAMPLE_DATA_LENGTH = 9529;
- private static final int FILE_AUDIO_VIDEO_VIDEO_SAMPLE_DATA_LENGTH = 89_876;
+ private static final String URI_PREFIX = "asset:///media/";
+ private static final String FILE_VIDEO_ONLY = "mkv/sample.mkv";
+ private static final String FILE_AUDIO_ONLY = "amr/sample_nb.amr";
+ private static final String FILE_AUDIO_VIDEO = "mp4/sample.mp4";
+ private static final String FILE_WITH_SUBTITLES = "mkv/sample_with_srt.mkv";
+ private static final String FILE_WITH_SEF_SLOW_MOTION = "mp4/sample_sef_slow_motion.mp4";
+ private static final String FILE_WITH_ALL_SAMPLE_FORMATS_UNSUPPORTED = "mp4/sample_ac3.mp4";
+ private static final String FILE_UNKNOWN_DURATION = "mp4/sample_fragmented.mp4";
+ public static final String DUMP_FILE_OUTPUT_DIRECTORY = "transformerdumps";
+ public static final String DUMP_FILE_EXTENSION = "dump";
private Context context;
private String outputPath;
+ private TestMuxer testMuxer;
private AutoAdvancingFakeClock clock;
private ProgressHolder progressHolder;
@@ -88,55 +91,78 @@ public final class TransformerTest {
@Test
public void startTransformation_videoOnly_completesSuccessfully() throws Exception {
- Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_VIDEO_ONLY);
+ Transformer transformer =
+ new Transformer.Builder()
+ .setContext(context)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_VIDEO_ONLY);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length()).isEqualTo(FILE_VIDEO_ONLY_SAMPLE_DATA_LENGTH);
+ DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_VIDEO_ONLY));
}
@Test
public void startTransformation_audioOnly_completesSuccessfully() throws Exception {
- Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_AUDIO_ONLY);
+ Transformer transformer =
+ new Transformer.Builder()
+ .setContext(context)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_AUDIO_ONLY);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length()).isEqualTo(FILE_AUDIO_ONLY_SAMPLE_DATA_LENGTH);
+ DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_AUDIO_ONLY));
}
@Test
public void startTransformation_audioAndVideo_completesSuccessfully() throws Exception {
- Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_AUDIO_VIDEO);
+ Transformer transformer =
+ new Transformer.Builder()
+ .setContext(context)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_AUDIO_VIDEO);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length())
- .isEqualTo(
- FILE_AUDIO_VIDEO_VIDEO_SAMPLE_DATA_LENGTH + FILE_AUDIO_VIDEO_AUDIO_SAMPLE_DATA_LENGTH);
+ DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO));
}
@Test
public void startTransformation_withSubtitles_completesSuccessfully() throws Exception {
- Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri("asset:///media/mkv/sample_with_srt.mkv");
+ Transformer transformer =
+ new Transformer.Builder()
+ .setContext(context)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_WITH_SUBTITLES);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length()).isEqualTo(89_502);
+ DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_WITH_SUBTITLES));
}
@Test
public void startTransformation_successiveTransformations_completesSuccessfully()
throws Exception {
- Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_VIDEO_ONLY);
+ Transformer transformer =
+ new Transformer.Builder()
+ .setContext(context)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_VIDEO_ONLY);
// Transform first media item.
transformer.startTransformation(mediaItem, outputPath);
@@ -147,13 +173,13 @@ public final class TransformerTest {
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length()).isEqualTo(FILE_VIDEO_ONLY_SAMPLE_DATA_LENGTH);
+ DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_VIDEO_ONLY));
}
@Test
public void startTransformation_concurrentTransformations_throwsError() throws Exception {
Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_VIDEO_ONLY);
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_VIDEO_ONLY);
transformer.startTransformation(mediaItem, outputPath);
@@ -164,25 +190,37 @@ public final class TransformerTest {
@Test
public void startTransformation_removeAudio_completesSuccessfully() throws Exception {
Transformer transformer =
- new Transformer.Builder().setContext(context).setRemoveAudio(true).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_AUDIO_VIDEO);
+ new Transformer.Builder()
+ .setContext(context)
+ .setRemoveAudio(true)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_AUDIO_VIDEO);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length()).isEqualTo(FILE_AUDIO_VIDEO_VIDEO_SAMPLE_DATA_LENGTH);
+ DumpFileAsserts.assertOutput(
+ context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".noaudio"));
}
@Test
public void startTransformation_removeVideo_completesSuccessfully() throws Exception {
Transformer transformer =
- new Transformer.Builder().setContext(context).setRemoveVideo(true).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_AUDIO_VIDEO);
+ new Transformer.Builder()
+ .setContext(context)
+ .setRemoveVideo(true)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_AUDIO_VIDEO);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length()).isEqualTo(FILE_AUDIO_VIDEO_AUDIO_SAMPLE_DATA_LENGTH);
+ DumpFileAsserts.assertOutput(
+ context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".novideo"));
}
@Test
@@ -192,13 +230,14 @@ public final class TransformerTest {
.setContext(context)
.setFlattenForSlowMotion(true)
.setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
.build();
- MediaItem mediaItem = MediaItem.fromUri("asset:///media/mp4/sample_sef_slow_motion.mp4");
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_WITH_SEF_SLOW_MOTION);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length()).isEqualTo(18_172);
+ DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_WITH_SEF_SLOW_MOTION));
}
@Test
@@ -217,7 +256,7 @@ public final class TransformerTest {
public void startTransformation_withAllSampleFormatsUnsupported_completesWithError()
throws Exception {
Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri("asset:///media/mp4/sample_ac3.mp4");
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_WITH_ALL_SAMPLE_FORMATS_UNSUPPORTED);
transformer.startTransformation(mediaItem, outputPath);
Exception exception = TransformerTestRunner.runUntilError(transformer);
@@ -227,8 +266,13 @@ public final class TransformerTest {
@Test
public void startTransformation_afterCancellation_completesSuccessfully() throws Exception {
- Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_VIDEO_ONLY);
+ Transformer transformer =
+ new Transformer.Builder()
+ .setContext(context)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_VIDEO_ONLY);
transformer.startTransformation(mediaItem, outputPath);
transformer.cancel();
@@ -238,7 +282,7 @@ public final class TransformerTest {
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
- assertThat(new File(outputPath).length()).isEqualTo(FILE_VIDEO_ONLY_SAMPLE_DATA_LENGTH);
+ DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_VIDEO_ONLY));
}
@Test
@@ -247,8 +291,13 @@ public final class TransformerTest {
anotherThread.start();
Looper looper = anotherThread.getLooper();
Transformer transformer =
- new Transformer.Builder().setContext(context).setLooper(looper).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_AUDIO_ONLY);
+ new Transformer.Builder()
+ .setContext(context)
+ .setLooper(looper)
+ .setClock(clock)
+ .setMuxerFactory(new TestMuxerFactory())
+ .build();
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_AUDIO_ONLY);
AtomicReference exception = new AtomicReference<>();
CountDownLatch countDownLatch = new CountDownLatch(1);
@@ -267,13 +316,13 @@ public final class TransformerTest {
countDownLatch.await();
assertThat(exception.get()).isNull();
- assertThat(new File(outputPath).length()).isEqualTo(FILE_AUDIO_ONLY_SAMPLE_DATA_LENGTH);
+ DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_AUDIO_ONLY));
}
@Test
public void startTransformation_fromWrongThread_throwsError() throws Exception {
Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_AUDIO_ONLY);
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_AUDIO_ONLY);
HandlerThread anotherThread = new HandlerThread("AnotherThread");
AtomicReference illegalStateException = new AtomicReference<>();
CountDownLatch countDownLatch = new CountDownLatch(1);
@@ -300,7 +349,7 @@ public final class TransformerTest {
@Test
public void getProgress_knownDuration_returnsConsistentStates() throws Exception {
Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_VIDEO_ONLY);
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_VIDEO_ONLY);
AtomicInteger previousProgressState =
new AtomicInteger(PROGRESS_STATE_WAITING_FOR_AVAILABILITY);
AtomicBoolean foundInconsistentState = new AtomicBoolean();
@@ -346,7 +395,7 @@ public final class TransformerTest {
@Test
public void getProgress_knownDuration_givesIncreasingPercentages() throws Exception {
Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_VIDEO_ONLY);
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_VIDEO_ONLY);
List progresses = new ArrayList<>();
Handler progressHandler =
new Handler(Looper.myLooper()) {
@@ -381,7 +430,7 @@ public final class TransformerTest {
@Test
public void getProgress_noCurrentTransformation_returnsNoTransformation() throws Exception {
Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_VIDEO_ONLY);
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_VIDEO_ONLY);
@Transformer.ProgressState int stateBeforeTransform = transformer.getProgress(progressHolder);
transformer.startTransformation(mediaItem, outputPath);
@@ -395,7 +444,7 @@ public final class TransformerTest {
@Test
public void getProgress_unknownDuration_returnsConsistentStates() throws Exception {
Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri("asset:///media/mp4/sample_fragmented.mp4");
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_UNKNOWN_DURATION);
AtomicInteger previousProgressState =
new AtomicInteger(PROGRESS_STATE_WAITING_FOR_AVAILABILITY);
AtomicBoolean foundInconsistentState = new AtomicBoolean();
@@ -462,7 +511,7 @@ public final class TransformerTest {
@Test
public void cancel_afterCompletion_doesNotThrow() throws Exception {
Transformer transformer = new Transformer.Builder().setContext(context).setClock(clock).build();
- MediaItem mediaItem = MediaItem.fromUri(FILE_VIDEO_ONLY);
+ MediaItem mediaItem = MediaItem.fromUri(URI_PREFIX + FILE_VIDEO_ONLY);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runUntilCompleted(transformer);
@@ -507,4 +556,28 @@ public final class TransformerTest {
private static void removeEncodersAndDecoders() {
ShadowMediaCodec.clearCodecs();
}
+
+ private static String getDumpFileName(String originalFileName) {
+ return DUMP_FILE_OUTPUT_DIRECTORY + '/' + originalFileName + '.' + DUMP_FILE_EXTENSION;
+ }
+
+ private final class TestMuxerFactory implements Muxer.Factory {
+ @Override
+ public Muxer create(String path, String outputMimeType) throws IOException {
+ testMuxer = new TestMuxer(path, outputMimeType);
+ return testMuxer;
+ }
+
+ @Override
+ public Muxer create(ParcelFileDescriptor parcelFileDescriptor, String outputMimeType)
+ throws IOException {
+ testMuxer = new TestMuxer("FD:" + parcelFileDescriptor.getFd(), outputMimeType);
+ return testMuxer;
+ }
+
+ @Override
+ public boolean supportsOutputMimeType(String mimeType) {
+ return true;
+ }
+ }
}
diff --git a/testdata/src/test/assets/transformerdumps/amr/sample_nb.amr.dump b/testdata/src/test/assets/transformerdumps/amr/sample_nb.amr.dump
new file mode 100644
index 0000000000..f48431a0f7
--- /dev/null
+++ b/testdata/src/test/assets/transformerdumps/amr/sample_nb.amr.dump
@@ -0,0 +1,1096 @@
+containerMimeType = video/mp4
+format 0:
+ sampleMimeType = audio/3gpp
+ channelCount = 1
+ sampleRate = 8000
+sample:
+ trackIndex = 0
+ dataHashCode = 924517484
+ isKeyFrame = true
+ presentationTimeUs = 0
+sample:
+ trackIndex = 0
+ dataHashCode = -835666085
+ isKeyFrame = true
+ presentationTimeUs = 750
+sample:
+ trackIndex = 0
+ dataHashCode = 430283125
+ isKeyFrame = true
+ presentationTimeUs = 1500
+sample:
+ trackIndex = 0
+ dataHashCode = 1215919932
+ isKeyFrame = true
+ presentationTimeUs = 2250
+sample:
+ trackIndex = 0
+ dataHashCode = -386387943
+ isKeyFrame = true
+ presentationTimeUs = 3000
+sample:
+ trackIndex = 0
+ dataHashCode = -765080119
+ isKeyFrame = true
+ presentationTimeUs = 3750
+sample:
+ trackIndex = 0
+ dataHashCode = -1855636054
+ isKeyFrame = true
+ presentationTimeUs = 4500
+sample:
+ trackIndex = 0
+ dataHashCode = -946579722
+ isKeyFrame = true
+ presentationTimeUs = 5250
+sample:
+ trackIndex = 0
+ dataHashCode = -841202654
+ isKeyFrame = true
+ presentationTimeUs = 6000
+sample:
+ trackIndex = 0
+ dataHashCode = -638764303
+ isKeyFrame = true
+ presentationTimeUs = 6750
+sample:
+ trackIndex = 0
+ dataHashCode = -1162388941
+ isKeyFrame = true
+ presentationTimeUs = 7500
+sample:
+ trackIndex = 0
+ dataHashCode = 572634367
+ isKeyFrame = true
+ presentationTimeUs = 8250
+sample:
+ trackIndex = 0
+ dataHashCode = -1774188021
+ isKeyFrame = true
+ presentationTimeUs = 9000
+sample:
+ trackIndex = 0
+ dataHashCode = 92464891
+ isKeyFrame = true
+ presentationTimeUs = 9750
+sample:
+ trackIndex = 0
+ dataHashCode = -991397659
+ isKeyFrame = true
+ presentationTimeUs = 10500
+sample:
+ trackIndex = 0
+ dataHashCode = -934698563
+ isKeyFrame = true
+ presentationTimeUs = 11250
+sample:
+ trackIndex = 0
+ dataHashCode = -811030035
+ isKeyFrame = true
+ presentationTimeUs = 12000
+sample:
+ trackIndex = 0
+ dataHashCode = 1892305159
+ isKeyFrame = true
+ presentationTimeUs = 12750
+sample:
+ trackIndex = 0
+ dataHashCode = -1266858924
+ isKeyFrame = true
+ presentationTimeUs = 13500
+sample:
+ trackIndex = 0
+ dataHashCode = 673814721
+ isKeyFrame = true
+ presentationTimeUs = 14250
+sample:
+ trackIndex = 0
+ dataHashCode = 1061124709
+ isKeyFrame = true
+ presentationTimeUs = 15000
+sample:
+ trackIndex = 0
+ dataHashCode = -869356712
+ isKeyFrame = true
+ presentationTimeUs = 15750
+sample:
+ trackIndex = 0
+ dataHashCode = 664729362
+ isKeyFrame = true
+ presentationTimeUs = 16500
+sample:
+ trackIndex = 0
+ dataHashCode = -1439741143
+ isKeyFrame = true
+ presentationTimeUs = 17250
+sample:
+ trackIndex = 0
+ dataHashCode = -151627580
+ isKeyFrame = true
+ presentationTimeUs = 18000
+sample:
+ trackIndex = 0
+ dataHashCode = -673268457
+ isKeyFrame = true
+ presentationTimeUs = 18750
+sample:
+ trackIndex = 0
+ dataHashCode = 1839962647
+ isKeyFrame = true
+ presentationTimeUs = 19500
+sample:
+ trackIndex = 0
+ dataHashCode = 1858999665
+ isKeyFrame = true
+ presentationTimeUs = 20250
+sample:
+ trackIndex = 0
+ dataHashCode = -1278193537
+ isKeyFrame = true
+ presentationTimeUs = 21000
+sample:
+ trackIndex = 0
+ dataHashCode = 568547001
+ isKeyFrame = true
+ presentationTimeUs = 21750
+sample:
+ trackIndex = 0
+ dataHashCode = 68217362
+ isKeyFrame = true
+ presentationTimeUs = 22500
+sample:
+ trackIndex = 0
+ dataHashCode = 1396217256
+ isKeyFrame = true
+ presentationTimeUs = 23250
+sample:
+ trackIndex = 0
+ dataHashCode = -971293094
+ isKeyFrame = true
+ presentationTimeUs = 24000
+sample:
+ trackIndex = 0
+ dataHashCode = -1742638874
+ isKeyFrame = true
+ presentationTimeUs = 24750
+sample:
+ trackIndex = 0
+ dataHashCode = 2047109317
+ isKeyFrame = true
+ presentationTimeUs = 25500
+sample:
+ trackIndex = 0
+ dataHashCode = -1668945241
+ isKeyFrame = true
+ presentationTimeUs = 26250
+sample:
+ trackIndex = 0
+ dataHashCode = -1229766218
+ isKeyFrame = true
+ presentationTimeUs = 27000
+sample:
+ trackIndex = 0
+ dataHashCode = 1765233454
+ isKeyFrame = true
+ presentationTimeUs = 27750
+sample:
+ trackIndex = 0
+ dataHashCode = -1930255456
+ isKeyFrame = true
+ presentationTimeUs = 28500
+sample:
+ trackIndex = 0
+ dataHashCode = -764925242
+ isKeyFrame = true
+ presentationTimeUs = 29250
+sample:
+ trackIndex = 0
+ dataHashCode = -1144688369
+ isKeyFrame = true
+ presentationTimeUs = 30000
+sample:
+ trackIndex = 0
+ dataHashCode = 1493699436
+ isKeyFrame = true
+ presentationTimeUs = 30750
+sample:
+ trackIndex = 0
+ dataHashCode = -468614511
+ isKeyFrame = true
+ presentationTimeUs = 31500
+sample:
+ trackIndex = 0
+ dataHashCode = -1578782058
+ isKeyFrame = true
+ presentationTimeUs = 32250
+sample:
+ trackIndex = 0
+ dataHashCode = -675743397
+ isKeyFrame = true
+ presentationTimeUs = 33000
+sample:
+ trackIndex = 0
+ dataHashCode = -863790111
+ isKeyFrame = true
+ presentationTimeUs = 33750
+sample:
+ trackIndex = 0
+ dataHashCode = -732307506
+ isKeyFrame = true
+ presentationTimeUs = 34500
+sample:
+ trackIndex = 0
+ dataHashCode = -693298708
+ isKeyFrame = true
+ presentationTimeUs = 35250
+sample:
+ trackIndex = 0
+ dataHashCode = -799131843
+ isKeyFrame = true
+ presentationTimeUs = 36000
+sample:
+ trackIndex = 0
+ dataHashCode = 1782866119
+ isKeyFrame = true
+ presentationTimeUs = 36750
+sample:
+ trackIndex = 0
+ dataHashCode = -912205505
+ isKeyFrame = true
+ presentationTimeUs = 37500
+sample:
+ trackIndex = 0
+ dataHashCode = 1067981287
+ isKeyFrame = true
+ presentationTimeUs = 38250
+sample:
+ trackIndex = 0
+ dataHashCode = 490520060
+ isKeyFrame = true
+ presentationTimeUs = 39000
+sample:
+ trackIndex = 0
+ dataHashCode = -1950632957
+ isKeyFrame = true
+ presentationTimeUs = 39750
+sample:
+ trackIndex = 0
+ dataHashCode = 565485817
+ isKeyFrame = true
+ presentationTimeUs = 40500
+sample:
+ trackIndex = 0
+ dataHashCode = -1057414703
+ isKeyFrame = true
+ presentationTimeUs = 41250
+sample:
+ trackIndex = 0
+ dataHashCode = 1568746155
+ isKeyFrame = true
+ presentationTimeUs = 42000
+sample:
+ trackIndex = 0
+ dataHashCode = 1355412472
+ isKeyFrame = true
+ presentationTimeUs = 42750
+sample:
+ trackIndex = 0
+ dataHashCode = 1546368465
+ isKeyFrame = true
+ presentationTimeUs = 43500
+sample:
+ trackIndex = 0
+ dataHashCode = 1811529381
+ isKeyFrame = true
+ presentationTimeUs = 44250
+sample:
+ trackIndex = 0
+ dataHashCode = 658031078
+ isKeyFrame = true
+ presentationTimeUs = 45000
+sample:
+ trackIndex = 0
+ dataHashCode = 1606584486
+ isKeyFrame = true
+ presentationTimeUs = 45750
+sample:
+ trackIndex = 0
+ dataHashCode = 2123252778
+ isKeyFrame = true
+ presentationTimeUs = 46500
+sample:
+ trackIndex = 0
+ dataHashCode = -1364579398
+ isKeyFrame = true
+ presentationTimeUs = 47250
+sample:
+ trackIndex = 0
+ dataHashCode = 1311427887
+ isKeyFrame = true
+ presentationTimeUs = 48000
+sample:
+ trackIndex = 0
+ dataHashCode = -691467569
+ isKeyFrame = true
+ presentationTimeUs = 48750
+sample:
+ trackIndex = 0
+ dataHashCode = 1876470084
+ isKeyFrame = true
+ presentationTimeUs = 49500
+sample:
+ trackIndex = 0
+ dataHashCode = -1472873479
+ isKeyFrame = true
+ presentationTimeUs = 50250
+sample:
+ trackIndex = 0
+ dataHashCode = -143574992
+ isKeyFrame = true
+ presentationTimeUs = 51000
+sample:
+ trackIndex = 0
+ dataHashCode = 984180453
+ isKeyFrame = true
+ presentationTimeUs = 51750
+sample:
+ trackIndex = 0
+ dataHashCode = -113645527
+ isKeyFrame = true
+ presentationTimeUs = 52500
+sample:
+ trackIndex = 0
+ dataHashCode = 1987501641
+ isKeyFrame = true
+ presentationTimeUs = 53250
+sample:
+ trackIndex = 0
+ dataHashCode = -1816426230
+ isKeyFrame = true
+ presentationTimeUs = 54000
+sample:
+ trackIndex = 0
+ dataHashCode = -1250050360
+ isKeyFrame = true
+ presentationTimeUs = 54750
+sample:
+ trackIndex = 0
+ dataHashCode = 1722852790
+ isKeyFrame = true
+ presentationTimeUs = 55500
+sample:
+ trackIndex = 0
+ dataHashCode = 225656333
+ isKeyFrame = true
+ presentationTimeUs = 56250
+sample:
+ trackIndex = 0
+ dataHashCode = -2137778394
+ isKeyFrame = true
+ presentationTimeUs = 57000
+sample:
+ trackIndex = 0
+ dataHashCode = 1433327155
+ isKeyFrame = true
+ presentationTimeUs = 57750
+sample:
+ trackIndex = 0
+ dataHashCode = -974261023
+ isKeyFrame = true
+ presentationTimeUs = 58500
+sample:
+ trackIndex = 0
+ dataHashCode = 1797813317
+ isKeyFrame = true
+ presentationTimeUs = 59250
+sample:
+ trackIndex = 0
+ dataHashCode = -594033497
+ isKeyFrame = true
+ presentationTimeUs = 60000
+sample:
+ trackIndex = 0
+ dataHashCode = -628310540
+ isKeyFrame = true
+ presentationTimeUs = 60750
+sample:
+ trackIndex = 0
+ dataHashCode = 1868627831
+ isKeyFrame = true
+ presentationTimeUs = 61500
+sample:
+ trackIndex = 0
+ dataHashCode = 1051863958
+ isKeyFrame = true
+ presentationTimeUs = 62250
+sample:
+ trackIndex = 0
+ dataHashCode = -1279059211
+ isKeyFrame = true
+ presentationTimeUs = 63000
+sample:
+ trackIndex = 0
+ dataHashCode = 408201874
+ isKeyFrame = true
+ presentationTimeUs = 63750
+sample:
+ trackIndex = 0
+ dataHashCode = 1686644299
+ isKeyFrame = true
+ presentationTimeUs = 64500
+sample:
+ trackIndex = 0
+ dataHashCode = 1288226241
+ isKeyFrame = true
+ presentationTimeUs = 65250
+sample:
+ trackIndex = 0
+ dataHashCode = 432829731
+ isKeyFrame = true
+ presentationTimeUs = 66000
+sample:
+ trackIndex = 0
+ dataHashCode = -1679312600
+ isKeyFrame = true
+ presentationTimeUs = 66750
+sample:
+ trackIndex = 0
+ dataHashCode = 1206680829
+ isKeyFrame = true
+ presentationTimeUs = 67500
+sample:
+ trackIndex = 0
+ dataHashCode = -325844704
+ isKeyFrame = true
+ presentationTimeUs = 68250
+sample:
+ trackIndex = 0
+ dataHashCode = 1941808848
+ isKeyFrame = true
+ presentationTimeUs = 69000
+sample:
+ trackIndex = 0
+ dataHashCode = -87346412
+ isKeyFrame = true
+ presentationTimeUs = 69750
+sample:
+ trackIndex = 0
+ dataHashCode = -329133765
+ isKeyFrame = true
+ presentationTimeUs = 70500
+sample:
+ trackIndex = 0
+ dataHashCode = -1299416212
+ isKeyFrame = true
+ presentationTimeUs = 71250
+sample:
+ trackIndex = 0
+ dataHashCode = -1314599219
+ isKeyFrame = true
+ presentationTimeUs = 72000
+sample:
+ trackIndex = 0
+ dataHashCode = 1456741286
+ isKeyFrame = true
+ presentationTimeUs = 72750
+sample:
+ trackIndex = 0
+ dataHashCode = 151296500
+ isKeyFrame = true
+ presentationTimeUs = 73500
+sample:
+ trackIndex = 0
+ dataHashCode = 1708763603
+ isKeyFrame = true
+ presentationTimeUs = 74250
+sample:
+ trackIndex = 0
+ dataHashCode = 227542220
+ isKeyFrame = true
+ presentationTimeUs = 75000
+sample:
+ trackIndex = 0
+ dataHashCode = 1094305517
+ isKeyFrame = true
+ presentationTimeUs = 75750
+sample:
+ trackIndex = 0
+ dataHashCode = -990377604
+ isKeyFrame = true
+ presentationTimeUs = 76500
+sample:
+ trackIndex = 0
+ dataHashCode = -1798036230
+ isKeyFrame = true
+ presentationTimeUs = 77250
+sample:
+ trackIndex = 0
+ dataHashCode = -1027148291
+ isKeyFrame = true
+ presentationTimeUs = 78000
+sample:
+ trackIndex = 0
+ dataHashCode = 359763976
+ isKeyFrame = true
+ presentationTimeUs = 78750
+sample:
+ trackIndex = 0
+ dataHashCode = 1332016420
+ isKeyFrame = true
+ presentationTimeUs = 79500
+sample:
+ trackIndex = 0
+ dataHashCode = -102753250
+ isKeyFrame = true
+ presentationTimeUs = 80250
+sample:
+ trackIndex = 0
+ dataHashCode = 1959063156
+ isKeyFrame = true
+ presentationTimeUs = 81000
+sample:
+ trackIndex = 0
+ dataHashCode = 2129089853
+ isKeyFrame = true
+ presentationTimeUs = 81750
+sample:
+ trackIndex = 0
+ dataHashCode = 1658742073
+ isKeyFrame = true
+ presentationTimeUs = 82500
+sample:
+ trackIndex = 0
+ dataHashCode = 2136916514
+ isKeyFrame = true
+ presentationTimeUs = 83250
+sample:
+ trackIndex = 0
+ dataHashCode = 105121407
+ isKeyFrame = true
+ presentationTimeUs = 84000
+sample:
+ trackIndex = 0
+ dataHashCode = -839464484
+ isKeyFrame = true
+ presentationTimeUs = 84750
+sample:
+ trackIndex = 0
+ dataHashCode = -1956791168
+ isKeyFrame = true
+ presentationTimeUs = 85500
+sample:
+ trackIndex = 0
+ dataHashCode = -1387546109
+ isKeyFrame = true
+ presentationTimeUs = 86250
+sample:
+ trackIndex = 0
+ dataHashCode = 128410432
+ isKeyFrame = true
+ presentationTimeUs = 87000
+sample:
+ trackIndex = 0
+ dataHashCode = 907081136
+ isKeyFrame = true
+ presentationTimeUs = 87750
+sample:
+ trackIndex = 0
+ dataHashCode = 1124845067
+ isKeyFrame = true
+ presentationTimeUs = 88500
+sample:
+ trackIndex = 0
+ dataHashCode = -1714479962
+ isKeyFrame = true
+ presentationTimeUs = 89250
+sample:
+ trackIndex = 0
+ dataHashCode = 322029323
+ isKeyFrame = true
+ presentationTimeUs = 90000
+sample:
+ trackIndex = 0
+ dataHashCode = -1116281187
+ isKeyFrame = true
+ presentationTimeUs = 90750
+sample:
+ trackIndex = 0
+ dataHashCode = 1571181228
+ isKeyFrame = true
+ presentationTimeUs = 91500
+sample:
+ trackIndex = 0
+ dataHashCode = 997979854
+ isKeyFrame = true
+ presentationTimeUs = 92250
+sample:
+ trackIndex = 0
+ dataHashCode = -1413492413
+ isKeyFrame = true
+ presentationTimeUs = 93000
+sample:
+ trackIndex = 0
+ dataHashCode = -381390490
+ isKeyFrame = true
+ presentationTimeUs = 93750
+sample:
+ trackIndex = 0
+ dataHashCode = -331348340
+ isKeyFrame = true
+ presentationTimeUs = 94500
+sample:
+ trackIndex = 0
+ dataHashCode = -1568238592
+ isKeyFrame = true
+ presentationTimeUs = 95250
+sample:
+ trackIndex = 0
+ dataHashCode = -941591445
+ isKeyFrame = true
+ presentationTimeUs = 96000
+sample:
+ trackIndex = 0
+ dataHashCode = 1616911281
+ isKeyFrame = true
+ presentationTimeUs = 96750
+sample:
+ trackIndex = 0
+ dataHashCode = -1755664741
+ isKeyFrame = true
+ presentationTimeUs = 97500
+sample:
+ trackIndex = 0
+ dataHashCode = -1950609742
+ isKeyFrame = true
+ presentationTimeUs = 98250
+sample:
+ trackIndex = 0
+ dataHashCode = 1476082149
+ isKeyFrame = true
+ presentationTimeUs = 99000
+sample:
+ trackIndex = 0
+ dataHashCode = 1289547483
+ isKeyFrame = true
+ presentationTimeUs = 99750
+sample:
+ trackIndex = 0
+ dataHashCode = -367599018
+ isKeyFrame = true
+ presentationTimeUs = 100500
+sample:
+ trackIndex = 0
+ dataHashCode = 679378334
+ isKeyFrame = true
+ presentationTimeUs = 101250
+sample:
+ trackIndex = 0
+ dataHashCode = 1437306809
+ isKeyFrame = true
+ presentationTimeUs = 102000
+sample:
+ trackIndex = 0
+ dataHashCode = 311988463
+ isKeyFrame = true
+ presentationTimeUs = 102750
+sample:
+ trackIndex = 0
+ dataHashCode = -1870442665
+ isKeyFrame = true
+ presentationTimeUs = 103500
+sample:
+ trackIndex = 0
+ dataHashCode = 1530013920
+ isKeyFrame = true
+ presentationTimeUs = 104250
+sample:
+ trackIndex = 0
+ dataHashCode = -585506443
+ isKeyFrame = true
+ presentationTimeUs = 105000
+sample:
+ trackIndex = 0
+ dataHashCode = -293690558
+ isKeyFrame = true
+ presentationTimeUs = 105750
+sample:
+ trackIndex = 0
+ dataHashCode = -616893325
+ isKeyFrame = true
+ presentationTimeUs = 106500
+sample:
+ trackIndex = 0
+ dataHashCode = 632210495
+ isKeyFrame = true
+ presentationTimeUs = 107250
+sample:
+ trackIndex = 0
+ dataHashCode = -291767937
+ isKeyFrame = true
+ presentationTimeUs = 108000
+sample:
+ trackIndex = 0
+ dataHashCode = -270265
+ isKeyFrame = true
+ presentationTimeUs = 108750
+sample:
+ trackIndex = 0
+ dataHashCode = -1095959376
+ isKeyFrame = true
+ presentationTimeUs = 109500
+sample:
+ trackIndex = 0
+ dataHashCode = -1363867284
+ isKeyFrame = true
+ presentationTimeUs = 110250
+sample:
+ trackIndex = 0
+ dataHashCode = 185415707
+ isKeyFrame = true
+ presentationTimeUs = 111000
+sample:
+ trackIndex = 0
+ dataHashCode = 1033720098
+ isKeyFrame = true
+ presentationTimeUs = 111750
+sample:
+ trackIndex = 0
+ dataHashCode = 1813896085
+ isKeyFrame = true
+ presentationTimeUs = 112500
+sample:
+ trackIndex = 0
+ dataHashCode = -1381192241
+ isKeyFrame = true
+ presentationTimeUs = 113250
+sample:
+ trackIndex = 0
+ dataHashCode = 362689054
+ isKeyFrame = true
+ presentationTimeUs = 114000
+sample:
+ trackIndex = 0
+ dataHashCode = -1320787356
+ isKeyFrame = true
+ presentationTimeUs = 114750
+sample:
+ trackIndex = 0
+ dataHashCode = 1306489379
+ isKeyFrame = true
+ presentationTimeUs = 115500
+sample:
+ trackIndex = 0
+ dataHashCode = -910313430
+ isKeyFrame = true
+ presentationTimeUs = 116250
+sample:
+ trackIndex = 0
+ dataHashCode = -1533334115
+ isKeyFrame = true
+ presentationTimeUs = 117000
+sample:
+ trackIndex = 0
+ dataHashCode = -700061723
+ isKeyFrame = true
+ presentationTimeUs = 117750
+sample:
+ trackIndex = 0
+ dataHashCode = 474100444
+ isKeyFrame = true
+ presentationTimeUs = 118500
+sample:
+ trackIndex = 0
+ dataHashCode = -2096659943
+ isKeyFrame = true
+ presentationTimeUs = 119250
+sample:
+ trackIndex = 0
+ dataHashCode = -690442126
+ isKeyFrame = true
+ presentationTimeUs = 120000
+sample:
+ trackIndex = 0
+ dataHashCode = 158718784
+ isKeyFrame = true
+ presentationTimeUs = 120750
+sample:
+ trackIndex = 0
+ dataHashCode = -1587553019
+ isKeyFrame = true
+ presentationTimeUs = 121500
+sample:
+ trackIndex = 0
+ dataHashCode = 1266916929
+ isKeyFrame = true
+ presentationTimeUs = 122250
+sample:
+ trackIndex = 0
+ dataHashCode = 1947792537
+ isKeyFrame = true
+ presentationTimeUs = 123000
+sample:
+ trackIndex = 0
+ dataHashCode = 2051622372
+ isKeyFrame = true
+ presentationTimeUs = 123750
+sample:
+ trackIndex = 0
+ dataHashCode = 1648973196
+ isKeyFrame = true
+ presentationTimeUs = 124500
+sample:
+ trackIndex = 0
+ dataHashCode = -1119069213
+ isKeyFrame = true
+ presentationTimeUs = 125250
+sample:
+ trackIndex = 0
+ dataHashCode = -1162670307
+ isKeyFrame = true
+ presentationTimeUs = 126000
+sample:
+ trackIndex = 0
+ dataHashCode = 505180178
+ isKeyFrame = true
+ presentationTimeUs = 126750
+sample:
+ trackIndex = 0
+ dataHashCode = -1707111799
+ isKeyFrame = true
+ presentationTimeUs = 127500
+sample:
+ trackIndex = 0
+ dataHashCode = 549350779
+ isKeyFrame = true
+ presentationTimeUs = 128250
+sample:
+ trackIndex = 0
+ dataHashCode = -895461091
+ isKeyFrame = true
+ presentationTimeUs = 129000
+sample:
+ trackIndex = 0
+ dataHashCode = 1834306839
+ isKeyFrame = true
+ presentationTimeUs = 129750
+sample:
+ trackIndex = 0
+ dataHashCode = -646169807
+ isKeyFrame = true
+ presentationTimeUs = 130500
+sample:
+ trackIndex = 0
+ dataHashCode = 123454915
+ isKeyFrame = true
+ presentationTimeUs = 131250
+sample:
+ trackIndex = 0
+ dataHashCode = 2074179659
+ isKeyFrame = true
+ presentationTimeUs = 132000
+sample:
+ trackIndex = 0
+ dataHashCode = 488070546
+ isKeyFrame = true
+ presentationTimeUs = 132750
+sample:
+ trackIndex = 0
+ dataHashCode = -1379245827
+ isKeyFrame = true
+ presentationTimeUs = 133500
+sample:
+ trackIndex = 0
+ dataHashCode = 922846867
+ isKeyFrame = true
+ presentationTimeUs = 134250
+sample:
+ trackIndex = 0
+ dataHashCode = 1163092079
+ isKeyFrame = true
+ presentationTimeUs = 135000
+sample:
+ trackIndex = 0
+ dataHashCode = -817674907
+ isKeyFrame = true
+ presentationTimeUs = 135750
+sample:
+ trackIndex = 0
+ dataHashCode = -765143209
+ isKeyFrame = true
+ presentationTimeUs = 136500
+sample:
+ trackIndex = 0
+ dataHashCode = 1337234415
+ isKeyFrame = true
+ presentationTimeUs = 137250
+sample:
+ trackIndex = 0
+ dataHashCode = 152696122
+ isKeyFrame = true
+ presentationTimeUs = 138000
+sample:
+ trackIndex = 0
+ dataHashCode = -1037369189
+ isKeyFrame = true
+ presentationTimeUs = 138750
+sample:
+ trackIndex = 0
+ dataHashCode = 93852784
+ isKeyFrame = true
+ presentationTimeUs = 139500
+sample:
+ trackIndex = 0
+ dataHashCode = -1512860804
+ isKeyFrame = true
+ presentationTimeUs = 140250
+sample:
+ trackIndex = 0
+ dataHashCode = -1571797975
+ isKeyFrame = true
+ presentationTimeUs = 141000
+sample:
+ trackIndex = 0
+ dataHashCode = -1390710594
+ isKeyFrame = true
+ presentationTimeUs = 141750
+sample:
+ trackIndex = 0
+ dataHashCode = 775548254
+ isKeyFrame = true
+ presentationTimeUs = 142500
+sample:
+ trackIndex = 0
+ dataHashCode = 329825934
+ isKeyFrame = true
+ presentationTimeUs = 143250
+sample:
+ trackIndex = 0
+ dataHashCode = 449672203
+ isKeyFrame = true
+ presentationTimeUs = 144000
+sample:
+ trackIndex = 0
+ dataHashCode = 135215283
+ isKeyFrame = true
+ presentationTimeUs = 144750
+sample:
+ trackIndex = 0
+ dataHashCode = -627202145
+ isKeyFrame = true
+ presentationTimeUs = 145500
+sample:
+ trackIndex = 0
+ dataHashCode = 565795710
+ isKeyFrame = true
+ presentationTimeUs = 146250
+sample:
+ trackIndex = 0
+ dataHashCode = -853390981
+ isKeyFrame = true
+ presentationTimeUs = 147000
+sample:
+ trackIndex = 0
+ dataHashCode = 1904980829
+ isKeyFrame = true
+ presentationTimeUs = 147750
+sample:
+ trackIndex = 0
+ dataHashCode = 1772857005
+ isKeyFrame = true
+ presentationTimeUs = 148500
+sample:
+ trackIndex = 0
+ dataHashCode = -1159621303
+ isKeyFrame = true
+ presentationTimeUs = 149250
+sample:
+ trackIndex = 0
+ dataHashCode = 712585139
+ isKeyFrame = true
+ presentationTimeUs = 150000
+sample:
+ trackIndex = 0
+ dataHashCode = 7470296
+ isKeyFrame = true
+ presentationTimeUs = 150750
+sample:
+ trackIndex = 0
+ dataHashCode = 1154659763
+ isKeyFrame = true
+ presentationTimeUs = 151500
+sample:
+ trackIndex = 0
+ dataHashCode = 512209179
+ isKeyFrame = true
+ presentationTimeUs = 152250
+sample:
+ trackIndex = 0
+ dataHashCode = 2026712081
+ isKeyFrame = true
+ presentationTimeUs = 153000
+sample:
+ trackIndex = 0
+ dataHashCode = -1625715216
+ isKeyFrame = true
+ presentationTimeUs = 153750
+sample:
+ trackIndex = 0
+ dataHashCode = -1299058326
+ isKeyFrame = true
+ presentationTimeUs = 154500
+sample:
+ trackIndex = 0
+ dataHashCode = -813560096
+ isKeyFrame = true
+ presentationTimeUs = 155250
+sample:
+ trackIndex = 0
+ dataHashCode = 1311045251
+ isKeyFrame = true
+ presentationTimeUs = 156000
+sample:
+ trackIndex = 0
+ dataHashCode = 1388107407
+ isKeyFrame = true
+ presentationTimeUs = 156750
+sample:
+ trackIndex = 0
+ dataHashCode = 1113099440
+ isKeyFrame = true
+ presentationTimeUs = 157500
+sample:
+ trackIndex = 0
+ dataHashCode = -339743582
+ isKeyFrame = true
+ presentationTimeUs = 158250
+sample:
+ trackIndex = 0
+ dataHashCode = -1055895345
+ isKeyFrame = true
+ presentationTimeUs = 159000
+sample:
+ trackIndex = 0
+ dataHashCode = 1869841923
+ isKeyFrame = true
+ presentationTimeUs = 159750
+sample:
+ trackIndex = 0
+ dataHashCode = 229443301
+ isKeyFrame = true
+ presentationTimeUs = 160500
+sample:
+ trackIndex = 0
+ dataHashCode = 1526951012
+ isKeyFrame = true
+ presentationTimeUs = 161250
+sample:
+ trackIndex = 0
+ dataHashCode = -1517436626
+ isKeyFrame = true
+ presentationTimeUs = 162000
+sample:
+ trackIndex = 0
+ dataHashCode = -1403405700
+ isKeyFrame = true
+ presentationTimeUs = 162750
+released = true
diff --git a/testdata/src/test/assets/transformerdumps/mkv/sample.mkv.dump b/testdata/src/test/assets/transformerdumps/mkv/sample.mkv.dump
new file mode 100644
index 0000000000..00d39b034e
--- /dev/null
+++ b/testdata/src/test/assets/transformerdumps/mkv/sample.mkv.dump
@@ -0,0 +1,163 @@
+containerMimeType = video/mp4
+format 0:
+ id = 1
+ sampleMimeType = video/avc
+ codecs = avc1.640034
+ width = 1080
+ height = 720
+ selectionFlags = 1
+ language = und
+ initializationData:
+ data = length 30, hash F6F3D010
+ data = length 10, hash 7A0D0F2B
+sample:
+ trackIndex = 0
+ dataHashCode = -252482306
+ isKeyFrame = true
+ presentationTimeUs = 67000
+sample:
+ trackIndex = 0
+ dataHashCode = 67864034
+ isKeyFrame = false
+ presentationTimeUs = 134000
+sample:
+ trackIndex = 0
+ dataHashCode = 897273234
+ isKeyFrame = false
+ presentationTimeUs = 100000
+sample:
+ trackIndex = 0
+ dataHashCode = -1549870586
+ isKeyFrame = false
+ presentationTimeUs = 267000
+sample:
+ trackIndex = 0
+ dataHashCode = 672384813
+ isKeyFrame = false
+ presentationTimeUs = 200000
+sample:
+ trackIndex = 0
+ dataHashCode = -988996493
+ isKeyFrame = false
+ presentationTimeUs = 167000
+sample:
+ trackIndex = 0
+ dataHashCode = 1711151377
+ isKeyFrame = false
+ presentationTimeUs = 234000
+sample:
+ trackIndex = 0
+ dataHashCode = -506806036
+ isKeyFrame = false
+ presentationTimeUs = 400000
+sample:
+ trackIndex = 0
+ dataHashCode = 1902167649
+ isKeyFrame = false
+ presentationTimeUs = 334000
+sample:
+ trackIndex = 0
+ dataHashCode = 2054873212
+ isKeyFrame = false
+ presentationTimeUs = 300000
+sample:
+ trackIndex = 0
+ dataHashCode = 1556608231
+ isKeyFrame = false
+ presentationTimeUs = 367000
+sample:
+ trackIndex = 0
+ dataHashCode = -1648978019
+ isKeyFrame = false
+ presentationTimeUs = 500000
+sample:
+ trackIndex = 0
+ dataHashCode = -484808327
+ isKeyFrame = false
+ presentationTimeUs = 467000
+sample:
+ trackIndex = 0
+ dataHashCode = -20706048
+ isKeyFrame = false
+ presentationTimeUs = 434000
+sample:
+ trackIndex = 0
+ dataHashCode = 2085064574
+ isKeyFrame = false
+ presentationTimeUs = 634000
+sample:
+ trackIndex = 0
+ dataHashCode = -637074022
+ isKeyFrame = false
+ presentationTimeUs = 567000
+sample:
+ trackIndex = 0
+ dataHashCode = -1824027029
+ isKeyFrame = false
+ presentationTimeUs = 534000
+sample:
+ trackIndex = 0
+ dataHashCode = -1701945306
+ isKeyFrame = false
+ presentationTimeUs = 600000
+sample:
+ trackIndex = 0
+ dataHashCode = -952425536
+ isKeyFrame = false
+ presentationTimeUs = 767000
+sample:
+ trackIndex = 0
+ dataHashCode = -1978031576
+ isKeyFrame = false
+ presentationTimeUs = 700000
+sample:
+ trackIndex = 0
+ dataHashCode = -2128215508
+ isKeyFrame = false
+ presentationTimeUs = 667000
+sample:
+ trackIndex = 0
+ dataHashCode = -259850011
+ isKeyFrame = false
+ presentationTimeUs = 734000
+sample:
+ trackIndex = 0
+ dataHashCode = 1920983928
+ isKeyFrame = false
+ presentationTimeUs = 900000
+sample:
+ trackIndex = 0
+ dataHashCode = 1100642337
+ isKeyFrame = false
+ presentationTimeUs = 834000
+sample:
+ trackIndex = 0
+ dataHashCode = 1544917830
+ isKeyFrame = false
+ presentationTimeUs = 800000
+sample:
+ trackIndex = 0
+ dataHashCode = -116205995
+ isKeyFrame = false
+ presentationTimeUs = 867000
+sample:
+ trackIndex = 0
+ dataHashCode = 696343585
+ isKeyFrame = false
+ presentationTimeUs = 1034000
+sample:
+ trackIndex = 0
+ dataHashCode = -644371190
+ isKeyFrame = false
+ presentationTimeUs = 967000
+sample:
+ trackIndex = 0
+ dataHashCode = -1606273467
+ isKeyFrame = false
+ presentationTimeUs = 934000
+sample:
+ trackIndex = 0
+ dataHashCode = -571265861
+ isKeyFrame = false
+ presentationTimeUs = 1000000
+released = true
diff --git a/testdata/src/test/assets/transformerdumps/mkv/sample_with_srt.mkv.dump b/testdata/src/test/assets/transformerdumps/mkv/sample_with_srt.mkv.dump
new file mode 100644
index 0000000000..05a19cd924
--- /dev/null
+++ b/testdata/src/test/assets/transformerdumps/mkv/sample_with_srt.mkv.dump
@@ -0,0 +1,163 @@
+containerMimeType = video/mp4
+format 0:
+ id = 1
+ sampleMimeType = video/avc
+ codecs = avc1.640034
+ width = 1080
+ height = 720
+ selectionFlags = 1
+ language = und
+ initializationData:
+ data = length 30, hash F6F3D010
+ data = length 10, hash 7A0D0F2B
+sample:
+ trackIndex = 0
+ dataHashCode = -252482306
+ isKeyFrame = true
+ presentationTimeUs = 0
+sample:
+ trackIndex = 0
+ dataHashCode = 67864034
+ isKeyFrame = false
+ presentationTimeUs = 67000
+sample:
+ trackIndex = 0
+ dataHashCode = 897273234
+ isKeyFrame = false
+ presentationTimeUs = 33000
+sample:
+ trackIndex = 0
+ dataHashCode = -1549870586
+ isKeyFrame = false
+ presentationTimeUs = 200000
+sample:
+ trackIndex = 0
+ dataHashCode = 672384813
+ isKeyFrame = false
+ presentationTimeUs = 133000
+sample:
+ trackIndex = 0
+ dataHashCode = -988996493
+ isKeyFrame = false
+ presentationTimeUs = 100000
+sample:
+ trackIndex = 0
+ dataHashCode = 1711151377
+ isKeyFrame = false
+ presentationTimeUs = 167000
+sample:
+ trackIndex = 0
+ dataHashCode = -506806036
+ isKeyFrame = false
+ presentationTimeUs = 333000
+sample:
+ trackIndex = 0
+ dataHashCode = 1902167649
+ isKeyFrame = false
+ presentationTimeUs = 267000
+sample:
+ trackIndex = 0
+ dataHashCode = 2054873212
+ isKeyFrame = false
+ presentationTimeUs = 233000
+sample:
+ trackIndex = 0
+ dataHashCode = 1556608231
+ isKeyFrame = false
+ presentationTimeUs = 300000
+sample:
+ trackIndex = 0
+ dataHashCode = -1648978019
+ isKeyFrame = false
+ presentationTimeUs = 433000
+sample:
+ trackIndex = 0
+ dataHashCode = -484808327
+ isKeyFrame = false
+ presentationTimeUs = 400000
+sample:
+ trackIndex = 0
+ dataHashCode = -20706048
+ isKeyFrame = false
+ presentationTimeUs = 367000
+sample:
+ trackIndex = 0
+ dataHashCode = 2085064574
+ isKeyFrame = false
+ presentationTimeUs = 567000
+sample:
+ trackIndex = 0
+ dataHashCode = -637074022
+ isKeyFrame = false
+ presentationTimeUs = 500000
+sample:
+ trackIndex = 0
+ dataHashCode = -1824027029
+ isKeyFrame = false
+ presentationTimeUs = 467000
+sample:
+ trackIndex = 0
+ dataHashCode = -1701945306
+ isKeyFrame = false
+ presentationTimeUs = 533000
+sample:
+ trackIndex = 0
+ dataHashCode = -952425536
+ isKeyFrame = false
+ presentationTimeUs = 700000
+sample:
+ trackIndex = 0
+ dataHashCode = -1978031576
+ isKeyFrame = false
+ presentationTimeUs = 633000
+sample:
+ trackIndex = 0
+ dataHashCode = -2128215508
+ isKeyFrame = false
+ presentationTimeUs = 600000
+sample:
+ trackIndex = 0
+ dataHashCode = -259850011
+ isKeyFrame = false
+ presentationTimeUs = 667000
+sample:
+ trackIndex = 0
+ dataHashCode = 1920983928
+ isKeyFrame = false
+ presentationTimeUs = 833000
+sample:
+ trackIndex = 0
+ dataHashCode = 1100642337
+ isKeyFrame = false
+ presentationTimeUs = 767000
+sample:
+ trackIndex = 0
+ dataHashCode = 1544917830
+ isKeyFrame = false
+ presentationTimeUs = 733000
+sample:
+ trackIndex = 0
+ dataHashCode = -116205995
+ isKeyFrame = false
+ presentationTimeUs = 800000
+sample:
+ trackIndex = 0
+ dataHashCode = 696343585
+ isKeyFrame = false
+ presentationTimeUs = 967000
+sample:
+ trackIndex = 0
+ dataHashCode = -644371190
+ isKeyFrame = false
+ presentationTimeUs = 900000
+sample:
+ trackIndex = 0
+ dataHashCode = -1606273467
+ isKeyFrame = false
+ presentationTimeUs = 867000
+sample:
+ trackIndex = 0
+ dataHashCode = -571265861
+ isKeyFrame = false
+ presentationTimeUs = 933000
+released = true
diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.dump b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.dump
new file mode 100644
index 0000000000..4ccbeae3d7
--- /dev/null
+++ b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.dump
@@ -0,0 +1,392 @@
+containerMimeType = video/mp4
+format 0:
+ sampleMimeType = audio/mp4a-latm
+ channelCount = 1
+ sampleRate = 44100
+format 1:
+ id = 1
+ sampleMimeType = video/avc
+ codecs = avc1.64001F
+ maxInputSize = 36722
+ width = 1080
+ height = 720
+ frameRate = 29.970028
+ initializationData:
+ data = length 29, hash 4746B5D9
+ data = length 10, hash 7A0D0F2B
+sample:
+ trackIndex = 1
+ dataHashCode = -770308242
+ isKeyFrame = true
+ presentationTimeUs = 0
+sample:
+ trackIndex = 1
+ dataHashCode = -732087136
+ isKeyFrame = false
+ presentationTimeUs = 66733
+sample:
+ trackIndex = 1
+ dataHashCode = 468156717
+ isKeyFrame = false
+ presentationTimeUs = 33366
+sample:
+ trackIndex = 1
+ dataHashCode = 1150349584
+ isKeyFrame = false
+ presentationTimeUs = 200200
+sample:
+ trackIndex = 1
+ dataHashCode = 1443582006
+ isKeyFrame = false
+ presentationTimeUs = 133466
+sample:
+ trackIndex = 1
+ dataHashCode = -310585145
+ isKeyFrame = false
+ presentationTimeUs = 100100
+sample:
+ trackIndex = 1
+ dataHashCode = 807460688
+ isKeyFrame = false
+ presentationTimeUs = 166833
+sample:
+ trackIndex = 1
+ dataHashCode = 1936487090
+ isKeyFrame = false
+ presentationTimeUs = 333666
+sample:
+ trackIndex = 1
+ dataHashCode = -32297181
+ isKeyFrame = false
+ presentationTimeUs = 266933
+sample:
+ trackIndex = 1
+ dataHashCode = 1529616406
+ isKeyFrame = false
+ presentationTimeUs = 233566
+sample:
+ trackIndex = 1
+ dataHashCode = 1949198785
+ isKeyFrame = false
+ presentationTimeUs = 300300
+sample:
+ trackIndex = 1
+ dataHashCode = -147880287
+ isKeyFrame = false
+ presentationTimeUs = 433766
+sample:
+ trackIndex = 1
+ dataHashCode = 1369083472
+ isKeyFrame = false
+ presentationTimeUs = 400400
+sample:
+ trackIndex = 1
+ dataHashCode = 965782073
+ isKeyFrame = false
+ presentationTimeUs = 367033
+sample:
+ trackIndex = 1
+ dataHashCode = -261176150
+ isKeyFrame = false
+ presentationTimeUs = 567233
+sample:
+ trackIndex = 0
+ dataHashCode = 1205768497
+ isKeyFrame = true
+ presentationTimeUs = 0
+sample:
+ trackIndex = 0
+ dataHashCode = 837571078
+ isKeyFrame = true
+ presentationTimeUs = 249
+sample:
+ trackIndex = 0
+ dataHashCode = -1991633045
+ isKeyFrame = true
+ presentationTimeUs = 317
+sample:
+ trackIndex = 0
+ dataHashCode = -822987359
+ isKeyFrame = true
+ presentationTimeUs = 1995
+sample:
+ trackIndex = 0
+ dataHashCode = -1141508176
+ isKeyFrame = true
+ presentationTimeUs = 4126
+sample:
+ trackIndex = 0
+ dataHashCode = -226971245
+ isKeyFrame = true
+ presentationTimeUs = 6438
+sample:
+ trackIndex = 0
+ dataHashCode = -2099636855
+ isKeyFrame = true
+ presentationTimeUs = 8818
+sample:
+ trackIndex = 0
+ dataHashCode = 1541550559
+ isKeyFrame = true
+ presentationTimeUs = 11198
+sample:
+ trackIndex = 0
+ dataHashCode = 411148001
+ isKeyFrame = true
+ presentationTimeUs = 13533
+sample:
+ trackIndex = 0
+ dataHashCode = -897603973
+ isKeyFrame = true
+ presentationTimeUs = 16072
+sample:
+ trackIndex = 0
+ dataHashCode = 1478106136
+ isKeyFrame = true
+ presentationTimeUs = 18498
+sample:
+ trackIndex = 0
+ dataHashCode = -1380417145
+ isKeyFrame = true
+ presentationTimeUs = 20878
+sample:
+ trackIndex = 0
+ dataHashCode = 780903644
+ isKeyFrame = true
+ presentationTimeUs = 23326
+sample:
+ trackIndex = 0
+ dataHashCode = 586204432
+ isKeyFrame = true
+ presentationTimeUs = 25911
+sample:
+ trackIndex = 0
+ dataHashCode = -2038771492
+ isKeyFrame = true
+ presentationTimeUs = 28541
+sample:
+ trackIndex = 0
+ dataHashCode = -2065161304
+ isKeyFrame = true
+ presentationTimeUs = 31194
+sample:
+ trackIndex = 0
+ dataHashCode = 468662933
+ isKeyFrame = true
+ presentationTimeUs = 33801
+sample:
+ trackIndex = 0
+ dataHashCode = -358398546
+ isKeyFrame = true
+ presentationTimeUs = 36363
+sample:
+ trackIndex = 0
+ dataHashCode = 1767325983
+ isKeyFrame = true
+ presentationTimeUs = 38811
+sample:
+ trackIndex = 0
+ dataHashCode = 1093095458
+ isKeyFrame = true
+ presentationTimeUs = 41396
+sample:
+ trackIndex = 0
+ dataHashCode = 1687543702
+ isKeyFrame = true
+ presentationTimeUs = 43867
+sample:
+ trackIndex = 0
+ dataHashCode = 1675188486
+ isKeyFrame = true
+ presentationTimeUs = 46588
+sample:
+ trackIndex = 0
+ dataHashCode = 888567545
+ isKeyFrame = true
+ presentationTimeUs = 49173
+sample:
+ trackIndex = 0
+ dataHashCode = -439631803
+ isKeyFrame = true
+ presentationTimeUs = 51871
+sample:
+ trackIndex = 0
+ dataHashCode = 1606694497
+ isKeyFrame = true
+ presentationTimeUs = 54524
+sample:
+ trackIndex = 0
+ dataHashCode = 1747388653
+ isKeyFrame = true
+ presentationTimeUs = 57131
+sample:
+ trackIndex = 0
+ dataHashCode = -734560004
+ isKeyFrame = true
+ presentationTimeUs = 59579
+sample:
+ trackIndex = 0
+ dataHashCode = -975079040
+ isKeyFrame = true
+ presentationTimeUs = 62277
+sample:
+ trackIndex = 0
+ dataHashCode = -1403504710
+ isKeyFrame = true
+ presentationTimeUs = 65020
+sample:
+ trackIndex = 0
+ dataHashCode = 379512981
+ isKeyFrame = true
+ presentationTimeUs = 67627
+sample:
+ trackIndex = 1
+ dataHashCode = -1830836678
+ isKeyFrame = false
+ presentationTimeUs = 500500
+sample:
+ trackIndex = 1
+ dataHashCode = 1767407540
+ isKeyFrame = false
+ presentationTimeUs = 467133
+sample:
+ trackIndex = 1
+ dataHashCode = 918440283
+ isKeyFrame = false
+ presentationTimeUs = 533866
+sample:
+ trackIndex = 1
+ dataHashCode = -1408463661
+ isKeyFrame = false
+ presentationTimeUs = 700700
+sample:
+ trackIndex = 0
+ dataHashCode = -997198863
+ isKeyFrame = true
+ presentationTimeUs = 70234
+sample:
+ trackIndex = 0
+ dataHashCode = 1394492825
+ isKeyFrame = true
+ presentationTimeUs = 72932
+sample:
+ trackIndex = 0
+ dataHashCode = -885232755
+ isKeyFrame = true
+ presentationTimeUs = 75471
+sample:
+ trackIndex = 0
+ dataHashCode = 260871367
+ isKeyFrame = true
+ presentationTimeUs = 78101
+sample:
+ trackIndex = 0
+ dataHashCode = -1505318960
+ isKeyFrame = true
+ presentationTimeUs = 80844
+sample:
+ trackIndex = 0
+ dataHashCode = -390625371
+ isKeyFrame = true
+ presentationTimeUs = 83474
+sample:
+ trackIndex = 0
+ dataHashCode = 1067950751
+ isKeyFrame = true
+ presentationTimeUs = 86149
+sample:
+ trackIndex = 0
+ dataHashCode = -1179436278
+ isKeyFrame = true
+ presentationTimeUs = 88734
+sample:
+ trackIndex = 0
+ dataHashCode = 1906607774
+ isKeyFrame = true
+ presentationTimeUs = 91387
+sample:
+ trackIndex = 0
+ dataHashCode = -800475828
+ isKeyFrame = true
+ presentationTimeUs = 94380
+sample:
+ trackIndex = 0
+ dataHashCode = 1718972977
+ isKeyFrame = true
+ presentationTimeUs = 97282
+sample:
+ trackIndex = 0
+ dataHashCode = -1120448741
+ isKeyFrame = true
+ presentationTimeUs = 99844
+sample:
+ trackIndex = 0
+ dataHashCode = -1718323210
+ isKeyFrame = true
+ presentationTimeUs = 102406
+sample:
+ trackIndex = 0
+ dataHashCode = -422416
+ isKeyFrame = true
+ presentationTimeUs = 105059
+sample:
+ trackIndex = 0
+ dataHashCode = 833757830
+ isKeyFrame = true
+ presentationTimeUs = 107644
+sample:
+ trackIndex = 1
+ dataHashCode = 1569455924
+ isKeyFrame = false
+ presentationTimeUs = 633966
+sample:
+ trackIndex = 1
+ dataHashCode = -1723778407
+ isKeyFrame = false
+ presentationTimeUs = 600600
+sample:
+ trackIndex = 1
+ dataHashCode = 1578275472
+ isKeyFrame = false
+ presentationTimeUs = 667333
+sample:
+ trackIndex = 1
+ dataHashCode = 1989768395
+ isKeyFrame = false
+ presentationTimeUs = 834166
+sample:
+ trackIndex = 1
+ dataHashCode = -1215674502
+ isKeyFrame = false
+ presentationTimeUs = 767433
+sample:
+ trackIndex = 1
+ dataHashCode = -814473606
+ isKeyFrame = false
+ presentationTimeUs = 734066
+sample:
+ trackIndex = 1
+ dataHashCode = 498370894
+ isKeyFrame = false
+ presentationTimeUs = 800800
+sample:
+ trackIndex = 1
+ dataHashCode = -1051506468
+ isKeyFrame = false
+ presentationTimeUs = 967633
+sample:
+ trackIndex = 1
+ dataHashCode = -1025604144
+ isKeyFrame = false
+ presentationTimeUs = 900900
+sample:
+ trackIndex = 1
+ dataHashCode = -913586520
+ isKeyFrame = false
+ presentationTimeUs = 867533
+sample:
+ trackIndex = 1
+ dataHashCode = 1340459242
+ isKeyFrame = false
+ presentationTimeUs = 934266
+released = true
diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.noaudio.dump b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.noaudio.dump
new file mode 100644
index 0000000000..d4484cbfb4
--- /dev/null
+++ b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.noaudio.dump
@@ -0,0 +1,163 @@
+containerMimeType = video/mp4
+format 0:
+ id = 1
+ sampleMimeType = video/avc
+ codecs = avc1.64001F
+ maxInputSize = 36722
+ width = 1080
+ height = 720
+ frameRate = 29.970028
+ initializationData:
+ data = length 29, hash 4746B5D9
+ data = length 10, hash 7A0D0F2B
+sample:
+ trackIndex = 0
+ dataHashCode = -770308242
+ isKeyFrame = true
+ presentationTimeUs = 0
+sample:
+ trackIndex = 0
+ dataHashCode = -732087136
+ isKeyFrame = false
+ presentationTimeUs = 66733
+sample:
+ trackIndex = 0
+ dataHashCode = 468156717
+ isKeyFrame = false
+ presentationTimeUs = 33366
+sample:
+ trackIndex = 0
+ dataHashCode = 1150349584
+ isKeyFrame = false
+ presentationTimeUs = 200200
+sample:
+ trackIndex = 0
+ dataHashCode = 1443582006
+ isKeyFrame = false
+ presentationTimeUs = 133466
+sample:
+ trackIndex = 0
+ dataHashCode = -310585145
+ isKeyFrame = false
+ presentationTimeUs = 100100
+sample:
+ trackIndex = 0
+ dataHashCode = 807460688
+ isKeyFrame = false
+ presentationTimeUs = 166833
+sample:
+ trackIndex = 0
+ dataHashCode = 1936487090
+ isKeyFrame = false
+ presentationTimeUs = 333666
+sample:
+ trackIndex = 0
+ dataHashCode = -32297181
+ isKeyFrame = false
+ presentationTimeUs = 266933
+sample:
+ trackIndex = 0
+ dataHashCode = 1529616406
+ isKeyFrame = false
+ presentationTimeUs = 233566
+sample:
+ trackIndex = 0
+ dataHashCode = 1949198785
+ isKeyFrame = false
+ presentationTimeUs = 300300
+sample:
+ trackIndex = 0
+ dataHashCode = -147880287
+ isKeyFrame = false
+ presentationTimeUs = 433766
+sample:
+ trackIndex = 0
+ dataHashCode = 1369083472
+ isKeyFrame = false
+ presentationTimeUs = 400400
+sample:
+ trackIndex = 0
+ dataHashCode = 965782073
+ isKeyFrame = false
+ presentationTimeUs = 367033
+sample:
+ trackIndex = 0
+ dataHashCode = -261176150
+ isKeyFrame = false
+ presentationTimeUs = 567233
+sample:
+ trackIndex = 0
+ dataHashCode = -1830836678
+ isKeyFrame = false
+ presentationTimeUs = 500500
+sample:
+ trackIndex = 0
+ dataHashCode = 1767407540
+ isKeyFrame = false
+ presentationTimeUs = 467133
+sample:
+ trackIndex = 0
+ dataHashCode = 918440283
+ isKeyFrame = false
+ presentationTimeUs = 533866
+sample:
+ trackIndex = 0
+ dataHashCode = -1408463661
+ isKeyFrame = false
+ presentationTimeUs = 700700
+sample:
+ trackIndex = 0
+ dataHashCode = 1569455924
+ isKeyFrame = false
+ presentationTimeUs = 633966
+sample:
+ trackIndex = 0
+ dataHashCode = -1723778407
+ isKeyFrame = false
+ presentationTimeUs = 600600
+sample:
+ trackIndex = 0
+ dataHashCode = 1578275472
+ isKeyFrame = false
+ presentationTimeUs = 667333
+sample:
+ trackIndex = 0
+ dataHashCode = 1989768395
+ isKeyFrame = false
+ presentationTimeUs = 834166
+sample:
+ trackIndex = 0
+ dataHashCode = -1215674502
+ isKeyFrame = false
+ presentationTimeUs = 767433
+sample:
+ trackIndex = 0
+ dataHashCode = -814473606
+ isKeyFrame = false
+ presentationTimeUs = 734066
+sample:
+ trackIndex = 0
+ dataHashCode = 498370894
+ isKeyFrame = false
+ presentationTimeUs = 800800
+sample:
+ trackIndex = 0
+ dataHashCode = -1051506468
+ isKeyFrame = false
+ presentationTimeUs = 967633
+sample:
+ trackIndex = 0
+ dataHashCode = -1025604144
+ isKeyFrame = false
+ presentationTimeUs = 900900
+sample:
+ trackIndex = 0
+ dataHashCode = -913586520
+ isKeyFrame = false
+ presentationTimeUs = 867533
+sample:
+ trackIndex = 0
+ dataHashCode = 1340459242
+ isKeyFrame = false
+ presentationTimeUs = 934266
+released = true
diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.novideo.dump b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.novideo.dump
new file mode 100644
index 0000000000..25e3aa791b
--- /dev/null
+++ b/testdata/src/test/assets/transformerdumps/mp4/sample.mp4.novideo.dump
@@ -0,0 +1,231 @@
+containerMimeType = video/mp4
+format 0:
+ sampleMimeType = audio/mp4a-latm
+ channelCount = 1
+ sampleRate = 44100
+sample:
+ trackIndex = 0
+ dataHashCode = 1205768497
+ isKeyFrame = true
+ presentationTimeUs = 0
+sample:
+ trackIndex = 0
+ dataHashCode = 837571078
+ isKeyFrame = true
+ presentationTimeUs = 249
+sample:
+ trackIndex = 0
+ dataHashCode = -1991633045
+ isKeyFrame = true
+ presentationTimeUs = 317
+sample:
+ trackIndex = 0
+ dataHashCode = -822987359
+ isKeyFrame = true
+ presentationTimeUs = 1995
+sample:
+ trackIndex = 0
+ dataHashCode = -1141508176
+ isKeyFrame = true
+ presentationTimeUs = 4126
+sample:
+ trackIndex = 0
+ dataHashCode = -226971245
+ isKeyFrame = true
+ presentationTimeUs = 6438
+sample:
+ trackIndex = 0
+ dataHashCode = -2099636855
+ isKeyFrame = true
+ presentationTimeUs = 8818
+sample:
+ trackIndex = 0
+ dataHashCode = 1541550559
+ isKeyFrame = true
+ presentationTimeUs = 11198
+sample:
+ trackIndex = 0
+ dataHashCode = 411148001
+ isKeyFrame = true
+ presentationTimeUs = 13533
+sample:
+ trackIndex = 0
+ dataHashCode = -897603973
+ isKeyFrame = true
+ presentationTimeUs = 16072
+sample:
+ trackIndex = 0
+ dataHashCode = 1478106136
+ isKeyFrame = true
+ presentationTimeUs = 18498
+sample:
+ trackIndex = 0
+ dataHashCode = -1380417145
+ isKeyFrame = true
+ presentationTimeUs = 20878
+sample:
+ trackIndex = 0
+ dataHashCode = 780903644
+ isKeyFrame = true
+ presentationTimeUs = 23326
+sample:
+ trackIndex = 0
+ dataHashCode = 586204432
+ isKeyFrame = true
+ presentationTimeUs = 25911
+sample:
+ trackIndex = 0
+ dataHashCode = -2038771492
+ isKeyFrame = true
+ presentationTimeUs = 28541
+sample:
+ trackIndex = 0
+ dataHashCode = -2065161304
+ isKeyFrame = true
+ presentationTimeUs = 31194
+sample:
+ trackIndex = 0
+ dataHashCode = 468662933
+ isKeyFrame = true
+ presentationTimeUs = 33801
+sample:
+ trackIndex = 0
+ dataHashCode = -358398546
+ isKeyFrame = true
+ presentationTimeUs = 36363
+sample:
+ trackIndex = 0
+ dataHashCode = 1767325983
+ isKeyFrame = true
+ presentationTimeUs = 38811
+sample:
+ trackIndex = 0
+ dataHashCode = 1093095458
+ isKeyFrame = true
+ presentationTimeUs = 41396
+sample:
+ trackIndex = 0
+ dataHashCode = 1687543702
+ isKeyFrame = true
+ presentationTimeUs = 43867
+sample:
+ trackIndex = 0
+ dataHashCode = 1675188486
+ isKeyFrame = true
+ presentationTimeUs = 46588
+sample:
+ trackIndex = 0
+ dataHashCode = 888567545
+ isKeyFrame = true
+ presentationTimeUs = 49173
+sample:
+ trackIndex = 0
+ dataHashCode = -439631803
+ isKeyFrame = true
+ presentationTimeUs = 51871
+sample:
+ trackIndex = 0
+ dataHashCode = 1606694497
+ isKeyFrame = true
+ presentationTimeUs = 54524
+sample:
+ trackIndex = 0
+ dataHashCode = 1747388653
+ isKeyFrame = true
+ presentationTimeUs = 57131
+sample:
+ trackIndex = 0
+ dataHashCode = -734560004
+ isKeyFrame = true
+ presentationTimeUs = 59579
+sample:
+ trackIndex = 0
+ dataHashCode = -975079040
+ isKeyFrame = true
+ presentationTimeUs = 62277
+sample:
+ trackIndex = 0
+ dataHashCode = -1403504710
+ isKeyFrame = true
+ presentationTimeUs = 65020
+sample:
+ trackIndex = 0
+ dataHashCode = 379512981
+ isKeyFrame = true
+ presentationTimeUs = 67627
+sample:
+ trackIndex = 0
+ dataHashCode = -997198863
+ isKeyFrame = true
+ presentationTimeUs = 70234
+sample:
+ trackIndex = 0
+ dataHashCode = 1394492825
+ isKeyFrame = true
+ presentationTimeUs = 72932
+sample:
+ trackIndex = 0
+ dataHashCode = -885232755
+ isKeyFrame = true
+ presentationTimeUs = 75471
+sample:
+ trackIndex = 0
+ dataHashCode = 260871367
+ isKeyFrame = true
+ presentationTimeUs = 78101
+sample:
+ trackIndex = 0
+ dataHashCode = -1505318960
+ isKeyFrame = true
+ presentationTimeUs = 80844
+sample:
+ trackIndex = 0
+ dataHashCode = -390625371
+ isKeyFrame = true
+ presentationTimeUs = 83474
+sample:
+ trackIndex = 0
+ dataHashCode = 1067950751
+ isKeyFrame = true
+ presentationTimeUs = 86149
+sample:
+ trackIndex = 0
+ dataHashCode = -1179436278
+ isKeyFrame = true
+ presentationTimeUs = 88734
+sample:
+ trackIndex = 0
+ dataHashCode = 1906607774
+ isKeyFrame = true
+ presentationTimeUs = 91387
+sample:
+ trackIndex = 0
+ dataHashCode = -800475828
+ isKeyFrame = true
+ presentationTimeUs = 94380
+sample:
+ trackIndex = 0
+ dataHashCode = 1718972977
+ isKeyFrame = true
+ presentationTimeUs = 97282
+sample:
+ trackIndex = 0
+ dataHashCode = -1120448741
+ isKeyFrame = true
+ presentationTimeUs = 99844
+sample:
+ trackIndex = 0
+ dataHashCode = -1718323210
+ isKeyFrame = true
+ presentationTimeUs = 102406
+sample:
+ trackIndex = 0
+ dataHashCode = -422416
+ isKeyFrame = true
+ presentationTimeUs = 105059
+sample:
+ trackIndex = 0
+ dataHashCode = 833757830
+ isKeyFrame = true
+ presentationTimeUs = 107644
+released = true
diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample_sef_slow_motion.mp4.dump b/testdata/src/test/assets/transformerdumps/mp4/sample_sef_slow_motion.mp4.dump
new file mode 100644
index 0000000000..5262f11ea1
--- /dev/null
+++ b/testdata/src/test/assets/transformerdumps/mp4/sample_sef_slow_motion.mp4.dump
@@ -0,0 +1,188 @@
+containerMimeType = video/mp4
+format 0:
+ sampleMimeType = audio/mp4a-latm
+ channelCount = 2
+ sampleRate = 12000
+format 1:
+ id = 2
+ sampleMimeType = video/avc
+ codecs = avc1.64000D
+ maxInputSize = 5476
+ width = 320
+ height = 240
+ frameRate = 29.523811
+ metadata = entries=[mdta: key=com.android.capture.fps, smta: captureFrameRate=240.0, svcTemporalLayerCount=4, SlowMotion: segments=[Segment: startTimeMs=88, endTimeMs=879, speedDivisor=2, Segment: startTimeMs=1255, endTimeMs=1970, speedDivisor=8]]
+ initializationData:
+ data = length 33, hash D3FB879D
+ data = length 10, hash 7A0D0F2B
+sample:
+ trackIndex = 1
+ dataHashCode = -549003117
+ isKeyFrame = true
+ presentationTimeUs = 0
+sample:
+ trackIndex = 1
+ dataHashCode = 593600631
+ isKeyFrame = false
+ presentationTimeUs = 14000
+sample:
+ trackIndex = 1
+ dataHashCode = -961321612
+ isKeyFrame = false
+ presentationTimeUs = 47333
+sample:
+ trackIndex = 1
+ dataHashCode = -386347143
+ isKeyFrame = false
+ presentationTimeUs = 80667
+sample:
+ trackIndex = 1
+ dataHashCode = -1289764147
+ isKeyFrame = false
+ presentationTimeUs = 114000
+sample:
+ trackIndex = 1
+ dataHashCode = 1337088875
+ isKeyFrame = false
+ presentationTimeUs = 147333
+sample:
+ trackIndex = 1
+ dataHashCode = -322406979
+ isKeyFrame = false
+ presentationTimeUs = 180667
+sample:
+ trackIndex = 1
+ dataHashCode = -1688033783
+ isKeyFrame = false
+ presentationTimeUs = 228042
+sample:
+ trackIndex = 1
+ dataHashCode = -700344608
+ isKeyFrame = false
+ presentationTimeUs = 244708
+sample:
+ trackIndex = 1
+ dataHashCode = -1441653629
+ isKeyFrame = false
+ presentationTimeUs = 334083
+sample:
+ trackIndex = 1
+ dataHashCode = 1201357091
+ isKeyFrame = false
+ presentationTimeUs = 267416
+sample:
+ trackIndex = 1
+ dataHashCode = -668484307
+ isKeyFrame = false
+ presentationTimeUs = 234083
+sample:
+ trackIndex = 1
+ dataHashCode = 653508165
+ isKeyFrame = false
+ presentationTimeUs = 300750
+sample:
+ trackIndex = 1
+ dataHashCode = -816848987
+ isKeyFrame = false
+ presentationTimeUs = 467416
+sample:
+ trackIndex = 1
+ dataHashCode = 1842436292
+ isKeyFrame = false
+ presentationTimeUs = 400750
+sample:
+ trackIndex = 1
+ dataHashCode = -559603233
+ isKeyFrame = false
+ presentationTimeUs = 367416
+sample:
+ trackIndex = 1
+ dataHashCode = -666437886
+ isKeyFrame = false
+ presentationTimeUs = 434083
+sample:
+ trackIndex = 1
+ dataHashCode = 182521759
+ isKeyFrame = false
+ presentationTimeUs = 600750
+sample:
+ trackIndex = 0
+ dataHashCode = -212376212
+ isKeyFrame = true
+ presentationTimeUs = 0
+sample:
+ trackIndex = 0
+ dataHashCode = -833872563
+ isKeyFrame = true
+ presentationTimeUs = 416
+sample:
+ trackIndex = 0
+ dataHashCode = -135901925
+ isKeyFrame = true
+ presentationTimeUs = 36499
+sample:
+ trackIndex = 0
+ dataHashCode = -2124187794
+ isKeyFrame = true
+ presentationTimeUs = 44415
+sample:
+ trackIndex = 0
+ dataHashCode = 1016665126
+ isKeyFrame = true
+ presentationTimeUs = 63081
+sample:
+ trackIndex = 1
+ dataHashCode = 2139021989
+ isKeyFrame = false
+ presentationTimeUs = 534083
+sample:
+ trackIndex = 1
+ dataHashCode = 2013165108
+ isKeyFrame = false
+ presentationTimeUs = 500750
+sample:
+ trackIndex = 1
+ dataHashCode = 405675195
+ isKeyFrame = false
+ presentationTimeUs = 567416
+sample:
+ trackIndex = 1
+ dataHashCode = -1893277090
+ isKeyFrame = false
+ presentationTimeUs = 734083
+sample:
+ trackIndex = 1
+ dataHashCode = -1554795381
+ isKeyFrame = false
+ presentationTimeUs = 667416
+sample:
+ trackIndex = 1
+ dataHashCode = 1197099206
+ isKeyFrame = false
+ presentationTimeUs = 634083
+sample:
+ trackIndex = 1
+ dataHashCode = -674808173
+ isKeyFrame = false
+ presentationTimeUs = 700750
+sample:
+ trackIndex = 1
+ dataHashCode = -775517313
+ isKeyFrame = false
+ presentationTimeUs = 867416
+sample:
+ trackIndex = 1
+ dataHashCode = -2045106113
+ isKeyFrame = false
+ presentationTimeUs = 800750
+sample:
+ trackIndex = 1
+ dataHashCode = 305167697
+ isKeyFrame = false
+ presentationTimeUs = 767416
+sample:
+ trackIndex = 1
+ dataHashCode = 554021920
+ isKeyFrame = false
+ presentationTimeUs = 834083
+released = true
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/DumpableFormat.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/DumpableFormat.java
new file mode 100644
index 0000000000..80c211914a
--- /dev/null
+++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/DumpableFormat.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2021 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.testutil;
+
+import androidx.annotation.Nullable;
+import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.util.Util;
+import com.google.common.base.Function;
+import org.checkerframework.checker.nullness.compatqual.NullableType;
+
+/** Wraps a {@link Format} to allow dumping it. */
+public final class DumpableFormat implements Dumper.Dumpable {
+ private final Format format;
+ public final int index;
+
+ private static final Format DEFAULT_FORMAT = new Format.Builder().build();
+
+ public DumpableFormat(Format format, int index) {
+ this.format = format;
+ this.index = index;
+ }
+
+ @Override
+ public void dump(Dumper dumper) {
+ dumper.startBlock("format " + index);
+ addIfNonDefault(dumper, "averageBitrate", format -> format.averageBitrate);
+ addIfNonDefault(dumper, "peakBitrate", format -> format.peakBitrate);
+ addIfNonDefault(dumper, "id", format -> format.id);
+ addIfNonDefault(dumper, "containerMimeType", format -> format.containerMimeType);
+ addIfNonDefault(dumper, "sampleMimeType", format -> format.sampleMimeType);
+ addIfNonDefault(dumper, "codecs", format -> format.codecs);
+ addIfNonDefault(dumper, "maxInputSize", format -> format.maxInputSize);
+ addIfNonDefault(dumper, "width", format -> format.width);
+ addIfNonDefault(dumper, "height", format -> format.height);
+ addIfNonDefault(dumper, "frameRate", format -> format.frameRate);
+ addIfNonDefault(dumper, "rotationDegrees", format -> format.rotationDegrees);
+ addIfNonDefault(dumper, "pixelWidthHeightRatio", format -> format.pixelWidthHeightRatio);
+ addIfNonDefault(dumper, "channelCount", format -> format.channelCount);
+ addIfNonDefault(dumper, "sampleRate", format -> format.sampleRate);
+ addIfNonDefault(dumper, "pcmEncoding", format -> format.pcmEncoding);
+ addIfNonDefault(dumper, "encoderDelay", format -> format.encoderDelay);
+ addIfNonDefault(dumper, "encoderPadding", format -> format.encoderPadding);
+ addIfNonDefault(dumper, "subsampleOffsetUs", format -> format.subsampleOffsetUs);
+ addIfNonDefault(dumper, "selectionFlags", format -> format.selectionFlags);
+ addIfNonDefault(dumper, "language", format -> format.language);
+ addIfNonDefault(dumper, "label", format -> format.label);
+ if (format.drmInitData != null) {
+ dumper.add("drmInitData", format.drmInitData.hashCode());
+ }
+ addIfNonDefault(dumper, "metadata", format -> format.metadata);
+ if (!format.initializationData.isEmpty()) {
+ dumper.startBlock("initializationData");
+ for (int i = 0; i < format.initializationData.size(); i++) {
+ dumper.add("data", format.initializationData.get(i));
+ }
+ dumper.endBlock();
+ }
+ dumper.endBlock();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DumpableFormat that = (DumpableFormat) o;
+ return index == that.index && format.equals(that.format);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = format.hashCode();
+ result = 31 * result + index;
+ return result;
+ }
+
+ private void addIfNonDefault(
+ Dumper dumper, String field, Function getFieldFunction) {
+ @Nullable Object thisValue = getFieldFunction.apply(format);
+ @Nullable Object defaultValue = getFieldFunction.apply(DEFAULT_FORMAT);
+ if (!Util.areEqual(thisValue, defaultValue)) {
+ dumper.add(field, thisValue);
+ }
+ }
+}
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java
index 4e636d993c..a5a88da03e 100644
--- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java
+++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTrackOutput.java
@@ -26,7 +26,6 @@ import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;
-import com.google.common.base.Function;
import com.google.common.primitives.Bytes;
import java.io.EOFException;
import java.io.IOException;
@@ -34,7 +33,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import org.checkerframework.checker.nullness.compatqual.NullableType;
/** A fake {@link TrackOutput}. */
public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
@@ -284,81 +282,4 @@ public final class FakeTrackOutput implements TrackOutput, Dumper.Dumpable {
}
}
- private static final class DumpableFormat implements Dumper.Dumpable {
- private final Format format;
- public final int index;
-
- private static final Format DEFAULT_FORMAT = new Format.Builder().build();
-
- public DumpableFormat(Format format, int index) {
- this.format = format;
- this.index = index;
- }
-
- @Override
- public void dump(Dumper dumper) {
- dumper.startBlock("format " + index);
- addIfNonDefault(dumper, "averageBitrate", format -> format.averageBitrate);
- addIfNonDefault(dumper, "peakBitrate", format -> format.peakBitrate);
- addIfNonDefault(dumper, "id", format -> format.id);
- addIfNonDefault(dumper, "containerMimeType", format -> format.containerMimeType);
- addIfNonDefault(dumper, "sampleMimeType", format -> format.sampleMimeType);
- addIfNonDefault(dumper, "codecs", format -> format.codecs);
- addIfNonDefault(dumper, "maxInputSize", format -> format.maxInputSize);
- addIfNonDefault(dumper, "width", format -> format.width);
- addIfNonDefault(dumper, "height", format -> format.height);
- addIfNonDefault(dumper, "frameRate", format -> format.frameRate);
- addIfNonDefault(dumper, "rotationDegrees", format -> format.rotationDegrees);
- addIfNonDefault(dumper, "pixelWidthHeightRatio", format -> format.pixelWidthHeightRatio);
- addIfNonDefault(dumper, "channelCount", format -> format.channelCount);
- addIfNonDefault(dumper, "sampleRate", format -> format.sampleRate);
- addIfNonDefault(dumper, "pcmEncoding", format -> format.pcmEncoding);
- addIfNonDefault(dumper, "encoderDelay", format -> format.encoderDelay);
- addIfNonDefault(dumper, "encoderPadding", format -> format.encoderPadding);
- addIfNonDefault(dumper, "subsampleOffsetUs", format -> format.subsampleOffsetUs);
- addIfNonDefault(dumper, "selectionFlags", format -> format.selectionFlags);
- addIfNonDefault(dumper, "language", format -> format.language);
- addIfNonDefault(dumper, "label", format -> format.label);
- if (format.drmInitData != null) {
- dumper.add("drmInitData", format.drmInitData.hashCode());
- }
- addIfNonDefault(dumper, "metadata", format -> format.metadata);
- if (!format.initializationData.isEmpty()) {
- dumper.startBlock("initializationData");
- for (int i = 0; i < format.initializationData.size(); i++) {
- dumper.add("data", format.initializationData.get(i));
- }
- dumper.endBlock();
- }
- dumper.endBlock();
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- DumpableFormat that = (DumpableFormat) o;
- return index == that.index && format.equals(that.format);
- }
-
- @Override
- public int hashCode() {
- int result = format.hashCode();
- result = 31 * result + index;
- return result;
- }
-
- private void addIfNonDefault(
- Dumper dumper, String field, Function getFieldFunction) {
- @Nullable Object thisValue = getFieldFunction.apply(format);
- @Nullable Object defaultValue = getFieldFunction.apply(DEFAULT_FORMAT);
- if (!Util.areEqual(thisValue, defaultValue)) {
- dumper.add(field, thisValue);
- }
- }
- }
}