Make Mp4MoovStructure.moov() method static
Creating a moov box is same as creating any other box so there is no particular need to have a separate class for this. In a follow up CL the method will be moved into Boxes.java along with other box creation methods. Made nit changes in the final fields ordering to match with constructor parameter ordering. PiperOrigin-RevId: 653602558
This commit is contained in:
parent
570be3680c
commit
a52df6d29e
@ -124,13 +124,10 @@ public final class FragmentedMp4Muxer implements Muxer {
|
||||
FileOutputStream fileOutputStream, long fragmentDurationMs, boolean sampleCopyEnabled) {
|
||||
checkNotNull(fileOutputStream);
|
||||
metadataCollector = new MetadataCollector();
|
||||
Mp4MoovStructure moovStructure =
|
||||
new Mp4MoovStructure(
|
||||
metadataCollector, Mp4Muxer.LAST_FRAME_DURATION_BEHAVIOR_DUPLICATE_PREV_DURATION);
|
||||
fragmentedMp4Writer =
|
||||
new FragmentedMp4Writer(
|
||||
fileOutputStream,
|
||||
moovStructure,
|
||||
metadataCollector,
|
||||
AnnexBToAvccConverter.DEFAULT,
|
||||
fragmentDurationMs,
|
||||
sampleCopyEnabled);
|
||||
|
@ -64,11 +64,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
private final FileOutputStream outputStream;
|
||||
private final FileChannel output;
|
||||
private final Mp4MoovStructure moovGenerator;
|
||||
private final MetadataCollector metadataCollector;
|
||||
private final AnnexBToAvccConverter annexBToAvccConverter;
|
||||
private final List<Track> tracks;
|
||||
private final long fragmentDurationUs;
|
||||
private final boolean sampleCopyEnabled;
|
||||
private final @Mp4Muxer.LastFrameDurationBehavior int lastFrameDurationBehavior;
|
||||
private final List<Track> tracks;
|
||||
|
||||
private @MonotonicNonNull Track videoTrack;
|
||||
private int currentFragmentSequenceNumber;
|
||||
@ -80,7 +81,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
* Creates an instance.
|
||||
*
|
||||
* @param outputStream The {@link FileOutputStream} to write the data to.
|
||||
* @param moovGenerator An {@link Mp4MoovStructure} instance to generate the moov box.
|
||||
* @param metadataCollector A {@link MetadataCollector}.
|
||||
* @param annexBToAvccConverter The {@link AnnexBToAvccConverter} to be used to convert H.264 and
|
||||
* H.265 NAL units from the Annex-B format (using start codes to delineate NAL units) to the
|
||||
* AVCC format (which uses length prefixes).
|
||||
@ -89,17 +90,18 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
*/
|
||||
public FragmentedMp4Writer(
|
||||
FileOutputStream outputStream,
|
||||
Mp4MoovStructure moovGenerator,
|
||||
MetadataCollector metadataCollector,
|
||||
AnnexBToAvccConverter annexBToAvccConverter,
|
||||
long fragmentDurationMs,
|
||||
boolean sampleCopyEnabled) {
|
||||
this.outputStream = outputStream;
|
||||
this.output = outputStream.getChannel();
|
||||
this.moovGenerator = moovGenerator;
|
||||
output = outputStream.getChannel();
|
||||
this.metadataCollector = metadataCollector;
|
||||
this.annexBToAvccConverter = annexBToAvccConverter;
|
||||
this.sampleCopyEnabled = sampleCopyEnabled;
|
||||
tracks = new ArrayList<>();
|
||||
this.fragmentDurationUs = fragmentDurationMs * 1_000;
|
||||
this.sampleCopyEnabled = sampleCopyEnabled;
|
||||
lastFrameDurationBehavior = Mp4Muxer.LAST_FRAME_DURATION_BEHAVIOR_DUPLICATE_PREV_DURATION;
|
||||
tracks = new ArrayList<>();
|
||||
minInputPresentationTimeUs = Long.MAX_VALUE;
|
||||
currentFragmentSequenceNumber = 1;
|
||||
}
|
||||
@ -200,8 +202,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
output.write(Boxes.ftyp());
|
||||
// The minInputPtsUs is actually ignored as there are no pending samples to write.
|
||||
output.write(
|
||||
moovGenerator.moovMetadataHeader(
|
||||
tracks, /* minInputPtsUs= */ 0L, /* isFragmentedMp4= */ true));
|
||||
Mp4MoovStructure.moov(
|
||||
tracks,
|
||||
metadataCollector,
|
||||
/* minInputPtsUs= */ 0L,
|
||||
/* isFragmentedMp4= */ true,
|
||||
lastFrameDurationBehavior));
|
||||
}
|
||||
|
||||
private boolean shouldFlushPendingSamples(
|
||||
|
@ -30,7 +30,7 @@ import java.util.Locale;
|
||||
import org.checkerframework.checker.nullness.qual.PolyNull;
|
||||
|
||||
/** Builds the moov box structure of an MP4 file. */
|
||||
/* package */ class Mp4MoovStructure {
|
||||
/* package */ final class Mp4MoovStructure {
|
||||
/** Provides track's metadata like media format, written samples. */
|
||||
public interface TrackMetadataProvider {
|
||||
Format format();
|
||||
@ -44,20 +44,16 @@ import org.checkerframework.checker.nullness.qual.PolyNull;
|
||||
ImmutableList<Integer> writtenChunkSampleCounts();
|
||||
}
|
||||
|
||||
private final MetadataCollector metadataCollector;
|
||||
private final @Mp4Muxer.LastFrameDurationBehavior int lastFrameDurationBehavior;
|
||||
private Mp4MoovStructure() {}
|
||||
|
||||
public Mp4MoovStructure(
|
||||
MetadataCollector metadataCollector,
|
||||
@Mp4Muxer.LastFrameDurationBehavior int lastFrameDurationBehavior) {
|
||||
this.metadataCollector = metadataCollector;
|
||||
this.lastFrameDurationBehavior = lastFrameDurationBehavior;
|
||||
}
|
||||
|
||||
/** Generates a mdat header. */
|
||||
/** Returns the moov box. */
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public ByteBuffer moovMetadataHeader(
|
||||
List<? extends TrackMetadataProvider> tracks, long minInputPtsUs, boolean isFragmentedMp4) {
|
||||
public static ByteBuffer moov(
|
||||
List<? extends TrackMetadataProvider> tracks,
|
||||
MetadataCollector metadataCollector,
|
||||
long minInputPtsUs,
|
||||
boolean isFragmentedMp4,
|
||||
@Mp4Muxer.LastFrameDurationBehavior int lastFrameDurationBehavior) {
|
||||
// The timestamp will always fit into a 32-bit integer. This is already validated in the
|
||||
// Mp4Muxer.setTimestampData() API. The value after type casting might be negative, but it is
|
||||
// still valid because it is meant to be read as an unsigned integer.
|
||||
|
@ -296,13 +296,12 @@ public final class Mp4Muxer implements Muxer {
|
||||
this.outputFileFormat = outputFileFormat;
|
||||
this.cacheFileProvider = cacheFileProvider;
|
||||
metadataCollector = new MetadataCollector();
|
||||
Mp4MoovStructure moovStructure =
|
||||
new Mp4MoovStructure(metadataCollector, lastFrameDurationBehavior);
|
||||
mp4Writer =
|
||||
new Mp4Writer(
|
||||
outputChannel,
|
||||
moovStructure,
|
||||
metadataCollector,
|
||||
annexBToAvccConverter,
|
||||
lastFrameDurationBehavior,
|
||||
sampleCopyEnabled,
|
||||
attemptStreamableOutputEnabled);
|
||||
editableVideoTracks = new ArrayList<>();
|
||||
@ -465,13 +464,12 @@ public final class Mp4Muxer implements Muxer {
|
||||
cacheFilePath = checkNotNull(cacheFileProvider).getCacheFilePath();
|
||||
cacheFileOutputStream = new FileOutputStream(cacheFilePath);
|
||||
editableVideoMetadataCollector = new MetadataCollector();
|
||||
Mp4MoovStructure mp4MoovStructure =
|
||||
new Mp4MoovStructure(editableVideoMetadataCollector, lastFrameDurationBehavior);
|
||||
editableVideoMp4Writer =
|
||||
new Mp4Writer(
|
||||
cacheFileOutputStream.getChannel(),
|
||||
mp4MoovStructure,
|
||||
checkNotNull(editableVideoMetadataCollector),
|
||||
annexBToAvccConverter,
|
||||
lastFrameDurationBehavior,
|
||||
sampleCopyEnabled,
|
||||
attemptStreamableOutputEnabled);
|
||||
}
|
||||
|
@ -43,11 +43,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
private static final String FREE_BOX_TYPE = "free";
|
||||
|
||||
private final FileChannel outputFileChannel;
|
||||
private final Mp4MoovStructure moovGenerator;
|
||||
private final MetadataCollector metadataCollector;
|
||||
private final AnnexBToAvccConverter annexBToAvccConverter;
|
||||
private final @Mp4Muxer.LastFrameDurationBehavior int lastFrameDurationBehavior;
|
||||
private final boolean sampleCopyEnabled;
|
||||
private final List<Track> tracks;
|
||||
private final AtomicBoolean hasWrittenSamples;
|
||||
private final boolean sampleCopyEnabled;
|
||||
|
||||
// Stores location of the space reserved for the moov box at the beginning of the file (after ftyp
|
||||
// box)
|
||||
@ -67,26 +68,30 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
* @param fileChannel The {@link FileChannel} to write the data to. The {@link FileChannel} can be
|
||||
* closed after {@linkplain #finishWritingSamplesAndFinalizeMoovBox() finishing writing
|
||||
* samples}.
|
||||
* @param moovGenerator An {@link Mp4MoovStructure} instance to generate the moov box.
|
||||
* @param metadataCollector A {@link MetadataCollector}.
|
||||
* @param annexBToAvccConverter The {@link AnnexBToAvccConverter} to be used to convert H.264 and
|
||||
* H.265 NAL units from the Annex-B format (using start codes to delineate NAL units) to the
|
||||
* AVCC format (which uses length prefixes).
|
||||
* @param lastFrameDurationBehavior The {@link Mp4Muxer.LastFrameDurationBehavior} for the video
|
||||
* track.
|
||||
* @param sampleCopyEnabled Whether sample copying is enabled.
|
||||
* @param attemptStreamableOutputEnabled Whether to attempt to write a streamable output.
|
||||
*/
|
||||
public Mp4Writer(
|
||||
FileChannel fileChannel,
|
||||
Mp4MoovStructure moovGenerator,
|
||||
MetadataCollector metadataCollector,
|
||||
AnnexBToAvccConverter annexBToAvccConverter,
|
||||
@Mp4Muxer.LastFrameDurationBehavior int lastFrameDurationBehavior,
|
||||
boolean sampleCopyEnabled,
|
||||
boolean attemptStreamableOutputEnabled) {
|
||||
this.outputFileChannel = fileChannel;
|
||||
this.moovGenerator = moovGenerator;
|
||||
this.metadataCollector = metadataCollector;
|
||||
this.annexBToAvccConverter = annexBToAvccConverter;
|
||||
this.lastFrameDurationBehavior = lastFrameDurationBehavior;
|
||||
this.sampleCopyEnabled = sampleCopyEnabled;
|
||||
canWriteMoovAtStart = attemptStreamableOutputEnabled;
|
||||
tracks = new ArrayList<>();
|
||||
hasWrittenSamples = new AtomicBoolean(false);
|
||||
canWriteMoovAtStart = attemptStreamableOutputEnabled;
|
||||
lastMoovWritten = Range.closed(0L, 0L);
|
||||
}
|
||||
|
||||
@ -239,7 +244,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
ByteBuffer moovHeader;
|
||||
if (minInputPtsUs != Long.MAX_VALUE) {
|
||||
moovHeader =
|
||||
moovGenerator.moovMetadataHeader(tracks, minInputPtsUs, /* isFragmentedMp4= */ false);
|
||||
Mp4MoovStructure.moov(
|
||||
tracks,
|
||||
metadataCollector,
|
||||
minInputPtsUs,
|
||||
/* isFragmentedMp4= */ false,
|
||||
lastFrameDurationBehavior);
|
||||
} else {
|
||||
// Skip moov box, if there are no samples.
|
||||
moovHeader = ByteBuffer.allocate(0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user