Commit d5499ee3 by andrewlewis Committed by Oliver Woodman

Switch transformer tests to use dump files

Add an interface to muxers to allow tests to pass a dumpable muxer.

#minor-release

PiperOrigin-RevId: 354543388
parent e41d0428
/*
* 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);
}
}
}
/*
* 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.
*
* <p>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();
}
......@@ -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;
}
......@@ -263,11 +261,24 @@ public final class Transformer {
}
/**
* 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)
......
......@@ -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);
......
/*
* 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<Dumper.Dumpable> 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();
}
}
}
......@@ -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
......
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
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
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
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
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
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
/*
* 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<Format, @NullableType Object> getFieldFunction) {
@Nullable Object thisValue = getFieldFunction.apply(format);
@Nullable Object defaultValue = getFieldFunction.apply(DEFAULT_FORMAT);
if (!Util.areEqual(thisValue, defaultValue)) {
dumper.add(field, thisValue);
}
}
}
......@@ -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<Format, @NullableType Object> getFieldFunction) {
@Nullable Object thisValue = getFieldFunction.apply(format);
@Nullable Object defaultValue = getFieldFunction.apply(DEFAULT_FORMAT);
if (!Util.areEqual(thisValue, defaultValue)) {
dumper.add(field, thisValue);
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment