diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java index d257f8e23bb..7f7dcb25d3b 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/ConfigurationActivity.java @@ -61,7 +61,7 @@ public final class ConfigurationActivity extends AppCompatActivity { public static final String SHOULD_REMOVE_AUDIO = "should_remove_audio"; public static final String SHOULD_REMOVE_VIDEO = "should_remove_video"; public static final String SHOULD_FLATTEN_FOR_SLOW_MOTION = "should_flatten_for_slow_motion"; - public static final String FORCE_SILENT_AUDIO = "force_silent_audio"; + public static final String GENERATE_SILENT_AUDIO = "generate_silent_audio"; public static final String AUDIO_MIME_TYPE = "audio_mime_type"; public static final String VIDEO_MIME_TYPE = "video_mime_type"; public static final String RESOLUTION_HEIGHT = "resolution_height"; @@ -210,7 +210,7 @@ public final class ConfigurationActivity extends AppCompatActivity { private @MonotonicNonNull CheckBox removeAudioCheckbox; private @MonotonicNonNull CheckBox removeVideoCheckbox; private @MonotonicNonNull CheckBox flattenForSlowMotionCheckbox; - private @MonotonicNonNull CheckBox forceSilentAudioCheckbox; + private @MonotonicNonNull CheckBox generateSilentAudioCheckbox; private @MonotonicNonNull Spinner audioMimeSpinner; private @MonotonicNonNull Spinner videoMimeSpinner; private @MonotonicNonNull Spinner resolutionHeightSpinner; @@ -271,7 +271,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { flattenForSlowMotionCheckbox = findViewById(R.id.flatten_for_slow_motion_checkbox); - forceSilentAudioCheckbox = findViewById(R.id.force_silent_audio_checkbox); + generateSilentAudioCheckbox = findViewById(R.id.generate_silent_audio_checkbox); ArrayAdapter audioMimeAdapter = new ArrayAdapter<>(/* context= */ this, R.layout.spinner_item); @@ -382,7 +382,7 @@ protected void onNewIntent(Intent intent) { "removeAudioCheckbox", "removeVideoCheckbox", "flattenForSlowMotionCheckbox", - "forceSilentAudioCheckbox", + "generateSilentAudioCheckbox", "audioMimeSpinner", "videoMimeSpinner", "resolutionHeightSpinner", @@ -402,7 +402,7 @@ private void startTransformation(View view) { bundle.putBoolean(SHOULD_REMOVE_AUDIO, removeAudioCheckbox.isChecked()); bundle.putBoolean(SHOULD_REMOVE_VIDEO, removeVideoCheckbox.isChecked()); bundle.putBoolean(SHOULD_FLATTEN_FOR_SLOW_MOTION, flattenForSlowMotionCheckbox.isChecked()); - bundle.putBoolean(FORCE_SILENT_AUDIO, forceSilentAudioCheckbox.isChecked()); + bundle.putBoolean(GENERATE_SILENT_AUDIO, generateSilentAudioCheckbox.isChecked()); String selectedAudioMimeType = String.valueOf(audioMimeSpinner.getSelectedItem()); if (!SAME_AS_INPUT_OPTION.equals(selectedAudioMimeType)) { bundle.putString(AUDIO_MIME_TYPE, selectedAudioMimeType); @@ -738,7 +738,7 @@ private void controlTextOverlaySettings() { @RequiresNonNull({ "removeVideoCheckbox", - "forceSilentAudioCheckbox", + "generateSilentAudioCheckbox", "audioMimeSpinner", "videoMimeSpinner", "resolutionHeightSpinner", @@ -760,7 +760,7 @@ private void onRemoveAudio(View view) { @RequiresNonNull({ "removeAudioCheckbox", - "forceSilentAudioCheckbox", + "generateSilentAudioCheckbox", "audioMimeSpinner", "videoMimeSpinner", "resolutionHeightSpinner", @@ -781,7 +781,7 @@ private void onRemoveVideo(View view) { } @RequiresNonNull({ - "forceSilentAudioCheckbox", + "generateSilentAudioCheckbox", "audioMimeSpinner", "videoMimeSpinner", "resolutionHeightSpinner", @@ -793,7 +793,7 @@ private void onRemoveVideo(View view) { "selectVideoEffectsButton" }) private void enableTrackSpecificOptions(boolean isAudioEnabled, boolean isVideoEnabled) { - forceSilentAudioCheckbox.setEnabled(isVideoEnabled); + generateSilentAudioCheckbox.setEnabled(isVideoEnabled); audioMimeSpinner.setEnabled(isAudioEnabled); videoMimeSpinner.setEnabled(isVideoEnabled); resolutionHeightSpinner.setEnabled(isVideoEnabled); diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java index ad3f30e178f..170dbfc67fa 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java @@ -309,6 +309,8 @@ private Transformer createTransformer(@Nullable Bundle bundle, String filePath) transformerBuilder .setRemoveAudio(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_AUDIO)) .setRemoveVideo(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_VIDEO)) + .experimentalSetGenerateSilentAudio( + bundle.getBoolean(ConfigurationActivity.GENERATE_SILENT_AUDIO)) .setEncoderFactory( new DefaultEncoderFactory.Builder(this.getApplicationContext()) .setEnableFallback(bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK)) @@ -322,9 +324,6 @@ private Transformer createTransformer(@Nullable Bundle bundle, String filePath) if (bundle.getBoolean(ConfigurationActivity.ENABLE_DEBUG_PREVIEW)) { transformerBuilder.setDebugViewProvider(new DemoDebugViewProvider()); } - - transformerBuilder.experimentalSetForceSilentAudio( - bundle.getBoolean(ConfigurationActivity.FORCE_SILENT_AUDIO)); } return transformerBuilder diff --git a/demos/transformer/src/main/res/layout/configuration_activity.xml b/demos/transformer/src/main/res/layout/configuration_activity.xml index 09aa1287d1a..8223dd4ae8c 100644 --- a/demos/transformer/src/main/res/layout/configuration_activity.xml +++ b/demos/transformer/src/main/res/layout/configuration_activity.xml @@ -116,9 +116,9 @@ android:layout_weight="1"> + android:text="@string/generate_silent_audio" /> Permission Denied Hide input video Show input video - Force silent audio + Generate silent audio Alpha Uri Specify bitmap overlay settings diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java index 163a7538584..338e088d060 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java @@ -64,15 +64,15 @@ public AudioSamplePipeline( long streamOffsetUs, TransformationRequest transformationRequest, ImmutableList audioProcessors, - long forceSilentAudioDurationUs, + long generateSilentAudioDurationUs, Codec.EncoderFactory encoderFactory, MuxerWrapper muxerWrapper, FallbackListener fallbackListener) throws TransformationException { super(inputFormat, streamStartPositionUs, muxerWrapper); - if (forceSilentAudioDurationUs != C.TIME_UNSET) { - silentAudioGenerator = new SilentAudioGenerator(inputFormat, forceSilentAudioDurationUs); + if (generateSilentAudioDurationUs != C.TIME_UNSET) { + silentAudioGenerator = new SilentAudioGenerator(inputFormat, generateSilentAudioDurationUs); } else { silentAudioGenerator = null; } 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 0fdf7058706..eb175e6c816 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 @@ -86,7 +86,7 @@ public static final class Builder { private ImmutableList videoEffects; private boolean removeAudio; private boolean removeVideo; - private boolean forceSilentAudio; + private boolean generateSilentAudio; private ListenerSet listeners; @Nullable private AssetLoader.Factory assetLoaderFactory; private FrameProcessor.Factory frameProcessorFactory; @@ -123,7 +123,7 @@ private Builder(Transformer transformer) { this.videoEffects = transformer.videoEffects; this.removeAudio = transformer.removeAudio; this.removeVideo = transformer.removeVideo; - this.forceSilentAudio = transformer.forceSilentAudio; + this.generateSilentAudio = transformer.generateSilentAudio; this.listeners = transformer.listeners; this.assetLoaderFactory = transformer.assetLoaderFactory; this.frameProcessorFactory = transformer.frameProcessorFactory; @@ -398,29 +398,32 @@ public Builder setDebugViewProvider(DebugViewProvider debugViewProvider) { } /** - * Sets whether to force silent audio for the output file, ignoring any existing audio. + * Sets whether to generate silent audio for the output file, if there is no audio available. * *

This method is experimental and may be removed or changed without warning. * + *

To replace existing audio with silence, call {@link #setRemoveAudio(boolean)} as well. + * *

Audio properties/format: * *

    *
  • Duration will match duration of the input media. *
  • Sample mime type will match {@link TransformationRequest#audioMimeType}, or {@link * MimeTypes#AUDIO_AAC} if {@code null}. - *
  • Sample rate will be 44100hz. This can be modified by passing a {@link + *
  • Sample rate will be {@code 44100} hz. This can be modified by passing a {@link * SonicAudioProcessor} to {@link #setAudioProcessors(List)}, using {@link * SonicAudioProcessor#setOutputSampleRateHz(int)}. - *
  • Channel count will be 2. This can be modified by implementing a custom {@link + *
  • Channel count will be {@code 2}. This can be modified by implementing a custom {@link * AudioProcessor} and passing it to {@link #setAudioProcessors(List)}. *
* - * @param forceSilentAudio Whether to output silent audio for the output file. + * @param generateSilentAudio Whether to generate silent audio for the output file if there is + * no audio track. * @return This builder. */ @CanIgnoreReturnValue - public Builder experimentalSetForceSilentAudio(boolean forceSilentAudio) { - this.forceSilentAudio = forceSilentAudio; + public Builder experimentalSetGenerateSilentAudio(boolean generateSilentAudio) { + this.generateSilentAudio = generateSilentAudio; return this; } @@ -457,7 +460,7 @@ public Transformer build() { videoEffects, removeAudio, removeVideo, - forceSilentAudio, + generateSilentAudio, listeners, assetLoaderFactory, frameProcessorFactory, @@ -577,7 +580,7 @@ default void onFallbackApplied( private final ImmutableList videoEffects; private final boolean removeAudio; private final boolean removeVideo; - private final boolean forceSilentAudio; + private final boolean generateSilentAudio; private final ListenerSet listeners; private final AssetLoader.Factory assetLoaderFactory; private final FrameProcessor.Factory frameProcessorFactory; @@ -596,7 +599,7 @@ private Transformer( ImmutableList videoEffects, boolean removeAudio, boolean removeVideo, - boolean forceSilentAudio, + boolean generateSilentAudio, ListenerSet listeners, AssetLoader.Factory assetLoaderFactory, FrameProcessor.Factory frameProcessorFactory, @@ -605,10 +608,6 @@ private Transformer( Looper looper, DebugViewProvider debugViewProvider, Clock clock) { - if (forceSilentAudio) { - removeAudio = true; - } - checkState(!removeVideo || !forceSilentAudio, "Silent only audio track needs a video track."); checkState(!removeAudio || !removeVideo, "Audio and video cannot both be removed."); this.context = context; this.transformationRequest = transformationRequest; @@ -616,7 +615,7 @@ private Transformer( this.videoEffects = videoEffects; this.removeAudio = removeAudio; this.removeVideo = removeVideo; - this.forceSilentAudio = forceSilentAudio; + this.generateSilentAudio = generateSilentAudio; this.listeners = listeners; this.assetLoaderFactory = assetLoaderFactory; this.frameProcessorFactory = frameProcessorFactory; @@ -759,7 +758,7 @@ private void startTransformationInternal( videoEffects, removeAudio, removeVideo, - forceSilentAudio, + generateSilentAudio, assetLoaderFactory, frameProcessorFactory, encoderFactory, diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java index 76f0d471329..fc9e81a14aa 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerInternal.java @@ -93,7 +93,6 @@ public interface Listener { private final TransformationRequest transformationRequest; private final ImmutableList audioProcessors; private final ImmutableList videoEffects; - private final boolean forceSilentAudio; private final FrameProcessor.Factory frameProcessorFactory; private final CapturingEncoderFactory encoderFactory; private final Listener listener; @@ -108,6 +107,7 @@ public interface Listener { private final ConditionVariable transformerConditionVariable; private final TransformationResult.Builder transformationResultBuilder; + private boolean generateSilentAudio; private boolean isDrainingPipelines; private @Transformer.ProgressState int progressState; private @MonotonicNonNull RuntimeException cancelException; @@ -124,7 +124,7 @@ public TransformerInternal( ImmutableList videoEffects, boolean removeAudio, boolean removeVideo, - boolean forceSilentAudio, + boolean generateSilentAudio, AssetLoader.Factory assetLoaderFactory, FrameProcessor.Factory frameProcessorFactory, Codec.EncoderFactory encoderFactory, @@ -138,7 +138,7 @@ public TransformerInternal( this.transformationRequest = transformationRequest; this.audioProcessors = audioProcessors; this.videoEffects = videoEffects; - this.forceSilentAudio = forceSilentAudio; + this.generateSilentAudio = generateSilentAudio; this.frameProcessorFactory = frameProcessorFactory; this.encoderFactory = new CapturingEncoderFactory(encoderFactory); this.listener = listener; @@ -373,9 +373,6 @@ public void onTrackCount(int trackCount) { return; } this.trackCount.set(trackCount); - if (forceSilentAudio) { - this.trackCount.incrementAndGet(); - } } @Override @@ -386,6 +383,14 @@ public SampleConsumer onTrackAdded( long streamOffsetUs) throws TransformationException { if (!trackAdded) { + if (generateSilentAudio) { + if (this.trackCount.get() == 1 && MimeTypes.isVideo(format.sampleMimeType)) { + this.trackCount.incrementAndGet(); + } else { + generateSilentAudio = false; + } + } + // Call setTrackCount() methods here so that they are called from the same thread as the // MuxerWrapper and FallbackListener methods called when building the sample pipelines. muxerWrapper.setTrackCount(trackCount.get()); @@ -397,7 +402,7 @@ public SampleConsumer onTrackAdded( getSamplePipeline(format, supportedOutputTypes, streamStartPositionUs, streamOffsetUs); internalHandler.obtainMessage(MSG_REGISTER_SAMPLE_PIPELINE, samplePipeline).sendToTarget(); - if (forceSilentAudio) { + if (generateSilentAudio) { Format silentAudioFormat = new Format.Builder() .setSampleMimeType(MimeTypes.AUDIO_AAC) @@ -482,7 +487,7 @@ private SamplePipeline getSamplePipeline( streamOffsetUs, transformationRequest, audioProcessors, - forceSilentAudio ? durationUs : C.TIME_UNSET, + generateSilentAudio ? durationUs : C.TIME_UNSET, encoderFactory, muxerWrapper, fallbackListener); @@ -528,7 +533,7 @@ private boolean shouldTranscodeAudio(Format inputFormat) { if (!audioProcessors.isEmpty()) { return true; } - if (forceSilentAudio) { + if (generateSilentAudio) { return true; } diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index c0c07f04e54..ef3c0edb120 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -271,10 +271,40 @@ public void startTransformation_removeVideo_completesSuccessfully() throws Excep } @Test - public void startTransformation_silentAudio_completesSuccessfully() throws Exception { + public void startTransformation_silentAudioOnAudioOnly_isIgnored() throws Exception { Transformer transformer = createTransformerBuilder(/* enableFallback= */ false) - .experimentalSetForceSilentAudio(true) + .experimentalSetGenerateSilentAudio(true) + .build(); + MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_ENCODER); + + transformer.startTransformation(mediaItem, outputPath); + TransformerTestRunner.runLooper(transformer); + + DumpFileAsserts.assertOutput( + context, testMuxer, getDumpFileName(FILE_AUDIO_UNSUPPORTED_BY_ENCODER)); + } + + @Test + public void startTransformation_silentAudioOnAudioVideo_isIgnored() throws Exception { + Transformer transformer = + createTransformerBuilder(/* enableFallback= */ false) + .experimentalSetGenerateSilentAudio(true) + .build(); + MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); + + transformer.startTransformation(mediaItem, outputPath); + TransformerTestRunner.runLooper(transformer); + + DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO)); + } + + @Test + public void startTransformation_silentAudioRemoveAudio_completesSuccessfully() throws Exception { + Transformer transformer = + createTransformerBuilder(/* enableFallback= */ false) + .experimentalSetGenerateSilentAudio(true) + .setRemoveAudio(true) .build(); MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); @@ -285,6 +315,36 @@ public void startTransformation_silentAudio_completesSuccessfully() throws Excep context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".silentaudio")); } + @Test + public void startTransformation_silentAudioRemoveVideo_isIgnored() throws Exception { + Transformer transformer = + createTransformerBuilder(/* enableFallback= */ false) + .experimentalSetGenerateSilentAudio(true) + .setRemoveVideo(true) + .build(); + MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); + + transformer.startTransformation(mediaItem, outputPath); + TransformerTestRunner.runLooper(transformer); + DumpFileAsserts.assertOutput( + context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".novideo")); + } + + @Test + public void startTransformation_silentAudioOnVideoOnly_completesSuccessfully() throws Exception { + Transformer transformer = + createTransformerBuilder(/* enableFallback= */ false) + .experimentalSetGenerateSilentAudio(true) + .build(); + MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_VIDEO_ONLY); + + transformer.startTransformation(mediaItem, outputPath); + TransformerTestRunner.runLooper(transformer); + + DumpFileAsserts.assertOutput( + context, testMuxer, getDumpFileName(FILE_VIDEO_ONLY + ".silentaudio")); + } + @Test public void startTransformation_adjustSampleRate_completesSuccessfully() throws Exception { SonicAudioProcessor sonicAudioProcessor = new SonicAudioProcessor(); diff --git a/testdata/src/test/assets/transformerdumps/mp4/sample_18byte_nclx_colr.mp4.silentaudio.dump b/testdata/src/test/assets/transformerdumps/mp4/sample_18byte_nclx_colr.mp4.silentaudio.dump new file mode 100644 index 00000000000..c02482575d1 --- /dev/null +++ b/testdata/src/test/assets/transformerdumps/mp4/sample_18byte_nclx_colr.mp4.silentaudio.dump @@ -0,0 +1,466 @@ +format 0: + id = 1 + sampleMimeType = video/avc + codecs = avc1.64001F + maxInputSize = 36722 + width = 1080 + height = 720 + frameRate = 29.970028 + colorInfo: + colorSpace = 1 + colorRange = 2 + colorTransfer = 3 + hdrStaticInfo = length 0, hash 0 + initializationData: + data = length 29, hash 4746B5D9 + data = length 10, hash 7A0D0F2B +format 1: + sampleMimeType = audio/mp4a-latm + channelCount = 2 + sampleRate = 44100 + pcmEncoding = 2 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 23220 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 46440 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 69660 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 92880 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 116100 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 139320 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 162540 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 185760 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 208980 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 232200 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 255420 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 278640 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 301860 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 325080 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 348300 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 371520 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 394740 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 417960 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 441180 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 464400 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 487620 +sample: + trackIndex = 0 + dataHashCode = -770308242 + size = 36692 + isKeyFrame = true + presentationTimeUs = 0 +sample: + trackIndex = 0 + dataHashCode = -732087136 + size = 5312 + isKeyFrame = false + presentationTimeUs = 66733 +sample: + trackIndex = 0 + dataHashCode = 468156717 + size = 599 + isKeyFrame = false + presentationTimeUs = 33366 +sample: + trackIndex = 0 + dataHashCode = 1150349584 + size = 7735 + isKeyFrame = false + presentationTimeUs = 200200 +sample: + trackIndex = 0 + dataHashCode = 1443582006 + size = 987 + isKeyFrame = false + presentationTimeUs = 133466 +sample: + trackIndex = 0 + dataHashCode = -310585145 + size = 673 + isKeyFrame = false + presentationTimeUs = 100100 +sample: + trackIndex = 0 + dataHashCode = 807460688 + size = 523 + isKeyFrame = false + presentationTimeUs = 166833 +sample: + trackIndex = 0 + dataHashCode = 1936487090 + size = 6061 + isKeyFrame = false + presentationTimeUs = 333666 +sample: + trackIndex = 0 + dataHashCode = -32297181 + size = 992 + isKeyFrame = false + presentationTimeUs = 266933 +sample: + trackIndex = 0 + dataHashCode = 1529616406 + size = 623 + isKeyFrame = false + presentationTimeUs = 233566 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 510840 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 534059 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 557279 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 580499 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 603719 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 626939 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 650159 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 673379 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 696599 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 719819 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 743039 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 766259 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 789479 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 812699 +sample: + trackIndex = 0 + dataHashCode = 1949198785 + size = 421 + isKeyFrame = false + presentationTimeUs = 300300 +sample: + trackIndex = 0 + dataHashCode = -147880287 + size = 4899 + isKeyFrame = false + presentationTimeUs = 433766 +sample: + trackIndex = 0 + dataHashCode = 1369083472 + size = 568 + isKeyFrame = false + presentationTimeUs = 400400 +sample: + trackIndex = 0 + dataHashCode = 965782073 + size = 620 + isKeyFrame = false + presentationTimeUs = 367033 +sample: + trackIndex = 0 + dataHashCode = -261176150 + size = 5450 + isKeyFrame = false + presentationTimeUs = 567233 +sample: + trackIndex = 0 + dataHashCode = -1830836678 + size = 1051 + isKeyFrame = false + presentationTimeUs = 500500 +sample: + trackIndex = 0 + dataHashCode = 1767407540 + size = 874 + isKeyFrame = false + presentationTimeUs = 467133 +sample: + trackIndex = 0 + dataHashCode = 918440283 + size = 781 + isKeyFrame = false + presentationTimeUs = 533866 +sample: + trackIndex = 0 + dataHashCode = -1408463661 + size = 4725 + isKeyFrame = false + presentationTimeUs = 700700 +sample: + trackIndex = 0 + dataHashCode = 1569455924 + size = 1022 + isKeyFrame = false + presentationTimeUs = 633966 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 835919 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 859139 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 882359 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 905579 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 928799 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 952019 +sample: + trackIndex = 1 + dataHashCode = 1742602241 + size = 4096 + isKeyFrame = true + presentationTimeUs = 975239 +sample: + trackIndex = 1 + dataHashCode = 226248705 + size = 448 + isKeyFrame = true + presentationTimeUs = 998459 +sample: + trackIndex = 0 + dataHashCode = -1723778407 + size = 790 + isKeyFrame = false + presentationTimeUs = 600600 +sample: + trackIndex = 0 + dataHashCode = 1578275472 + size = 610 + isKeyFrame = false + presentationTimeUs = 667333 +sample: + trackIndex = 0 + dataHashCode = 1989768395 + size = 2751 + isKeyFrame = false + presentationTimeUs = 834166 +sample: + trackIndex = 0 + dataHashCode = -1215674502 + size = 745 + isKeyFrame = false + presentationTimeUs = 767433 +sample: + trackIndex = 0 + dataHashCode = -814473606 + size = 621 + isKeyFrame = false + presentationTimeUs = 734066 +sample: + trackIndex = 0 + dataHashCode = 498370894 + size = 505 + isKeyFrame = false + presentationTimeUs = 800800 +sample: + trackIndex = 0 + dataHashCode = -1051506468 + size = 1268 + isKeyFrame = false + presentationTimeUs = 967633 +sample: + trackIndex = 0 + dataHashCode = -1025604144 + size = 880 + isKeyFrame = false + presentationTimeUs = 900900 +sample: + trackIndex = 0 + dataHashCode = -913586520 + size = 530 + isKeyFrame = false + presentationTimeUs = 867533 +sample: + trackIndex = 0 + dataHashCode = 1340459242 + size = 568 + isKeyFrame = false + presentationTimeUs = 934266 +released = true