MidiExtractor: mark only the first sample as key-frame

This change fixes a bug with seeking forward in MIDI. When seeking forward,
the progressive media period attempts to seek within the sample queue, if a
key-frame exists before the seeking position. With MIDI, however, we can
only skip Note-On and Note-Off samples and all other samples must be sent
to the MIDI decoder.

When seeking outside the sample queue, the MidiExtractor already
instructs the player to start from the beginning of the MIDI input. With
this change, only the first output sample is a key-frame, thus the
progressive media period can no longer seek within the sample queue and
is forced to seek from the MIDI input start always.

Issue: androidx/media#704

#minor-release

PiperOrigin-RevId: 584321443
This commit is contained in:
christosts 2023-11-21 07:36:48 -08:00 committed by Copybara-Service
parent 79fd3365fa
commit ec08db458e
9 changed files with 340 additions and 294 deletions

View File

@ -91,6 +91,8 @@
* Decoder Extensions (FFmpeg, VP9, AV1, MIDI, etc.):
* MIDI decoder: Ignore SysEx event messages
([#710](https://github.com/androidx/media/pull/710)).
* MIDI: Fix issue where seeking forward skips the Program Change events
([#704](https://github.com/androidx/media/issues/704).
* Leanback extension:
* Cast Extension:
* Sanitize creation of a `Timeline` to not crash the app when loading

View File

@ -17,17 +17,19 @@ package androidx.media3.decoder.midi;
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 java.lang.annotation.ElementType.TYPE_USE;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.DataReader;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.ParserException;
import androidx.media3.common.util.ParsableByteArray;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.extractor.DummyTrackOutput;
import androidx.media3.extractor.Extractor;
import androidx.media3.extractor.ExtractorInput;
import androidx.media3.extractor.ExtractorOutput;
@ -43,6 +45,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.PriorityQueue;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** Extracts data from MIDI containers. */
@UnstableApi
@ -99,14 +102,13 @@ public final class MidiExtractor implements Extractor, SeekMap {
private int ticksPerQuarterNote;
private long currentTimestampUs;
private long startTimeUs;
private TrackOutput trackOutput;
private @MonotonicNonNull SingleKeyFrameTrackOutput trackOutput;
public MidiExtractor() {
state = STATE_INITIALIZED;
trackChunkList = new ArrayList<>();
trackPriorityQueue = new PriorityQueue<>();
midiFileData = new ParsableByteArray(/* limit= */ 512);
trackOutput = new DummyTrackOutput();
}
// Extractor implementation.
@ -117,7 +119,7 @@ public final class MidiExtractor implements Extractor, SeekMap {
throw new IllegalStateException();
}
trackOutput = output.track(0, C.TRACK_TYPE_AUDIO);
trackOutput = new SingleKeyFrameTrackOutput(output.track(0, C.TRACK_TYPE_AUDIO));
trackOutput.format(
new Format.Builder()
.setCodecs(MimeTypes.AUDIO_MIDI)
@ -140,6 +142,9 @@ public final class MidiExtractor implements Extractor, SeekMap {
public void seek(long position, long timeUs) {
checkState(state != STATE_RELEASED);
startTimeUs = timeUs;
if (trackOutput != null) {
trackOutput.reset();
}
if (state == STATE_LOADING) {
midiFileData.setPosition(0);
bytesRead = 0;
@ -211,7 +216,8 @@ public final class MidiExtractor implements Extractor, SeekMap {
outputEmptySample();
} else { // Event time is sooner than the maximum threshold.
currentTimestampUs = nextCommandTimestampUs;
nextChunk.outputFrontSample(trackOutput);
nextChunk.outputFrontSample(
checkStateNotNull(trackOutput), /* skipNoteEvents= */ false);
nextChunk.populateFrontTrackEvent();
}
@ -223,9 +229,8 @@ public final class MidiExtractor implements Extractor, SeekMap {
return result;
case STATE_INITIALIZED:
case STATE_RELEASED:
throw new IllegalStateException();
default:
throw new IllegalStateException(); // Should never happen.
throw new IllegalStateException();
}
}
@ -333,12 +338,13 @@ public final class MidiExtractor implements Extractor, SeekMap {
}
private void outputEmptySample() {
trackOutput.sampleMetadata(
currentTimestampUs,
/* flags= */ C.BUFFER_FLAG_KEY_FRAME,
/* size= */ 0,
/* offset= */ 0,
/* cryptoData= */ null);
checkStateNotNull(trackOutput)
.sampleMetadata(
currentTimestampUs,
/* flags= */ 0,
/* size= */ 0,
/* offset= */ 0,
/* cryptoData= */ null);
}
private void seekChunksTo(long seekTimeUs) throws ParserException {
@ -347,12 +353,64 @@ public final class MidiExtractor implements Extractor, SeekMap {
long nextTimestampUs = nextChunk.peekNextTimestampUs();
if (nextTimestampUs != C.TIME_UNSET && nextTimestampUs < seekTimeUs) {
nextChunk.outputFrontSample(
trackOutput, C.BUFFER_FLAG_KEY_FRAME, /* skipNoteEvents= */ true);
nextChunk.outputFrontSample(checkStateNotNull(trackOutput), /* skipNoteEvents= */ true);
nextChunk.populateFrontTrackEvent();
trackPriorityQueue.add(nextChunk);
}
}
trackPriorityQueue.addAll(trackChunkList);
}
/**
* A {@link TrackOutput} wrapper that marks only the first sample as a key-frame.
*
* <p>Only the first sample is marked as a key-frame so that seeking requires the player to seek
* to the beginning of the MIDI input and output all non Note-On and Note-Off events to the {@link
* MidiDecoder}.
*/
private static final class SingleKeyFrameTrackOutput implements TrackOutput {
private final TrackOutput trackOutput;
private int outputSampleCount;
private SingleKeyFrameTrackOutput(TrackOutput trackOutput) {
this.trackOutput = trackOutput;
}
@Override
public void format(Format format) {
trackOutput.format(format);
}
@Override
public int sampleData(
DataReader input, int length, boolean allowEndOfInput, @SampleDataPart int sampleDataPart)
throws IOException {
return trackOutput.sampleData(input, length, allowEndOfInput, sampleDataPart);
}
@Override
public void sampleData(ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) {
trackOutput.sampleData(data, length, sampleDataPart);
}
@Override
public void sampleMetadata(
long timeUs,
@C.BufferFlags int flags,
int size,
int offset,
@Nullable CryptoData cryptoData) {
// No MIDI sample should be marked as key-frame
checkState((flags & C.BUFFER_FLAG_KEY_FRAME) == 0);
if (outputSampleCount == 0) {
flags |= C.BUFFER_FLAG_KEY_FRAME;
}
trackOutput.sampleMetadata(timeUs, flags, size, offset, cryptoData);
outputSampleCount++;
}
public void reset() {
outputSampleCount = 0;
}
}
}

View File

@ -90,25 +90,13 @@ import java.util.ArrayList;
ticksPerQuarterNote);
}
/**
* Outputs the front sample to {@code trackOutput}, flagged as a {@linkplain
* C#BUFFER_FLAG_KEY_FRAME key frame}.
*/
public void outputFrontSample(TrackOutput trackOutput) {
outputFrontSample(
/* trackOutput= */ trackOutput,
/* flags= */ C.BUFFER_FLAG_KEY_FRAME,
/* skipNoteEvents= */ false);
}
/**
* Outputs the current track event to {@code trackOutput}.
*
* @param trackOutput The {@link TrackOutput} to output samples to.
* @param flags {@link C.BufferFlags} to mark the buffer with.
* @param skipNoteEvents Whether note events should be skipped.
*/
public void outputFrontSample(TrackOutput trackOutput, int flags, boolean skipNoteEvents) {
public void outputFrontSample(TrackOutput trackOutput, boolean skipNoteEvents) {
if (!currentTrackEvent.isPopulated()) {
return;
}
@ -149,7 +137,7 @@ import java.util.ArrayList;
trackOutput.sampleData(sampleData, sampleSize);
trackOutput.sampleMetadata(
lastOutputEventTimestampUs,
/* flags= */ flags,
/* flags= */ 0,
/* size= */ sampleSize,
/* offset= */ 0,
/* cryptoData= */ null);
@ -207,10 +195,8 @@ import java.util.ArrayList;
return 1;
} else if (otherTimestampUs == C.TIME_UNSET) {
return -1;
} else if (thisTimestampUs < otherTimestampUs) {
return -1;
} else {
return 1;
return Long.compare(thisTimestampUs, otherTimestampUs);
}
}

View File

@ -52,7 +52,7 @@ public class TrackChunkTest {
/* tempoListener= */ mock(TrackChunk.TempoChangedListener.class));
trackChunk.populateFrontTrackEvent();
trackChunk.outputFrontSample(fakeTrackOutput);
trackChunk.outputFrontSample(fakeTrackOutput, /* skipNoteEvents= */ false);
assertThat(fakeTrackOutput.getSampleTimeUs(/* index= */ 0)).isEqualTo(/* expected= */ 0);
trackChunk.addTempoChange(/* tempoBpm= */ 180, /* ticks= */ 480);
@ -60,7 +60,7 @@ public class TrackChunkTest {
trackChunk.addTempoChange(/* tempoBpm= */ 300, /* ticks= */ 1440);
trackChunk.populateFrontTrackEvent();
trackChunk.outputFrontSample(fakeTrackOutput);
trackChunk.outputFrontSample(fakeTrackOutput, /* skipNoteEvents= */ false);
assertThat(fakeTrackOutput.getSampleTimeUs(/* index= */ 1)).isEqualTo(/* expected= */ 1283333);
}
}

View File

@ -16,382 +16,382 @@ track 0:
data = length 7, hash C95FA520
sample 1:
time = 0
flags = 1
flags = 0
data = length 5, hash 1CF3DA7
sample 2:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFED75B
sample 3:
time = 100000
flags = 1
flags = 0
data = length 0, hash 1
sample 4:
time = 200000
flags = 1
flags = 0
data = length 0, hash 1
sample 5:
time = 300000
flags = 1
flags = 0
data = length 0, hash 1
sample 6:
time = 400000
flags = 1
flags = 0
data = length 0, hash 1
sample 7:
time = 500000
flags = 1
flags = 0
data = length 3, hash FFFED733
sample 8:
time = 500000
flags = 1
flags = 0
data = length 3, hash FFFED751
sample 9:
time = 600000
flags = 1
flags = 0
data = length 0, hash 1
sample 10:
time = 700000
flags = 1
flags = 0
data = length 0, hash 1
sample 11:
time = 800000
flags = 1
flags = 0
data = length 0, hash 1
sample 12:
time = 900000
flags = 1
flags = 0
data = length 0, hash 1
sample 13:
time = 1000000
flags = 1
flags = 0
data = length 3, hash FFFED733
sample 14:
time = 1000000
flags = 1
flags = 0
data = length 3, hash FFFED839
sample 15:
time = 1100000
flags = 1
flags = 0
data = length 0, hash 1
sample 16:
time = 1200000
flags = 1
flags = 0
data = length 0, hash 1
sample 17:
time = 1300000
flags = 1
flags = 0
data = length 0, hash 1
sample 18:
time = 1400000
flags = 1
flags = 0
data = length 0, hash 1
sample 19:
time = 1500000
flags = 1
flags = 0
data = length 3, hash FFFED80C
sample 20:
time = 1500000
flags = 1
flags = 0
data = length 3, hash FFFED83E
sample 21:
time = 1600000
flags = 1
flags = 0
data = length 0, hash 1
sample 22:
time = 1700000
flags = 1
flags = 0
data = length 0, hash 1
sample 23:
time = 1800000
flags = 1
flags = 0
data = length 0, hash 1
sample 24:
time = 1900000
flags = 1
flags = 0
data = length 0, hash 1
sample 25:
time = 2000000
flags = 1
flags = 0
data = length 3, hash FFFED80C
sample 26:
time = 2000000
flags = 1
flags = 0
data = length 3, hash FFFED877
sample 27:
time = 2100000
flags = 1
flags = 0
data = length 0, hash 1
sample 28:
time = 2200000
flags = 1
flags = 0
data = length 0, hash 1
sample 29:
time = 2300000
flags = 1
flags = 0
data = length 0, hash 1
sample 30:
time = 2400000
flags = 1
flags = 0
data = length 0, hash 1
sample 31:
time = 2500000
flags = 1
flags = 0
data = length 3, hash FFFED84A
sample 32:
time = 2500000
flags = 1
flags = 0
data = length 3, hash FFFED87C
sample 33:
time = 2600000
flags = 1
flags = 0
data = length 0, hash 1
sample 34:
time = 2700000
flags = 1
flags = 0
data = length 0, hash 1
sample 35:
time = 2800000
flags = 1
flags = 0
data = length 0, hash 1
sample 36:
time = 2900000
flags = 1
flags = 0
data = length 0, hash 1
sample 37:
time = 3000000
flags = 1
flags = 0
data = length 3, hash FFFED84A
sample 38:
time = 3000000
flags = 1
flags = 0
data = length 3, hash FFFED82F
sample 39:
time = 3100000
flags = 1
flags = 0
data = length 0, hash 1
sample 40:
time = 3200000
flags = 1
flags = 0
data = length 0, hash 1
sample 41:
time = 3300000
flags = 1
flags = 0
data = length 0, hash 1
sample 42:
time = 3400000
flags = 1
flags = 0
data = length 0, hash 1
sample 43:
time = 3500000
flags = 1
flags = 0
data = length 0, hash 1
sample 44:
time = 3600000
flags = 1
flags = 0
data = length 0, hash 1
sample 45:
time = 3700000
flags = 1
flags = 0
data = length 0, hash 1
sample 46:
time = 3800000
flags = 1
flags = 0
data = length 0, hash 1
sample 47:
time = 3900000
flags = 1
flags = 0
data = length 0, hash 1
sample 48:
time = 4000000
flags = 1
flags = 0
data = length 3, hash FFFED80C
sample 49:
time = 4000000
flags = 1
flags = 0
data = length 3, hash FFFED800
sample 50:
time = 4100000
flags = 1
flags = 0
data = length 0, hash 1
sample 51:
time = 4200000
flags = 1
flags = 0
data = length 0, hash 1
sample 52:
time = 4300000
flags = 1
flags = 0
data = length 0, hash 1
sample 53:
time = 4400000
flags = 1
flags = 0
data = length 0, hash 1
sample 54:
time = 4500000
flags = 1
flags = 0
data = length 3, hash FFFED7CE
sample 55:
time = 4500000
flags = 1
flags = 0
data = length 3, hash FFFED7FB
sample 56:
time = 4600000
flags = 1
flags = 0
data = length 0, hash 1
sample 57:
time = 4700000
flags = 1
flags = 0
data = length 0, hash 1
sample 58:
time = 4800000
flags = 1
flags = 0
data = length 0, hash 1
sample 59:
time = 4900000
flags = 1
flags = 0
data = length 0, hash 1
sample 60:
time = 5000000
flags = 1
flags = 0
data = length 3, hash FFFED7CE
sample 61:
time = 5000000
flags = 1
flags = 0
data = length 3, hash FFFED7E1
sample 62:
time = 5100000
flags = 1
flags = 0
data = length 0, hash 1
sample 63:
time = 5200000
flags = 1
flags = 0
data = length 0, hash 1
sample 64:
time = 5250000
flags = 1
flags = 0
data = length 3, hash FFFED7AF
sample 65:
time = 5350000
flags = 1
flags = 0
data = length 0, hash 1
sample 66:
time = 5450000
flags = 1
flags = 0
data = length 0, hash 1
sample 67:
time = 5500000
flags = 1
flags = 0
data = length 3, hash FFFED7D7
sample 68:
time = 5600000
flags = 1
flags = 0
data = length 0, hash 1
sample 69:
time = 5700000
flags = 1
flags = 0
data = length 0, hash 1
sample 70:
time = 5750000
flags = 1
flags = 0
data = length 3, hash FFFED7AF
sample 71:
time = 5850000
flags = 1
flags = 0
data = length 0, hash 1
sample 72:
time = 5950000
flags = 1
flags = 0
data = length 0, hash 1
sample 73:
time = 6000000
flags = 1
flags = 0
data = length 3, hash FFFED79E
sample 74:
time = 6100000
flags = 1
flags = 0
data = length 0, hash 1
sample 75:
time = 6200000
flags = 1
flags = 0
data = length 0, hash 1
sample 76:
time = 6250000
flags = 1
flags = 0
data = length 3, hash FFFED771
sample 77:
time = 6350000
flags = 1
flags = 0
data = length 0, hash 1
sample 78:
time = 6450000
flags = 1
flags = 0
data = length 0, hash 1
sample 79:
time = 6500000
flags = 1
flags = 0
data = length 3, hash FFFED7A3
sample 80:
time = 6600000
flags = 1
flags = 0
data = length 0, hash 1
sample 81:
time = 6700000
flags = 1
flags = 0
data = length 0, hash 1
sample 82:
time = 6750000
flags = 1
flags = 0
data = length 3, hash FFFED771
sample 83:
time = 6850000
flags = 1
flags = 0
data = length 0, hash 1
sample 84:
time = 6950000
flags = 1
flags = 0
data = length 0, hash 1
sample 85:
time = 7000000
flags = 1
flags = 0
data = length 3, hash FFFED751
sample 86:
time = 7100000
flags = 1
flags = 0
data = length 0, hash 1
sample 87:
time = 7200000
flags = 1
flags = 0
data = length 0, hash 1
sample 88:
time = 7300000
flags = 1
flags = 0
data = length 0, hash 1
sample 89:
time = 7400000
flags = 1
flags = 0
data = length 0, hash 1
sample 90:
time = 7500000
flags = 1
flags = 0
data = length 0, hash 1
sample 91:
time = 7600000
flags = 1
flags = 0
data = length 0, hash 1
sample 92:
time = 7700000
flags = 1
flags = 0
data = length 0, hash 1
sample 93:
time = 7800000
flags = 1
flags = 0
data = length 0, hash 1
sample 94:
time = 7900000
flags = 1
flags = 0
data = length 0, hash 1
sample 95:
time = 8000000
flags = 1
flags = 0
data = length 3, hash FFFED733
tracksEnded = true

View File

@ -16,382 +16,382 @@ track 0:
data = length 7, hash C95FA520
sample 1:
time = 0
flags = 1
flags = 0
data = length 5, hash 1CF3DA7
sample 2:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFED75B
sample 3:
time = 100000
flags = 1
flags = 0
data = length 0, hash 1
sample 4:
time = 200000
flags = 1
flags = 0
data = length 0, hash 1
sample 5:
time = 300000
flags = 1
flags = 0
data = length 0, hash 1
sample 6:
time = 400000
flags = 1
flags = 0
data = length 0, hash 1
sample 7:
time = 500000
flags = 1
flags = 0
data = length 3, hash FFFED733
sample 8:
time = 500000
flags = 1
flags = 0
data = length 3, hash FFFED751
sample 9:
time = 600000
flags = 1
flags = 0
data = length 0, hash 1
sample 10:
time = 700000
flags = 1
flags = 0
data = length 0, hash 1
sample 11:
time = 800000
flags = 1
flags = 0
data = length 0, hash 1
sample 12:
time = 900000
flags = 1
flags = 0
data = length 0, hash 1
sample 13:
time = 1000000
flags = 1
flags = 0
data = length 3, hash FFFED733
sample 14:
time = 1000000
flags = 1
flags = 0
data = length 3, hash FFFED839
sample 15:
time = 1100000
flags = 1
flags = 0
data = length 0, hash 1
sample 16:
time = 1200000
flags = 1
flags = 0
data = length 0, hash 1
sample 17:
time = 1300000
flags = 1
flags = 0
data = length 0, hash 1
sample 18:
time = 1400000
flags = 1
flags = 0
data = length 0, hash 1
sample 19:
time = 1500000
flags = 1
flags = 0
data = length 3, hash FFFED80C
sample 20:
time = 1500000
flags = 1
flags = 0
data = length 3, hash FFFED83E
sample 21:
time = 1600000
flags = 1
flags = 0
data = length 0, hash 1
sample 22:
time = 1700000
flags = 1
flags = 0
data = length 0, hash 1
sample 23:
time = 1800000
flags = 1
flags = 0
data = length 0, hash 1
sample 24:
time = 1900000
flags = 1
flags = 0
data = length 0, hash 1
sample 25:
time = 2000000
flags = 1
flags = 0
data = length 3, hash FFFED80C
sample 26:
time = 2000000
flags = 1
flags = 0
data = length 3, hash FFFED877
sample 27:
time = 2100000
flags = 1
flags = 0
data = length 0, hash 1
sample 28:
time = 2200000
flags = 1
flags = 0
data = length 0, hash 1
sample 29:
time = 2300000
flags = 1
flags = 0
data = length 0, hash 1
sample 30:
time = 2400000
flags = 1
flags = 0
data = length 0, hash 1
sample 31:
time = 2500000
flags = 1
flags = 0
data = length 3, hash FFFED84A
sample 32:
time = 2500000
flags = 1
flags = 0
data = length 3, hash FFFED87C
sample 33:
time = 2600000
flags = 1
flags = 0
data = length 0, hash 1
sample 34:
time = 2700000
flags = 1
flags = 0
data = length 0, hash 1
sample 35:
time = 2800000
flags = 1
flags = 0
data = length 0, hash 1
sample 36:
time = 2900000
flags = 1
flags = 0
data = length 0, hash 1
sample 37:
time = 3000000
flags = 1
flags = 0
data = length 3, hash FFFED84A
sample 38:
time = 3000000
flags = 1
flags = 0
data = length 3, hash FFFED82F
sample 39:
time = 3100000
flags = 1
flags = 0
data = length 0, hash 1
sample 40:
time = 3200000
flags = 1
flags = 0
data = length 0, hash 1
sample 41:
time = 3300000
flags = 1
flags = 0
data = length 0, hash 1
sample 42:
time = 3400000
flags = 1
flags = 0
data = length 0, hash 1
sample 43:
time = 3500000
flags = 1
flags = 0
data = length 0, hash 1
sample 44:
time = 3600000
flags = 1
flags = 0
data = length 0, hash 1
sample 45:
time = 3700000
flags = 1
flags = 0
data = length 0, hash 1
sample 46:
time = 3800000
flags = 1
flags = 0
data = length 0, hash 1
sample 47:
time = 3900000
flags = 1
flags = 0
data = length 0, hash 1
sample 48:
time = 4000000
flags = 1
flags = 0
data = length 3, hash FFFED80C
sample 49:
time = 4000000
flags = 1
flags = 0
data = length 3, hash FFFED800
sample 50:
time = 4100000
flags = 1
flags = 0
data = length 0, hash 1
sample 51:
time = 4200000
flags = 1
flags = 0
data = length 0, hash 1
sample 52:
time = 4300000
flags = 1
flags = 0
data = length 0, hash 1
sample 53:
time = 4400000
flags = 1
flags = 0
data = length 0, hash 1
sample 54:
time = 4500000
flags = 1
flags = 0
data = length 3, hash FFFED7CE
sample 55:
time = 4500000
flags = 1
flags = 0
data = length 3, hash FFFED7FB
sample 56:
time = 4600000
flags = 1
flags = 0
data = length 0, hash 1
sample 57:
time = 4700000
flags = 1
flags = 0
data = length 0, hash 1
sample 58:
time = 4800000
flags = 1
flags = 0
data = length 0, hash 1
sample 59:
time = 4900000
flags = 1
flags = 0
data = length 0, hash 1
sample 60:
time = 5000000
flags = 1
flags = 0
data = length 3, hash FFFED7CE
sample 61:
time = 5000000
flags = 1
flags = 0
data = length 3, hash FFFED7E1
sample 62:
time = 5100000
flags = 1
flags = 0
data = length 0, hash 1
sample 63:
time = 5200000
flags = 1
flags = 0
data = length 0, hash 1
sample 64:
time = 5250000
flags = 1
flags = 0
data = length 3, hash FFFED7AF
sample 65:
time = 5350000
flags = 1
flags = 0
data = length 0, hash 1
sample 66:
time = 5450000
flags = 1
flags = 0
data = length 0, hash 1
sample 67:
time = 5500000
flags = 1
flags = 0
data = length 3, hash FFFED7D7
sample 68:
time = 5600000
flags = 1
flags = 0
data = length 0, hash 1
sample 69:
time = 5700000
flags = 1
flags = 0
data = length 0, hash 1
sample 70:
time = 5750000
flags = 1
flags = 0
data = length 3, hash FFFED7AF
sample 71:
time = 5850000
flags = 1
flags = 0
data = length 0, hash 1
sample 72:
time = 5950000
flags = 1
flags = 0
data = length 0, hash 1
sample 73:
time = 6000000
flags = 1
flags = 0
data = length 3, hash FFFED79E
sample 74:
time = 6100000
flags = 1
flags = 0
data = length 0, hash 1
sample 75:
time = 6200000
flags = 1
flags = 0
data = length 0, hash 1
sample 76:
time = 6250000
flags = 1
flags = 0
data = length 3, hash FFFED771
sample 77:
time = 6350000
flags = 1
flags = 0
data = length 0, hash 1
sample 78:
time = 6450000
flags = 1
flags = 0
data = length 0, hash 1
sample 79:
time = 6500000
flags = 1
flags = 0
data = length 3, hash FFFED7A3
sample 80:
time = 6600000
flags = 1
flags = 0
data = length 0, hash 1
sample 81:
time = 6700000
flags = 1
flags = 0
data = length 0, hash 1
sample 82:
time = 6750000
flags = 1
flags = 0
data = length 3, hash FFFED771
sample 83:
time = 6850000
flags = 1
flags = 0
data = length 0, hash 1
sample 84:
time = 6950000
flags = 1
flags = 0
data = length 0, hash 1
sample 85:
time = 7000000
flags = 1
flags = 0
data = length 3, hash FFFED751
sample 86:
time = 7100000
flags = 1
flags = 0
data = length 0, hash 1
sample 87:
time = 7200000
flags = 1
flags = 0
data = length 0, hash 1
sample 88:
time = 7300000
flags = 1
flags = 0
data = length 0, hash 1
sample 89:
time = 7400000
flags = 1
flags = 0
data = length 0, hash 1
sample 90:
time = 7500000
flags = 1
flags = 0
data = length 0, hash 1
sample 91:
time = 7600000
flags = 1
flags = 0
data = length 0, hash 1
sample 92:
time = 7700000
flags = 1
flags = 0
data = length 0, hash 1
sample 93:
time = 7800000
flags = 1
flags = 0
data = length 0, hash 1
sample 94:
time = 7900000
flags = 1
flags = 0
data = length 0, hash 1
sample 95:
time = 8000000
flags = 1
flags = 0
data = length 3, hash FFFED733
tracksEnded = true

View File

@ -16,74 +16,74 @@ track 0:
data = length 3, hash 70FB
sample 1:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFEDCE7
sample 2:
time = 0
flags = 1
flags = 0
data = length 7, hash C95FA238
sample 3:
time = 0
flags = 1
flags = 0
data = length 6, hash 37A83E76
sample 4:
time = 100000
flags = 1
flags = 0
data = length 0, hash 1
sample 5:
time = 200000
flags = 1
flags = 0
data = length 0, hash 1
sample 6:
time = 300000
flags = 1
flags = 0
data = length 0, hash 1
sample 7:
time = 400000
flags = 1
flags = 0
data = length 0, hash 1
sample 8:
time = 500000
flags = 1
flags = 0
data = length 6, hash 37A84514
sample 9:
time = 600000
flags = 1
flags = 0
data = length 0, hash 1
sample 10:
time = 700000
flags = 1
flags = 0
data = length 0, hash 1
sample 11:
time = 800000
flags = 1
flags = 0
data = length 0, hash 1
sample 12:
time = 833333
flags = 1
flags = 0
data = length 6, hash 37A83493
sample 13:
time = 933333
flags = 1
flags = 0
data = length 0, hash 1
sample 14:
time = 1033333
flags = 1
flags = 0
data = length 0, hash 1
sample 15:
time = 1083333
flags = 1
flags = 0
data = length 6, hash 37A83CA6
sample 16:
time = 1183333
flags = 1
flags = 0
data = length 0, hash 1
sample 17:
time = 1283333
flags = 1
flags = 0
data = length 3, hash FFFEA058
sample 18:
time = 1283333
flags = 1
flags = 0
data = length 3, hash FFFF4CA9
tracksEnded = true

View File

@ -16,122 +16,122 @@ track 0:
data = length 3, hash 70FB
sample 1:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFF5A77
sample 2:
time = 0
flags = 1
flags = 0
data = length 7, hash C95FA238
sample 3:
time = 0
flags = 1
flags = 0
data = length 3, hash 70FB
sample 4:
time = 0
flags = 1
flags = 0
data = length 6, hash 37A83E76
sample 5:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFF4D46
sample 6:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFF4D0D
sample 7:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFF4DA4
sample 8:
time = 0
flags = 1
flags = 0
data = length 3, hash 40
sample 9:
time = 0
flags = 1
flags = 0
data = length 2, hash FFFFFC20
sample 10:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFEDCE7
sample 11:
time = 100000
flags = 1
flags = 0
data = length 0, hash 1
sample 12:
time = 200000
flags = 1
flags = 0
data = length 0, hash 1
sample 13:
time = 300000
flags = 1
flags = 0
data = length 0, hash 1
sample 14:
time = 400000
flags = 1
flags = 0
data = length 0, hash 1
sample 15:
time = 500000
flags = 1
flags = 0
data = length 6, hash 37A84514
sample 16:
time = 500000
flags = 1
flags = 0
data = length 3, hash FFFEDD63
sample 17:
time = 600000
flags = 1
flags = 0
data = length 0, hash 1
sample 18:
time = 700000
flags = 1
flags = 0
data = length 0, hash 1
sample 19:
time = 800000
flags = 1
flags = 0
data = length 0, hash 1
sample 20:
time = 833333
flags = 1
flags = 0
data = length 3, hash FFFEA0D4
sample 21:
time = 833333
flags = 1
flags = 0
data = length 6, hash 37A83493
sample 22:
time = 833333
flags = 1
flags = 0
data = length 3, hash FFFEDDC0
sample 23:
time = 933333
flags = 1
flags = 0
data = length 0, hash 1
sample 24:
time = 1033333
flags = 1
flags = 0
data = length 0, hash 1
sample 25:
time = 1083333
flags = 1
flags = 0
data = length 6, hash 37A83CA6
sample 26:
time = 1083333
flags = 1
flags = 0
data = length 3, hash FFFEA131
sample 27:
time = 1083333
flags = 1
flags = 0
data = length 3, hash FFFEDE1D
sample 28:
time = 1183333
flags = 1
flags = 0
data = length 0, hash 1
sample 29:
time = 1283333
flags = 1
flags = 0
data = length 3, hash FFFEA058
sample 30:
time = 1283333
flags = 1
flags = 0
data = length 3, hash FFFEA18E
tracksEnded = true

View File

@ -16,90 +16,90 @@ track 0:
data = length 3, hash 70FB
sample 1:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFF56B6
sample 2:
time = 0
flags = 1
flags = 0
data = length 7, hash C95FA238
sample 3:
time = 0
flags = 1
flags = 0
data = length 3, hash FFFF494C
sample 4:
time = 0
flags = 1
flags = 0
data = length 6, hash 37A83E76
sample 5:
time = 4999999
flags = 1
flags = 0
data = length 3, hash 8DE
sample 6:
time = 5500000
flags = 1
flags = 0
data = length 0, hash 1
sample 7:
time = 5600000
flags = 1
flags = 0
data = length 0, hash 1
sample 8:
time = 5700000
flags = 1
flags = 0
data = length 0, hash 1
sample 9:
time = 5800000
flags = 1
flags = 0
data = length 0, hash 1
sample 10:
time = 5900000
flags = 1
flags = 0
data = length 0, hash 1
sample 11:
time = 5999999
flags = 1
flags = 0
data = length 3, hash FFFED7B2
sample 12:
time = 6099999
flags = 1
flags = 0
data = length 0, hash 1
sample 13:
time = 6199999
flags = 1
flags = 0
data = length 0, hash 1
sample 14:
time = 6299999
flags = 1
flags = 0
data = length 0, hash 1
sample 15:
time = 6399999
flags = 1
flags = 0
data = length 0, hash 1
sample 16:
time = 6499999
flags = 1
flags = 0
data = length 0, hash 1
sample 17:
time = 6599999
flags = 1
flags = 0
data = length 0, hash 1
sample 18:
time = 6699999
flags = 1
flags = 0
data = length 0, hash 1
sample 19:
time = 6799999
flags = 1
flags = 0
data = length 0, hash 1
sample 20:
time = 6899999
flags = 1
flags = 0
data = length 0, hash 1
sample 21:
time = 6999999
flags = 1
flags = 0
data = length 0, hash 1
sample 22:
time = 7041665
flags = 1
flags = 0
data = length 3, hash FFFE9B23
tracksEnded = true