Handle clip start position equal to end position in Transformer
After this CL, Transformer will throw if the clipping start and end positions are the same because MediaMuxer doesn't support writing a file with no samples. This should work once we default to the in-app muxer. Issue: androidx/media#1242 PiperOrigin-RevId: 624861950
This commit is contained in:
parent
c151d13a1d
commit
fa0fb38ca6
@ -0,0 +1,34 @@
|
||||
format audio:
|
||||
averageBitrate = 192181
|
||||
peakBitrate = 192181
|
||||
id = 2
|
||||
sampleMimeType = audio/mp4a-latm
|
||||
codecs = mp4a.40.2
|
||||
maxInputSize = 643
|
||||
channelCount = 2
|
||||
sampleRate = 48000
|
||||
language = en
|
||||
metadata = entries=[TSSE: description=null: values=[Lavf58.76.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000]
|
||||
initializationData:
|
||||
data = length 2, hash 560
|
||||
format video:
|
||||
id = 1
|
||||
sampleMimeType = video/avc
|
||||
codecs = avc1.42C015
|
||||
maxInputSize = 14839
|
||||
width = 320
|
||||
height = 240
|
||||
frameRate = 59.997425
|
||||
colorInfo:
|
||||
colorSpace = 2
|
||||
colorRange = 1
|
||||
colorTransfer = 3
|
||||
lumaBitdepth = 8
|
||||
chromaBitdepth = 8
|
||||
metadata = entries=[TSSE: description=null: values=[Lavf58.76.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000]
|
||||
initializationData:
|
||||
data = length 31, hash 4B108214
|
||||
data = length 9, hash FBA158BB
|
||||
container metadata = entries=[TSSE: description=null: values=[Lavf58.76.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000]
|
||||
container metadata = entries=[TSSE: description=null: values=[Lavf58.76.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000]
|
||||
released = true
|
@ -88,7 +88,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return isSourceReady();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,6 +84,7 @@ import java.nio.ByteBuffer;
|
||||
private int videoTrackIndex;
|
||||
|
||||
private boolean isStarted;
|
||||
private boolean isReleased;
|
||||
|
||||
private FrameworkMuxer(MediaMuxer mediaMuxer, long videoDurationMs) {
|
||||
this.mediaMuxer = mediaMuxer;
|
||||
@ -140,15 +141,10 @@ import java.nio.ByteBuffer;
|
||||
}
|
||||
|
||||
if (!isStarted) {
|
||||
isStarted = true;
|
||||
if (Util.SDK_INT < 30 && presentationTimeUs < 0) {
|
||||
trackIndexToPresentationTimeOffsetUs.put(trackIndex, -presentationTimeUs);
|
||||
}
|
||||
try {
|
||||
mediaMuxer.start();
|
||||
} catch (RuntimeException e) {
|
||||
throw new MuxerException("Failed to start the muxer", e);
|
||||
}
|
||||
startMuxer();
|
||||
}
|
||||
|
||||
int offset = data.position();
|
||||
@ -204,11 +200,16 @@ import java.nio.ByteBuffer;
|
||||
|
||||
@Override
|
||||
public void release(boolean forCancellation) throws MuxerException {
|
||||
if (!isStarted) {
|
||||
mediaMuxer.release();
|
||||
if (isReleased) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isStarted) {
|
||||
// Start the muxer even if no samples have been written so that it throws instead of silently
|
||||
// writing nothing to the output file.
|
||||
startMuxer();
|
||||
}
|
||||
|
||||
if (videoDurationUs != C.TIME_UNSET && videoTrackIndex != C.INDEX_UNSET) {
|
||||
writeSampleData(
|
||||
videoTrackIndex,
|
||||
@ -227,9 +228,19 @@ import java.nio.ByteBuffer;
|
||||
}
|
||||
} finally {
|
||||
mediaMuxer.release();
|
||||
isReleased = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void startMuxer() throws MuxerException {
|
||||
try {
|
||||
mediaMuxer.start();
|
||||
} catch (RuntimeException e) {
|
||||
throw new MuxerException("Failed to start the muxer", e);
|
||||
}
|
||||
isStarted = true;
|
||||
}
|
||||
|
||||
// Accesses MediaMuxer state via reflection to ensure that muxer resources can be released even
|
||||
// if stopping fails.
|
||||
@SuppressLint("PrivateApi")
|
||||
|
@ -561,13 +561,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the muxer that all the samples have been {@linkplain #writeSample(int, ByteBuffer,
|
||||
* boolean, long) written} for a given track.
|
||||
* Attempts to notify the muxer that all the samples have been {@linkplain #writeSample(int,
|
||||
* ByteBuffer, boolean, long) written} for a given track.
|
||||
*
|
||||
* @param trackType The {@link C.TrackType}.
|
||||
*/
|
||||
public void endTrack(@C.TrackType int trackType) {
|
||||
if (!contains(trackTypeToInfo, trackType)) {
|
||||
if (!isReady || !contains(trackTypeToInfo, trackType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -160,6 +160,32 @@ public final class MediaItemExportTest {
|
||||
/* modifications...= */ "clipped"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void start_withClippingStartAndEndEqual_completesSuccessfully() throws Exception {
|
||||
CapturingMuxer.Factory muxerFactory = new CapturingMuxer.Factory(/* handleAudioAsPcm= */ false);
|
||||
Transformer transformer =
|
||||
createTransformerBuilder(muxerFactory, /* enableFallback= */ false).build();
|
||||
MediaItem mediaItem =
|
||||
new MediaItem.Builder()
|
||||
.setUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO_INCREASING_TIMESTAMPS_15S)
|
||||
.setClippingConfiguration(
|
||||
new MediaItem.ClippingConfiguration.Builder()
|
||||
.setStartPositionMs(0)
|
||||
.setEndPositionMs(0)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
transformer.start(mediaItem, outputDir.newFile().getPath());
|
||||
TransformerTestRunner.runLooper(transformer);
|
||||
|
||||
DumpFileAsserts.assertOutput(
|
||||
context,
|
||||
muxerFactory.getCreatedMuxer(),
|
||||
getDumpFileName(
|
||||
/* originalFileName= */ FILE_AUDIO_VIDEO_INCREASING_TIMESTAMPS_15S,
|
||||
/* modifications...= */ "clipped_to_empty"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void start_trimOptimizationEnabled_clippingConfigurationUnset_outputMatchesOriginal()
|
||||
throws Exception {
|
||||
|
Loading…
x
Reference in New Issue
Block a user