Add support for depth/editing file format in Mp4Extractor

PiperOrigin-RevId: 662956209
This commit is contained in:
sheenachhabra 2024-08-14 09:52:32 -07:00 committed by Copybara-Service
parent 92635342fb
commit 68eaa061e0
21 changed files with 1166 additions and 66 deletions

View File

@ -119,6 +119,21 @@ public final class MdtaMetadataEntry implements Metadata.Entry {
validateData(key, value, typeIndicator);
}
/**
* Returns the editable track types from the {@linkplain #KEY_EDITABLE_TRACKS_MAP editable tracks
* map} metadata.
*/
public List<Integer> getEditableTrackTypesFromMap() {
checkState(key.equals(KEY_EDITABLE_TRACKS_MAP), "Metadata is not an editable tracks map");
// Value has 1 byte version, 1 byte track count, n bytes track types.
int numberOfTracks = value[1];
List<Integer> trackTypes = new ArrayList<>();
for (int i = 0; i < numberOfTracks; i++) {
trackTypes.add((int) value[i + 2]);
}
return trackTypes;
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
@ -235,19 +250,4 @@ public final class MdtaMetadataEntry implements Metadata.Entry {
Joiner.on(',').appendTo(sb, trackTypes);
return sb.toString();
}
/**
* Returns the editable track types from the {@linkplain #KEY_EDITABLE_TRACKS_MAP editable tracks
* map} metadata.
*/
private List<Integer> getEditableTrackTypesFromMap() {
checkState(key.equals(KEY_EDITABLE_TRACKS_MAP), "Metadata is not an editable tracks map");
// Value has 1 byte version, 1 byte track count, n bytes track types.
int numberOfTracks = value[1];
List<Integer> trackTypes = new ArrayList<>();
for (int i = 0; i < numberOfTracks; i++) {
trackTypes.add((int) value[i + 2]);
}
return trackTypes;
}
}

View File

@ -446,6 +446,9 @@ import java.util.List;
@SuppressWarnings("ConstantCaseForConstants")
public static final int TYPE_iacb = 0x69616362;
@SuppressWarnings("ConstantCaseForConstants")
public static final int TYPE_edvd = 0x65647664;
public final int type;
public Atom(int type) {

View File

@ -238,6 +238,27 @@ import com.google.common.collect.ImmutableList;
return null;
}
/**
* Returns the {@link MdtaMetadataEntry} for a given key, or {@code null} if the key is not
* present.
*
* @param metadata The {@link Metadata} to retrieve the {@link MdtaMetadataEntry} from.
* @param key The metadata key to search.
*/
@Nullable
public static MdtaMetadataEntry findMdtaMetadataEntryWithKey(Metadata metadata, String key) {
for (int i = 0; i < metadata.length(); i++) {
Metadata.Entry entry = metadata.get(i);
if (entry instanceof MdtaMetadataEntry) {
MdtaMetadataEntry mdtaMetadataEntry = (MdtaMetadataEntry) entry;
if (mdtaMetadataEntry.key.equals(key)) {
return mdtaMetadataEntry;
}
}
}
return null;
}
@Nullable
private static TextInformationFrame parseTextAttribute(
int type, String id, ParsableByteArray data) {

View File

@ -15,9 +15,21 @@
*/
package androidx.media3.extractor.mp4;
import static androidx.media3.common.C.AUXILIARY_TRACK_TYPE_DEPTH_INVERSE;
import static androidx.media3.common.C.AUXILIARY_TRACK_TYPE_DEPTH_LINEAR;
import static androidx.media3.common.C.AUXILIARY_TRACK_TYPE_ORIGINAL;
import static androidx.media3.common.C.AUXILIARY_TRACK_TYPE_UNDEFINED;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.Util.castNonNull;
import static androidx.media3.container.MdtaMetadataEntry.EDITABLE_TRACKS_SAMPLES_LOCATION_IN_EDIT_DATA_MP4;
import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_INVERSE;
import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_LINEAR;
import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_METADATA;
import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_SHARP;
import static androidx.media3.extractor.mp4.AtomParsers.parseTraks;
import static androidx.media3.extractor.mp4.MetadataUtil.findMdtaMetadataEntryWithKey;
import static androidx.media3.extractor.mp4.Sniffer.BRAND_HEIC;
import static androidx.media3.extractor.mp4.Sniffer.BRAND_QUICKTIME;
import static java.lang.Math.max;
@ -34,6 +46,7 @@ import androidx.media3.common.ParserException;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.ParsableByteArray;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.container.MdtaMetadataEntry;
import androidx.media3.container.NalUnitUtil;
import androidx.media3.extractor.Ac3Util;
import androidx.media3.extractor.Ac4Util;
@ -62,6 +75,7 @@ import java.lang.annotation.Target;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@ -93,7 +107,8 @@ public final class Mp4Extractor implements Extractor, SeekMap {
FLAG_READ_SEF_DATA,
FLAG_MARK_FIRST_VIDEO_TRACK_WITH_MAIN_ROLE,
FLAG_EMIT_RAW_SUBTITLE_DATA,
FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES
FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES,
FLAG_READ_EDITABLE_VIDEO_TRACKS
})
public @interface Flags {}
@ -143,6 +158,18 @@ public final class Mp4Extractor implements Extractor, SeekMap {
*/
public static final int FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES = 1 << 5;
// TODO: b/345219017 - Add depth/editing file format spec link after its published.
/**
* Flag to extract the editable video tracks.
*
* <p>Either primary video tracks or editable video tracks (but not both) will be extracted based
* on the flag.
*
* <p>If the flag is set but the editable video tracks are not present, then it fallbacks to
* extract primary tracks instead.
*/
public static final int FLAG_READ_EDITABLE_VIDEO_TRACKS = 1 << 6;
/**
* @deprecated Use {@link #newFactory(SubtitleParser.Factory)} instead.
*/
@ -219,6 +246,12 @@ public final class Mp4Extractor implements Extractor, SeekMap {
private int sampleCurrentNalBytesRemaining;
private boolean isSampleDependedOn;
private boolean seenFtypAtom;
private boolean seekToEdvdAtom;
private long edvdAtomOffset;
private boolean readingEditableVideoTracks;
// Used when editable video samples are in the edit data MP4 (inside edvd atom).
private long sampleOffsetForEditableVideoTracks;
// Extractor outputs.
private ExtractorOutput extractorOutput;
@ -527,9 +560,10 @@ public final class Mp4Extractor implements Extractor, SeekMap {
}
/**
* Processes the atom payload. If {@link #atomData} is null and the size is at or above the
* threshold {@link #RELOAD_MINIMUM_SEEK_DISTANCE}, {@code true} is returned and the caller should
* restart loading at the position in {@code positionHolder}. Otherwise, the atom is read/skipped.
* Processes the atom payload.
*
* <p>If seek is required, {@code true} is returned and the caller should restart loading at the
* position in {@code positionHolder}. Otherwise the atom is read/skipped.
*/
private boolean readAtomPayload(ExtractorInput input, PositionHolder positionHolder)
throws IOException {
@ -560,6 +594,12 @@ public final class Mp4Extractor implements Extractor, SeekMap {
}
}
processAtomEnded(atomEndPosition);
if (seekToEdvdAtom) {
readingEditableVideoTracks = true;
positionHolder.position = edvdAtomOffset;
seekRequired = true;
seekToEdvdAtom = false;
}
return seekRequired && parserState != STATE_READING_SAMPLE;
}
@ -579,7 +619,9 @@ public final class Mp4Extractor implements Extractor, SeekMap {
// We've reached the end of the moov atom. Process it and prepare to read samples.
processMoovAtom(containerAtom);
containerAtoms.clear();
parserState = STATE_READING_SAMPLE;
if (!seekToEdvdAtom) {
parserState = STATE_READING_SAMPLE;
}
} else if (!containerAtoms.isEmpty()) {
containerAtoms.peek().add(containerAtom);
}
@ -589,13 +631,35 @@ public final class Mp4Extractor implements Extractor, SeekMap {
}
}
/** Updates the stored track metadata to reflect the contents of the specified moov atom. */
/**
* Processes moov atom and updates the stored track metadata.
*
* <p>The processing is aborted if the edvd.moov atom needs to be processed instead.
*/
private void processMoovAtom(ContainerAtom moov) throws ParserException {
// Process metadata first to determine whether to abort processing and seek to the edvd atom.
@Nullable Metadata mdtaMetadata = null;
@Nullable Atom.ContainerAtom meta = moov.getContainerAtomOfType(Atom.TYPE_meta);
List<@C.AuxiliaryTrackType Integer> auxiliaryTrackTypesForEditableVideoTracks =
new ArrayList<>();
if (meta != null) {
mdtaMetadata = AtomParsers.parseMdtaFromMeta(meta);
if (readingEditableVideoTracks) {
checkStateNotNull(mdtaMetadata);
maybeSetDefaultSampleOffsetForEditableVideoTracks(mdtaMetadata);
auxiliaryTrackTypesForEditableVideoTracks =
getAuxiliaryTrackTypesForEditableVideoTracks(mdtaMetadata);
} else if (shouldSeekToEdvdAtom(mdtaMetadata)) {
seekToEdvdAtom = true;
return;
}
}
int firstVideoTrackIndex = C.INDEX_UNSET;
long durationUs = C.TIME_UNSET;
List<Mp4Track> tracks = new ArrayList<>();
// Process metadata.
// Process remaining metadata.
boolean isQuickTime = fileType == FILE_TYPE_QUICKTIME;
GaplessInfoHolder gaplessInfoHolder = new GaplessInfoHolder();
@Nullable Metadata udtaMetadata = null;
@ -604,11 +668,6 @@ public final class Mp4Extractor implements Extractor, SeekMap {
udtaMetadata = AtomParsers.parseUdta(udta);
gaplessInfoHolder.setFromMetadata(udtaMetadata);
}
@Nullable Metadata mdtaMetadata = null;
@Nullable Atom.ContainerAtom meta = moov.getContainerAtomOfType(Atom.TYPE_meta);
if (meta != null) {
mdtaMetadata = AtomParsers.parseMdtaFromMeta(meta);
}
Metadata mvhdMetadata =
new Metadata(
@ -625,6 +684,16 @@ public final class Mp4Extractor implements Extractor, SeekMap {
isQuickTime,
/* modifyTrackFunction= */ track -> track);
if (readingEditableVideoTracks) {
checkState(
auxiliaryTrackTypesForEditableVideoTracks.size() == trackSampleTables.size(),
String.format(
Locale.US,
"The number of auxiliary track types from metadata (%d) is not same as the number of"
+ " editable video tracks (%d)",
auxiliaryTrackTypesForEditableVideoTracks.size(),
trackSampleTables.size()));
}
int trackIndex = 0;
for (int i = 0; i < trackSampleTables.size(); i++) {
TrackSampleTable trackSampleTable = trackSampleTables.get(i);
@ -651,17 +720,20 @@ public final class Mp4Extractor implements Extractor, SeekMap {
Format.Builder formatBuilder = track.format.buildUpon();
formatBuilder.setMaxInputSize(maxInputSize);
if (track.type == C.TRACK_TYPE_VIDEO) {
@C.RoleFlags int roleFlags = track.format.roleFlags;
if ((flags & FLAG_MARK_FIRST_VIDEO_TRACK_WITH_MAIN_ROLE) != 0) {
formatBuilder.setRoleFlags(
track.format.roleFlags
| (firstVideoTrackIndex == C.INDEX_UNSET
? C.ROLE_FLAG_MAIN
: C.ROLE_FLAG_ALTERNATE));
roleFlags |=
firstVideoTrackIndex == C.INDEX_UNSET ? C.ROLE_FLAG_MAIN : C.ROLE_FLAG_ALTERNATE;
}
if (trackDurationUs > 0 && trackSampleTable.sampleCount > 0) {
float frameRate = trackSampleTable.sampleCount / (trackDurationUs / 1000000f);
formatBuilder.setFrameRate(frameRate);
}
if (readingEditableVideoTracks) {
roleFlags |= C.ROLE_FLAG_AUXILIARY;
formatBuilder.setAuxiliaryTrackType(auxiliaryTrackTypesForEditableVideoTracks.get(i));
}
formatBuilder.setRoleFlags(roleFlags);
}
MetadataUtil.setFormatGaplessInfo(track.type, gaplessInfoHolder, formatBuilder);
@ -688,6 +760,72 @@ public final class Mp4Extractor implements Extractor, SeekMap {
extractorOutput.seekMap(this);
}
private boolean shouldSeekToEdvdAtom(@Nullable Metadata mdtaMetadata) {
if (mdtaMetadata == null) {
return false;
}
if ((flags & FLAG_READ_EDITABLE_VIDEO_TRACKS) != 0) {
@Nullable
MdtaMetadataEntry edvdAtomOffsetMetadata =
findMdtaMetadataEntryWithKey(mdtaMetadata, MdtaMetadataEntry.KEY_EDITABLE_TRACKS_OFFSET);
if (edvdAtomOffsetMetadata != null) {
long offset = new ParsableByteArray(edvdAtomOffsetMetadata.value).readUnsignedLongToLong();
if (offset > 0) {
edvdAtomOffset = offset;
return true;
}
}
}
return false;
}
/**
* Sets the sample offset for the editable video tracks, if the samples are in the edit data MP4
* (inside edvd atom).
*/
private void maybeSetDefaultSampleOffsetForEditableVideoTracks(Metadata metadata) {
@Nullable
MdtaMetadataEntry sampleLocationMetadata =
findMdtaMetadataEntryWithKey(
metadata, MdtaMetadataEntry.KEY_EDITABLE_TRACKS_SAMPLES_LOCATION);
if (sampleLocationMetadata != null) {
if (sampleLocationMetadata.value[0] == EDITABLE_TRACKS_SAMPLES_LOCATION_IN_EDIT_DATA_MP4) {
sampleOffsetForEditableVideoTracks = edvdAtomOffset + 16; // 16 bits for edvd atom header
}
}
}
private List<@C.AuxiliaryTrackType Integer> getAuxiliaryTrackTypesForEditableVideoTracks(
Metadata metadata) {
MdtaMetadataEntry trackTypesMetadata =
checkStateNotNull(
findMdtaMetadataEntryWithKey(metadata, MdtaMetadataEntry.KEY_EDITABLE_TRACKS_MAP));
List<Integer> editableVideoTrackTypes = trackTypesMetadata.getEditableTrackTypesFromMap();
List<@C.AuxiliaryTrackType Integer> auxiliaryTrackTypes =
new ArrayList<>(editableVideoTrackTypes.size());
for (int i = 0; i < editableVideoTrackTypes.size(); i++) {
@C.AuxiliaryTrackType int auxiliaryTrackType;
switch (editableVideoTrackTypes.get(i)) {
case EDITABLE_TRACK_TYPE_SHARP:
auxiliaryTrackType = AUXILIARY_TRACK_TYPE_ORIGINAL;
break;
case EDITABLE_TRACK_TYPE_DEPTH_LINEAR:
auxiliaryTrackType = AUXILIARY_TRACK_TYPE_DEPTH_LINEAR;
break;
case EDITABLE_TRACK_TYPE_DEPTH_INVERSE:
auxiliaryTrackType = AUXILIARY_TRACK_TYPE_DEPTH_INVERSE;
break;
case EDITABLE_TRACK_TYPE_DEPTH_METADATA:
auxiliaryTrackType = C.AUXILIARY_TRACK_TYPE_DEPTH_METADATA;
break;
default:
auxiliaryTrackType = AUXILIARY_TRACK_TYPE_UNDEFINED;
}
auxiliaryTrackTypes.add(auxiliaryTrackType);
}
return auxiliaryTrackTypes;
}
/**
* Attempts to extract the next sample in the current mdat atom for the specified track.
*
@ -714,7 +852,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
Mp4Track track = tracks[sampleTrackIndex];
TrackOutput trackOutput = track.trackOutput;
int sampleIndex = track.sampleIndex;
long position = track.sampleTable.offsets[sampleIndex];
long position = track.sampleTable.offsets[sampleIndex] + sampleOffsetForEditableVideoTracks;
int sampleSize = track.sampleTable.sizes[sampleIndex];
@Nullable TrueHdSampleRechunker trueHdSampleRechunker = track.trueHdSampleRechunker;
long skipAmount = position - inputPosition + sampleBytesRead;
@ -1067,7 +1205,8 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|| atom == Atom.TYPE_minf
|| atom == Atom.TYPE_stbl
|| atom == Atom.TYPE_edts
|| atom == Atom.TYPE_meta;
|| atom == Atom.TYPE_meta
|| atom == Atom.TYPE_edvd;
}
private static final class Mp4Track {

View File

@ -17,10 +17,13 @@ package androidx.media3.extractor.mp4;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import androidx.media3.extractor.Extractor;
import androidx.media3.extractor.PositionHolder;
import androidx.media3.extractor.SniffFailure;
import androidx.media3.extractor.text.DefaultSubtitleParserFactory;
import androidx.media3.extractor.text.SubtitleParser;
import androidx.media3.test.utils.DumpFileAsserts;
import androidx.media3.test.utils.FakeExtractorInput;
import androidx.media3.test.utils.FakeExtractorOutput;
import androidx.media3.test.utils.FakeTrackOutput;
@ -102,6 +105,44 @@ public final class Mp4ExtractorNonParameterizedTest {
assertThat(extractorSeekTimeUs).isIn(trackSeekTimesUs.build());
}
@Test
public void
extract_fileHavingNoEditableVideoTracksWithReadEditableVideoTracksFlag_extractsPrimaryVideoTracks()
throws Exception {
Context context = ApplicationProvider.getApplicationContext();
String inputFilePath = "media/mp4/sample.mp4";
Mp4Extractor mp4Extractor =
new Mp4Extractor(
new DefaultSubtitleParserFactory(), Mp4Extractor.FLAG_READ_EDITABLE_VIDEO_TRACKS);
FakeExtractorOutput primaryTracksOutput =
TestUtil.extractAllSamplesFromFile(mp4Extractor, context, inputFilePath);
String dumpFilePath = getDumpFilePath(inputFilePath, "_with_flag_read_Editable_video_tracks");
DumpFileAsserts.assertOutput(context, primaryTracksOutput, dumpFilePath);
}
@Test
public void
extract_fileHavingEditableVideoTracksWithReadEditableVideoTracksFlag_extractsEditableVideoTracks()
throws Exception {
Context context = ApplicationProvider.getApplicationContext();
String inputFilePath = "media/mp4/sample_with_fake_editable_video_tracks.mp4";
Mp4Extractor mp4Extractor =
new Mp4Extractor(
new DefaultSubtitleParserFactory(), Mp4Extractor.FLAG_READ_EDITABLE_VIDEO_TRACKS);
FakeExtractorOutput editableTracksOutput =
TestUtil.extractAllSamplesFromFile(mp4Extractor, context, inputFilePath);
String dumpFilePath = getDumpFilePath(inputFilePath, "_with_flag_read_Editable_video_tracks");
DumpFileAsserts.assertOutput(context, editableTracksOutput, dumpFilePath);
}
private static String getDumpFilePath(String inputFilePath, String suffix) {
return inputFilePath.replaceFirst("media", "extractordumps") + suffix;
}
private static FakeExtractorInput createInputForSample(String sample) throws IOException {
return new FakeExtractorInput.Builder()
.setData(

View File

@ -218,6 +218,11 @@ public final class Mp4ExtractorParameterizedTest {
assertExtractorBehavior("media/mp4/water_180_mvhevc_5frames.mov");
}
@Test
public void mp4WithEditableVideoTracks() throws Exception {
assertExtractorBehavior("media/mp4/sample_with_fake_editable_video_tracks.mp4");
}
private void assertExtractorBehavior(String file) throws IOException {
ExtractorAsserts.AssertionConfig.Builder assertionConfigBuilder =
new ExtractorAsserts.AssertionConfig.Builder();

View File

@ -25,8 +25,6 @@ import android.content.Context;
import android.media.MediaCodec.BufferInfo;
import android.util.Pair;
import androidx.media3.common.C;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.ParsableByteArray;
import androidx.media3.common.util.Util;
import androidx.media3.container.MdtaMetadataEntry;
import androidx.media3.container.Mp4LocationData;
@ -43,7 +41,6 @@ import androidx.media3.test.utils.TestUtil;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.junit.Rule;
import org.junit.Test;
@ -510,7 +507,7 @@ public class Mp4MuxerEndToEndTest {
FakeExtractorOutput primaryTracksOutput =
TestUtil.extractAllSamplesFromFilePath(
new Mp4Extractor(new DefaultSubtitleParserFactory()), outputFilePath);
// The Mp4Extractor can not read edvd box and can only parse primary tracks.
// The Mp4Extractor extracts primary tracks by default.
DumpFileAsserts.assertOutput(
context,
primaryTracksOutput,
@ -556,11 +553,11 @@ public class Mp4MuxerEndToEndTest {
muxer.close();
}
byte[] edvdBoxPayload = getEdvdBoxPayload(outputFilePath);
FakeExtractorOutput editableTracksOutput =
TestUtil.extractAllSamplesFromByteArray(
new Mp4Extractor(new DefaultSubtitleParserFactory()), edvdBoxPayload);
// The Mp4Extractor can parse the MP4 embedded in the edvd box.
TestUtil.extractAllSamplesFromFilePath(
new Mp4Extractor(
new DefaultSubtitleParserFactory(), Mp4Extractor.FLAG_READ_EDITABLE_VIDEO_TRACKS),
outputFilePath);
DumpFileAsserts.assertOutput(
context,
editableTracksOutput,
@ -575,28 +572,4 @@ public class Mp4MuxerEndToEndTest {
muxer.writeSampleData(trackToken, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
}
}
private static byte[] getEdvdBoxPayload(String filePath) throws IOException {
ParsableByteArray data = new ParsableByteArray(TestUtil.getByteArrayFromFilePath(filePath));
while (data.bytesLeft() > 0) {
long size = data.readInt();
String name = data.readString(/* length= */ 4);
long payloadSize = size - 8;
if (size == 1) {
size = data.readUnsignedLongToLong();
// Parsing is not supported for box having size > Integer.MAX_VALUE.
Assertions.checkState(size <= Integer.MAX_VALUE);
// Subtract 4 bytes (32-bit box size) + 4 bytes (box name) + 8 bytes (64-bit box size).
payloadSize = size - 16;
}
if (name.equals("edvd")) {
byte[] payloadData = new byte[(int) payloadSize];
data.readBytes(payloadData, /* offset= */ 0, (int) payloadSize);
return payloadData;
} else {
data.skipBytes((int) payloadSize);
}
}
return new byte[0];
}
}

View File

@ -0,0 +1,343 @@
seekMap:
isSeekable = true
duration = 1024000
getPosition(0) = [[timeUs=0, position=2269]]
getPosition(1) = [[timeUs=0, position=2269]]
getPosition(512000) = [[timeUs=0, position=2269]]
getPosition(1024000) = [[timeUs=0, position=2269]]
numberOfTracks = 2
track 0:
total output bytes = 89876
sample count = 30
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.64001F
maxInputSize = 36722
maxNumReorderSamples = 2
width = 1080
height = 720
frameRate = 29.970028
colorInfo:
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[TSSE: description=null: values=[Lavf56.1.0], xyz: latitude=40.68, longitude=-74.5, Mp4Timestamp: creation time=3547558895, modification time=3547558895, timescale=1000]
initializationData:
data = length 29, hash 4746B5D9
data = length 10, hash 7A0D0F2B
sample 0:
time = 0
flags = 1
data = length 36692, hash D216076E
sample 1:
time = 66733
flags = 0
data = length 5312, hash D45D3CA0
sample 2:
time = 33366
flags = 0
data = length 599, hash 1BE7812D
sample 3:
time = 200200
flags = 0
data = length 7735, hash 4490F110
sample 4:
time = 133466
flags = 0
data = length 987, hash 560B5036
sample 5:
time = 100100
flags = 0
data = length 673, hash ED7CD8C7
sample 6:
time = 166833
flags = 0
data = length 523, hash 3020DF50
sample 7:
time = 333666
flags = 0
data = length 6061, hash 736C72B2
sample 8:
time = 266933
flags = 0
data = length 992, hash FE132F23
sample 9:
time = 233566
flags = 0
data = length 623, hash 5B2C1816
sample 10:
time = 300300
flags = 0
data = length 421, hash 742E69C1
sample 11:
time = 433766
flags = 0
data = length 4899, hash F72F86A1
sample 12:
time = 400400
flags = 0
data = length 568, hash 519A8E50
sample 13:
time = 367033
flags = 0
data = length 620, hash 3990AA39
sample 14:
time = 567233
flags = 0
data = length 5450, hash F06EC4AA
sample 15:
time = 500500
flags = 0
data = length 1051, hash 92DFA63A
sample 16:
time = 467133
flags = 0
data = length 874, hash 69587FB4
sample 17:
time = 533866
flags = 0
data = length 781, hash 36BE495B
sample 18:
time = 700700
flags = 0
data = length 4725, hash AC0C8CD3
sample 19:
time = 633966
flags = 0
data = length 1022, hash 5D8BFF34
sample 20:
time = 600600
flags = 0
data = length 790, hash 99413A99
sample 21:
time = 667333
flags = 0
data = length 610, hash 5E129290
sample 22:
time = 834166
flags = 0
data = length 2751, hash 769974CB
sample 23:
time = 767433
flags = 0
data = length 745, hash B78A477A
sample 24:
time = 734066
flags = 0
data = length 621, hash CF741E7A
sample 25:
time = 800800
flags = 0
data = length 505, hash 1DB4894E
sample 26:
time = 967633
flags = 0
data = length 1268, hash C15348DC
sample 27:
time = 900900
flags = 0
data = length 880, hash C2DE85D0
sample 28:
time = 867533
flags = 0
data = length 530, hash C98BC6A8
sample 29:
time = 934266
flags = 536870912
data = length 568, hash 4FE5C8EA
track 1:
total output bytes = 9529
sample count = 45
format 0:
peakBitrate = 200000
id = 2
sampleMimeType = audio/mp4a-latm
codecs = mp4a.40.2
maxInputSize = 294
channelCount = 1
sampleRate = 44100
language = und
metadata = entries=[TSSE: description=null: values=[Lavf56.1.0], xyz: latitude=40.68, longitude=-74.5, Mp4Timestamp: creation time=3547558895, modification time=3547558895, timescale=1000]
initializationData:
data = length 2, hash 5F7
sample 0:
time = 44000
flags = 1
data = length 23, hash 47DE9131
sample 1:
time = 67219
flags = 1
data = length 6, hash 31EC5206
sample 2:
time = 90439
flags = 1
data = length 148, hash 894A176B
sample 3:
time = 113659
flags = 1
data = length 189, hash CEF235A1
sample 4:
time = 136879
flags = 1
data = length 205, hash BBF5F7B0
sample 5:
time = 160099
flags = 1
data = length 210, hash F278B193
sample 6:
time = 183319
flags = 1
data = length 210, hash 82DA1589
sample 7:
time = 206539
flags = 1
data = length 207, hash 5BE231DF
sample 8:
time = 229759
flags = 1
data = length 225, hash 18819EE1
sample 9:
time = 252979
flags = 1
data = length 215, hash CA7FA67B
sample 10:
time = 276199
flags = 1
data = length 211, hash 581A1C18
sample 11:
time = 299419
flags = 1
data = length 216, hash ADB88187
sample 12:
time = 322639
flags = 1
data = length 229, hash 2E8BA4DC
sample 13:
time = 345859
flags = 1
data = length 232, hash 22F0C510
sample 14:
time = 369079
flags = 1
data = length 235, hash 867AD0DC
sample 15:
time = 392299
flags = 1
data = length 231, hash 84E823A8
sample 16:
time = 415519
flags = 1
data = length 226, hash 1BEF3A95
sample 17:
time = 438739
flags = 1
data = length 216, hash EAA345AE
sample 18:
time = 461959
flags = 1
data = length 229, hash 6957411F
sample 19:
time = 485179
flags = 1
data = length 219, hash 41275022
sample 20:
time = 508399
flags = 1
data = length 241, hash 6495DF96
sample 21:
time = 531619
flags = 1
data = length 228, hash 63D95906
sample 22:
time = 554839
flags = 1
data = length 238, hash 34F676F9
sample 23:
time = 578058
flags = 1
data = length 234, hash E5CBC045
sample 24:
time = 601278
flags = 1
data = length 231, hash 5FC43661
sample 25:
time = 624498
flags = 1
data = length 217, hash 682708ED
sample 26:
time = 647718
flags = 1
data = length 239, hash D43780FC
sample 27:
time = 670938
flags = 1
data = length 243, hash C5E17980
sample 28:
time = 694158
flags = 1
data = length 231, hash AC5837BA
sample 29:
time = 717378
flags = 1
data = length 230, hash 169EE895
sample 30:
time = 740598
flags = 1
data = length 238, hash C48FF3F1
sample 31:
time = 763818
flags = 1
data = length 225, hash 531E4599
sample 32:
time = 787038
flags = 1
data = length 232, hash CB3C6B8D
sample 33:
time = 810258
flags = 1
data = length 243, hash F8C94C7
sample 34:
time = 833478
flags = 1
data = length 232, hash A646A7D0
sample 35:
time = 856698
flags = 1
data = length 237, hash E8B787A5
sample 36:
time = 879918
flags = 1
data = length 228, hash 3FA7A29F
sample 37:
time = 903138
flags = 1
data = length 235, hash B9B33B0A
sample 38:
time = 926358
flags = 1
data = length 264, hash 71A4869E
sample 39:
time = 949578
flags = 1
data = length 257, hash D049B54C
sample 40:
time = 972798
flags = 1
data = length 227, hash 66757231
sample 41:
time = 996018
flags = 1
data = length 227, hash BD374F1B
sample 42:
time = 1019238
flags = 1
data = length 235, hash 999477F6
sample 43:
time = 1042458
flags = 1
data = length 229, hash FFF98DF0
sample 44:
time = 1065678
flags = 536870913
data = length 6, hash 31B22286
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,48 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=editable.tracks.offset, value=400332, mdta: key=editable.tracks.length, value=400628, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -0,0 +1,91 @@
seekMap:
isSeekable = true
duration = 0
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400276]]
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(0) = [[timeUs=0, position=400052]]
numberOfTracks = 2
track 0:
total output bytes = 280
sample count = 5
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
roleFlags = [auxiliary]
auxiliaryTrackType = original
metadata = entries=[mdta: key=editable.tracks.map, value=track types = 0,1, mdta: key=editable.tracks.samples.location, value=0, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
track 1:
total output bytes = 280
sample count = 5
format 0:
id = 2
sampleMimeType = video/avc
codecs = avc1.F4000A
maxInputSize = 86
maxNumReorderSamples = 2
width = 12
height = 10
colorInfo:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
roleFlags = [auxiliary]
auxiliaryTrackType = depth-linear
metadata = entries=[mdta: key=editable.tracks.map, value=track types = 0,1, mdta: key=editable.tracks.samples.location, value=0, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
sample 0:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 1:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 2:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 3:
time = 0
flags = 1
data = length 56, hash C4551A2E
sample 4:
time = 0
flags = 536870913
data = length 56, hash C4551A2E
tracksEnded = true

View File

@ -21,6 +21,8 @@ track 0:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
roleFlags = [auxiliary]
auxiliaryTrackType = original
metadata = entries=[mdta: key=editable.tracks.map, value=track types = 0,1, mdta: key=editable.tracks.samples.location, value=0, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510
@ -60,6 +62,8 @@ track 1:
colorRange = 1
lumaBitdepth = 8
chromaBitdepth = 8
roleFlags = [auxiliary]
auxiliaryTrackType = depth-linear
metadata = entries=[mdta: key=editable.tracks.map, value=track types = 0,1, mdta: key=editable.tracks.samples.location, value=0, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000]
initializationData:
data = length 28, hash 410B510