From b96787d37453e0807189679b42906e7c0b048368 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Wed, 16 Feb 2022 17:41:00 +0000 Subject: [PATCH] Avoid attempting to mux out of order pre-API 25 Calling `MediaMuxer.writeSampleData` can block indefinitely on old API versions. It is better not to call this method to fail quickly with an exception rather than getting stuck. Based on on-device testing media muxer doesn't generally handle out of order samples before API 25. There are a small number of devices where this does succeed but it seems preferable to turn this off everywhere to keep the code simple and have consistent behavior. Once we switch to in-app muxing this limitation will no longer apply. #mse-bug-week PiperOrigin-RevId: 429070255 --- .../media3/transformer/FrameworkMuxer.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameworkMuxer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameworkMuxer.java index 1645a4f620..214d7b121f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameworkMuxer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameworkMuxer.java @@ -16,6 +16,7 @@ package androidx.media3.transformer; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Util.SDK_INT; import static androidx.media3.common.util.Util.castNonNull; @@ -24,6 +25,7 @@ import android.media.MediaCodec; import android.media.MediaFormat; import android.media.MediaMuxer; import android.os.ParcelFileDescriptor; +import android.util.SparseLongArray; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.media3.common.C; @@ -119,12 +121,14 @@ import java.nio.ByteBuffer; private final MediaMuxer mediaMuxer; private final MediaCodec.BufferInfo bufferInfo; + private final SparseLongArray trackIndexToLastPresentationTimeUs; private boolean isStarted; private FrameworkMuxer(MediaMuxer mediaMuxer) { this.mediaMuxer = mediaMuxer; bufferInfo = new MediaCodec.BufferInfo(); + trackIndexToLastPresentationTimeUs = new SparseLongArray(); } @Override @@ -172,7 +176,17 @@ import java.nio.ByteBuffer; int size = data.limit() - offset; int flags = isKeyFrame ? C.BUFFER_FLAG_KEY_FRAME : 0; bufferInfo.set(offset, size, presentationTimeUs, flags); + long lastSamplePresentationTimeUs = trackIndexToLastPresentationTimeUs.get(trackIndex); try { + // writeSampleData blocks on old API versions, so check here to avoid calling the method. + checkState( + Util.SDK_INT > 24 || presentationTimeUs >= lastSamplePresentationTimeUs, + "Samples not in presentation order (" + + presentationTimeUs + + " < " + + lastSamplePresentationTimeUs + + ") unsupported on this API version"); + trackIndexToLastPresentationTimeUs.put(trackIndex, presentationTimeUs); mediaMuxer.writeSampleData(trackIndex, data, bufferInfo); } catch (RuntimeException e) { throw new MuxerException(