mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Pass BufferInfo in writeSampleData() method in Transformer/Muxer.java
This is to eventually replace Transformer/Muxer.java with Muxer/Muxer.java PiperOrigin-RevId: 627043808
This commit is contained in:
parent
86ef571644
commit
03a041c452
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.muxer;
|
package androidx.media3.muxer;
|
||||||
|
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec.BufferInfo;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.Metadata;
|
import androidx.media3.common.Metadata;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
@ -32,8 +32,7 @@ public interface Muxer {
|
|||||||
TrackToken addTrack(Format format);
|
TrackToken addTrack(Format format);
|
||||||
|
|
||||||
/** Writes encoded sample data. */
|
/** Writes encoded sample data. */
|
||||||
void writeSampleData(
|
void writeSampleData(TrackToken trackToken, ByteBuffer byteBuffer, BufferInfo bufferInfo)
|
||||||
TrackToken trackToken, ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo)
|
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
/** Adds {@linkplain Metadata.Entry metadata} about the output file. */
|
/** Adds {@linkplain Metadata.Entry metadata} about the output file. */
|
||||||
|
@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.media.MediaCodec.BufferInfo;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Effect;
|
import androidx.media3.common.Effect;
|
||||||
@ -449,18 +450,17 @@ public class TransformerPauseResumeTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSampleData(
|
public void writeSampleData(TrackToken trackToken, ByteBuffer data, BufferInfo bufferInfo)
|
||||||
TrackToken trackToken, ByteBuffer data, long presentationTimeUs, @C.BufferFlags int flags)
|
|
||||||
throws MuxerException {
|
throws MuxerException {
|
||||||
if (trackToken == videoTrackToken
|
if (trackToken == videoTrackToken
|
||||||
&& presentationTimeUs >= DEFAULT_PRESENTATION_TIME_US_TO_BLOCK_FRAME) {
|
&& bufferInfo.presentationTimeUs >= DEFAULT_PRESENTATION_TIME_US_TO_BLOCK_FRAME) {
|
||||||
if (!notifiedListener) {
|
if (!notifiedListener) {
|
||||||
listener.onFrameBlocked();
|
listener.onFrameBlocked();
|
||||||
notifiedListener = true;
|
notifiedListener = true;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wrappedMuxer.writeSampleData(trackToken, data, presentationTimeUs, flags);
|
wrappedMuxer.writeSampleData(trackToken, data, bufferInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.transformer;
|
package androidx.media3.transformer;
|
||||||
|
|
||||||
|
import android.media.MediaCodec.BufferInfo;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.Metadata;
|
import androidx.media3.common.Metadata;
|
||||||
@ -70,10 +71,9 @@ public final class DefaultMuxer implements Muxer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSampleData(
|
public void writeSampleData(TrackToken trackToken, ByteBuffer data, BufferInfo bufferInfo)
|
||||||
TrackToken trackToken, ByteBuffer data, long presentationTimeUs, @C.BufferFlags int flags)
|
|
||||||
throws MuxerException {
|
throws MuxerException {
|
||||||
muxer.writeSampleData(trackToken, data, presentationTimeUs, flags);
|
muxer.writeSampleData(trackToken, data, bufferInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,7 +21,7 @@ import static androidx.media3.common.util.Util.SDK_INT;
|
|||||||
import static androidx.media3.common.util.Util.castNonNull;
|
import static androidx.media3.common.util.Util.castNonNull;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec.BufferInfo;
|
||||||
import android.media.MediaFormat;
|
import android.media.MediaFormat;
|
||||||
import android.media.MediaMuxer;
|
import android.media.MediaMuxer;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@ -80,7 +80,6 @@ import java.util.Map;
|
|||||||
|
|
||||||
private final MediaMuxer mediaMuxer;
|
private final MediaMuxer mediaMuxer;
|
||||||
private final long videoDurationUs;
|
private final long videoDurationUs;
|
||||||
private final MediaCodec.BufferInfo bufferInfo;
|
|
||||||
private final Map<TrackToken, Long> trackTokenToLastPresentationTimeUs;
|
private final Map<TrackToken, Long> trackTokenToLastPresentationTimeUs;
|
||||||
private final Map<TrackToken, Long> trackTokenToPresentationTimeOffsetUs;
|
private final Map<TrackToken, Long> trackTokenToPresentationTimeOffsetUs;
|
||||||
|
|
||||||
@ -92,7 +91,6 @@ import java.util.Map;
|
|||||||
private FrameworkMuxer(MediaMuxer mediaMuxer, long videoDurationMs) {
|
private FrameworkMuxer(MediaMuxer mediaMuxer, long videoDurationMs) {
|
||||||
this.mediaMuxer = mediaMuxer;
|
this.mediaMuxer = mediaMuxer;
|
||||||
this.videoDurationUs = Util.msToUs(videoDurationMs);
|
this.videoDurationUs = Util.msToUs(videoDurationMs);
|
||||||
bufferInfo = new MediaCodec.BufferInfo();
|
|
||||||
trackTokenToLastPresentationTimeUs = new HashMap<>();
|
trackTokenToLastPresentationTimeUs = new HashMap<>();
|
||||||
trackTokenToPresentationTimeOffsetUs = new HashMap<>();
|
trackTokenToPresentationTimeOffsetUs = new HashMap<>();
|
||||||
}
|
}
|
||||||
@ -133,10 +131,9 @@ import java.util.Map;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSampleData(
|
public void writeSampleData(TrackToken trackToken, ByteBuffer data, BufferInfo bufferInfo)
|
||||||
TrackToken trackToken, ByteBuffer data, long presentationTimeUs, @C.BufferFlags int flags)
|
|
||||||
throws MuxerException {
|
throws MuxerException {
|
||||||
|
long presentationTimeUs = bufferInfo.presentationTimeUs;
|
||||||
if (videoDurationUs != C.TIME_UNSET
|
if (videoDurationUs != C.TIME_UNSET
|
||||||
&& trackToken == videoTrackToken
|
&& trackToken == videoTrackToken
|
||||||
&& presentationTimeUs > videoDurationUs) {
|
&& presentationTimeUs > videoDurationUs) {
|
||||||
@ -149,14 +146,10 @@ import java.util.Map;
|
|||||||
startMuxer();
|
startMuxer();
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = data.position();
|
|
||||||
int size = data.limit() - offset;
|
|
||||||
|
|
||||||
long presentationTimeOffsetUs =
|
long presentationTimeOffsetUs =
|
||||||
trackTokenToPresentationTimeOffsetUs.getOrDefault(trackToken, 0L);
|
trackTokenToPresentationTimeOffsetUs.getOrDefault(trackToken, 0L);
|
||||||
presentationTimeUs += presentationTimeOffsetUs;
|
presentationTimeUs += presentationTimeOffsetUs;
|
||||||
|
|
||||||
bufferInfo.set(offset, size, presentationTimeUs, TransformerUtil.getMediaCodecFlags(flags));
|
|
||||||
long lastSamplePresentationTimeUs =
|
long lastSamplePresentationTimeUs =
|
||||||
trackTokenToLastPresentationTimeUs.getOrDefault(trackToken, 0L);
|
trackTokenToLastPresentationTimeUs.getOrDefault(trackToken, 0L);
|
||||||
// writeSampleData blocks on old API versions, so check here to avoid calling the method.
|
// writeSampleData blocks on old API versions, so check here to avoid calling the method.
|
||||||
@ -176,13 +169,17 @@ import java.util.Map;
|
|||||||
+ " < "
|
+ " < "
|
||||||
+ lastSamplePresentationTimeUs
|
+ lastSamplePresentationTimeUs
|
||||||
+ ") unsupported when using negative PTS workaround");
|
+ ") unsupported when using negative PTS workaround");
|
||||||
|
bufferInfo.set(bufferInfo.offset, bufferInfo.size, presentationTimeUs, bufferInfo.flags);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
checkState(trackToken instanceof TrackTokenImpl);
|
checkState(trackToken instanceof TrackTokenImpl);
|
||||||
mediaMuxer.writeSampleData(((TrackTokenImpl) trackToken).trackIndex, data, bufferInfo);
|
mediaMuxer.writeSampleData(((TrackTokenImpl) trackToken).trackIndex, data, bufferInfo);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw new MuxerException(
|
throw new MuxerException(
|
||||||
"Failed to write sample for presentationTimeUs=" + presentationTimeUs + ", size=" + size,
|
"Failed to write sample for presentationTimeUs="
|
||||||
|
+ presentationTimeUs
|
||||||
|
+ ", size="
|
||||||
|
+ bufferInfo.size,
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,11 +205,13 @@ import java.util.Map;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (videoDurationUs != C.TIME_UNSET && videoTrackToken != null) {
|
if (videoDurationUs != C.TIME_UNSET && videoTrackToken != null) {
|
||||||
writeSampleData(
|
BufferInfo bufferInfo = new BufferInfo();
|
||||||
videoTrackToken,
|
bufferInfo.set(
|
||||||
ByteBuffer.allocateDirect(0),
|
/* newOffset= */ 0,
|
||||||
|
/* newSize= */ 0,
|
||||||
videoDurationUs,
|
videoDurationUs,
|
||||||
C.BUFFER_FLAG_END_OF_STREAM);
|
TransformerUtil.getMediaCodecFlags(C.BUFFER_FLAG_END_OF_STREAM));
|
||||||
|
writeSampleData(checkNotNull(videoTrackToken), ByteBuffer.allocateDirect(0), bufferInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
isStarted = false;
|
isStarted = false;
|
||||||
|
@ -159,14 +159,12 @@ public final class InAppMuxer implements Muxer {
|
|||||||
|
|
||||||
private final androidx.media3.muxer.Muxer muxer;
|
private final androidx.media3.muxer.Muxer muxer;
|
||||||
private final @Nullable MetadataProvider metadataProvider;
|
private final @Nullable MetadataProvider metadataProvider;
|
||||||
private final BufferInfo bufferInfo;
|
|
||||||
private final Set<Metadata.Entry> metadataEntries;
|
private final Set<Metadata.Entry> metadataEntries;
|
||||||
|
|
||||||
private InAppMuxer(
|
private InAppMuxer(
|
||||||
androidx.media3.muxer.Muxer muxer, @Nullable MetadataProvider metadataProvider) {
|
androidx.media3.muxer.Muxer muxer, @Nullable MetadataProvider metadataProvider) {
|
||||||
this.muxer = muxer;
|
this.muxer = muxer;
|
||||||
this.metadataProvider = metadataProvider;
|
this.metadataProvider = metadataProvider;
|
||||||
bufferInfo = new BufferInfo();
|
|
||||||
metadataEntries = new LinkedHashSet<>();
|
metadataEntries = new LinkedHashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,19 +178,17 @@ public final class InAppMuxer implements Muxer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSampleData(
|
public void writeSampleData(TrackToken trackToken, ByteBuffer data, BufferInfo bufferInfo)
|
||||||
TrackToken trackToken, ByteBuffer data, long presentationTimeUs, @C.BufferFlags int flags)
|
|
||||||
throws MuxerException {
|
throws MuxerException {
|
||||||
|
|
||||||
int size = data.remaining();
|
|
||||||
bufferInfo.set(
|
|
||||||
data.position(), size, presentationTimeUs, TransformerUtil.getMediaCodecFlags(flags));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
muxer.writeSampleData(trackToken, data, bufferInfo);
|
muxer.writeSampleData(trackToken, data, bufferInfo);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new MuxerException(
|
throw new MuxerException(
|
||||||
"Failed to write sample for presentationTimeUs=" + presentationTimeUs + ", size=" + size,
|
"Failed to write sample for presentationTimeUs="
|
||||||
|
+ bufferInfo.presentationTimeUs
|
||||||
|
+ ", size="
|
||||||
|
+ bufferInfo.size,
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.transformer;
|
package androidx.media3.transformer;
|
||||||
|
|
||||||
|
import android.media.MediaCodec.BufferInfo;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.Metadata;
|
import androidx.media3.common.Metadata;
|
||||||
@ -84,13 +85,10 @@ public interface Muxer {
|
|||||||
* @param trackToken The {@link TrackToken} of the track, previously returned by {@link
|
* @param trackToken The {@link TrackToken} of the track, previously returned by {@link
|
||||||
* #addTrack(Format)}.
|
* #addTrack(Format)}.
|
||||||
* @param data A buffer containing the sample data to write to the container.
|
* @param data A buffer containing the sample data to write to the container.
|
||||||
* @param presentationTimeUs The presentation time of the sample in microseconds.
|
* @param bufferInfo The {@link BufferInfo} of the sample.
|
||||||
* @param flags The {@link C.BufferFlags} associated with the data. Only {@link
|
|
||||||
* C#BUFFER_FLAG_KEY_FRAME} and {@link C#BUFFER_FLAG_END_OF_STREAM} are supported.
|
|
||||||
* @throws MuxerException If the muxer fails to write the sample.
|
* @throws MuxerException If the muxer fails to write the sample.
|
||||||
*/
|
*/
|
||||||
void writeSampleData(
|
void writeSampleData(TrackToken trackToken, ByteBuffer data, BufferInfo bufferInfo)
|
||||||
TrackToken trackToken, ByteBuffer data, long presentationTimeUs, @C.BufferFlags int flags)
|
|
||||||
throws MuxerException;
|
throws MuxerException;
|
||||||
|
|
||||||
/** Adds {@linkplain Metadata.Entry metadata} about the output file. */
|
/** Adds {@linkplain Metadata.Entry metadata} about the output file. */
|
||||||
|
@ -28,6 +28,7 @@ import static java.lang.Math.max;
|
|||||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
|
||||||
|
import android.media.MediaCodec.BufferInfo;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.IntRange;
|
import androidx.annotation.IntRange;
|
||||||
@ -147,6 +148,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
private final ScheduledExecutorService abortScheduledExecutorService;
|
private final ScheduledExecutorService abortScheduledExecutorService;
|
||||||
private final @MonotonicNonNull Format appendVideoFormat;
|
private final @MonotonicNonNull Format appendVideoFormat;
|
||||||
private final long maxDelayBetweenSamplesMs;
|
private final long maxDelayBetweenSamplesMs;
|
||||||
|
private final BufferInfo bufferInfo;
|
||||||
|
|
||||||
private boolean isReady;
|
private boolean isReady;
|
||||||
private boolean isEnded;
|
private boolean isEnded;
|
||||||
@ -206,6 +208,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
previousTrackType = C.TRACK_TYPE_NONE;
|
previousTrackType = C.TRACK_TYPE_NONE;
|
||||||
firstVideoPresentationTimeUs = C.TIME_UNSET;
|
firstVideoPresentationTimeUs = C.TIME_UNSET;
|
||||||
abortScheduledExecutorService = Util.newSingleThreadScheduledExecutor(TIMER_THREAD_NAME);
|
abortScheduledExecutorService = Util.newSingleThreadScheduledExecutor(TIMER_THREAD_NAME);
|
||||||
|
bufferInfo = new BufferInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -552,8 +555,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
|
|
||||||
resetAbortTimer();
|
resetAbortTimer();
|
||||||
checkStateNotNull(muxer);
|
checkStateNotNull(muxer);
|
||||||
muxer.writeSampleData(
|
bufferInfo.set(
|
||||||
trackInfo.trackToken, data, presentationTimeUs, isKeyFrame ? C.BUFFER_FLAG_KEY_FRAME : 0);
|
data.position(),
|
||||||
|
data.remaining(),
|
||||||
|
presentationTimeUs,
|
||||||
|
TransformerUtil.getMediaCodecFlags(isKeyFrame ? C.BUFFER_FLAG_KEY_FRAME : 0));
|
||||||
|
muxer.writeSampleData(trackInfo.trackToken, data, bufferInfo);
|
||||||
if (trackType == C.TRACK_TYPE_VIDEO) {
|
if (trackType == C.TRACK_TYPE_VIDEO) {
|
||||||
DebugTraceUtil.logEvent(DebugTraceUtil.EVENT_MUXER_WRITE_SAMPLE_VIDEO, presentationTimeUs);
|
DebugTraceUtil.logEvent(DebugTraceUtil.EVENT_MUXER_WRITE_SAMPLE_VIDEO, presentationTimeUs);
|
||||||
} else if (trackType == C.TRACK_TYPE_AUDIO) {
|
} else if (trackType == C.TRACK_TYPE_AUDIO) {
|
||||||
|
@ -19,6 +19,7 @@ import static androidx.media3.common.util.Assertions.checkNotNull;
|
|||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.transformer.TransformerUtil.getProcessedTrackType;
|
import static androidx.media3.transformer.TransformerUtil.getProcessedTrackType;
|
||||||
|
|
||||||
|
import android.media.MediaCodec.BufferInfo;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
@ -122,15 +123,16 @@ public final class CapturingMuxer implements Muxer, Dumpable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSampleData(
|
public void writeSampleData(TrackToken trackToken, ByteBuffer data, BufferInfo bufferInfo)
|
||||||
TrackToken trackToken, ByteBuffer data, long presentationTimeUs, @C.BufferFlags int flags)
|
|
||||||
throws MuxerException {
|
throws MuxerException {
|
||||||
@C.TrackType int trackType = checkNotNull(trackTokenToType.get(trackToken));
|
@C.TrackType int trackType = checkNotNull(trackTokenToType.get(trackToken));
|
||||||
dumpableStreamByTrackType
|
dumpableStreamByTrackType
|
||||||
.get(trackType)
|
.get(trackType)
|
||||||
.addSample(
|
.addSample(
|
||||||
data, (flags & C.BUFFER_FLAG_KEY_FRAME) == C.BUFFER_FLAG_KEY_FRAME, presentationTimeUs);
|
data,
|
||||||
wrappedMuxer.writeSampleData(trackToken, data, presentationTimeUs, flags);
|
(bufferInfo.flags & C.BUFFER_FLAG_KEY_FRAME) == C.BUFFER_FLAG_KEY_FRAME,
|
||||||
|
bufferInfo.presentationTimeUs);
|
||||||
|
wrappedMuxer.writeSampleData(trackToken, data, bufferInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user