Merge pull request #7378 from shenwill:dev-v2

PiperOrigin-RevId: 336875300
This commit is contained in:
kim-vde 2020-10-13 16:30:01 +01:00
commit 2e5f2f12ad
13 changed files with 1366 additions and 7 deletions

View File

@ -55,6 +55,8 @@
([#7988](https://github.com/google/ExoPlayer/issues/7988)).
* Ignore negative payload size in PES packets
([#8005](https://github.com/google/ExoPlayer/issues/8005)).
* Make FLV files seekable by using the key frame index
([#7378](https://github.com/google/ExoPlayer/issues/7378)).
* HLS:
* Fix crash affecting chunkful preparation of master playlists that start
with an I-FRAME only variant

View File

@ -0,0 +1,85 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.extractor;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Util;
/**
* A {@link SeekMap} implementation based on a mapping between times and positions in the input
* stream.
*/
public final class IndexSeekMap implements SeekMap {
private final long[] positions;
private final long[] timesUs;
private final long durationUs;
private final boolean isSeekable;
/**
* Creates an instance.
*
* @param positions The positions in the stream corresponding to {@code timesUs}, in bytes.
* @param timesUs The times corresponding to {@code positions}, in microseconds.
* @param durationUs The duration of the input stream, or {@link C#TIME_UNSET} if it is unknown.
*/
public IndexSeekMap(long[] positions, long[] timesUs, long durationUs) {
checkArgument(positions.length == timesUs.length);
int length = timesUs.length;
isSeekable = length > 0;
if (isSeekable && timesUs[0] > 0) {
// Add (position = 0, timeUs = 0) as first entry.
this.positions = new long[length + 1];
this.timesUs = new long[length + 1];
System.arraycopy(positions, 0, this.positions, 1, length);
System.arraycopy(timesUs, 0, this.timesUs, 1, length);
} else {
this.positions = positions;
this.timesUs = timesUs;
}
this.durationUs = durationUs;
}
@Override
public boolean isSeekable() {
return isSeekable;
}
@Override
public long getDurationUs() {
return durationUs;
}
@Override
public SeekMap.SeekPoints getSeekPoints(long timeUs) {
if (!isSeekable) {
return new SeekMap.SeekPoints(SeekPoint.START);
}
int targetIndex =
Util.binarySearchFloor(timesUs, timeUs, /* inclusive= */ true, /* stayInBounds= */ true);
SeekPoint leftSeekPoint = new SeekPoint(timesUs[targetIndex], positions[targetIndex]);
if (leftSeekPoint.timeUs >= timeUs || targetIndex == timesUs.length - 1) {
return new SeekMap.SeekPoints(leftSeekPoint);
} else {
SeekPoint rightSeekPoint =
new SeekPoint(timesUs[targetIndex + 1], positions[targetIndex + 1]);
return new SeekMap.SeekPoints(leftSeekPoint, rightSeekPoint);
}
}
}

View File

@ -23,6 +23,7 @@ import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.extractor.IndexSeekMap;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.util.Assertions;
@ -135,8 +136,12 @@ public final class FlvExtractor implements Extractor {
@Override
public void seek(long position, long timeUs) {
state = STATE_READING_FLV_HEADER;
outputFirstSample = false;
if (position == 0) {
state = STATE_READING_FLV_HEADER;
outputFirstSample = false;
} else {
state = STATE_READING_TAG_HEADER;
}
bytesToNextTagHeader = 0;
}
@ -267,7 +272,11 @@ public final class FlvExtractor implements Extractor {
wasSampleOutput = metadataReader.consume(prepareTagData(input), timestampUs);
long durationUs = metadataReader.getDurationUs();
if (durationUs != C.TIME_UNSET) {
extractorOutput.seekMap(new SeekMap.Unseekable(durationUs));
extractorOutput.seekMap(
new IndexSeekMap(
metadataReader.getKeyFrameTagPositions(),
metadataReader.getKeyFrameTimesUs(),
durationUs));
outputSeekMap = true;
}
} else {

View File

@ -22,6 +22,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -31,6 +32,9 @@ import java.util.Map;
private static final String NAME_METADATA = "onMetaData";
private static final String KEY_DURATION = "duration";
private static final String KEY_KEY_FRAMES = "keyframes";
private static final String KEY_FILE_POSITIONS = "filepositions";
private static final String KEY_TIMES = "times";
// AMF object types
private static final int AMF_TYPE_NUMBER = 0;
@ -43,16 +47,28 @@ import java.util.Map;
private static final int AMF_TYPE_DATE = 11;
private long durationUs;
private long[] keyFrameTimesUs;
private long[] keyFrameTagPositions;
public ScriptTagPayloadReader() {
super(new DummyTrackOutput());
durationUs = C.TIME_UNSET;
keyFrameTimesUs = new long[0];
keyFrameTagPositions = new long[0];
}
public long getDurationUs() {
return durationUs;
}
public long[] getKeyFrameTimesUs() {
return keyFrameTimesUs;
}
public long[] getKeyFrameTagPositions() {
return keyFrameTagPositions;
}
@Override
public void seek() {
// Do nothing.
@ -80,14 +96,41 @@ import java.util.Map;
// We're not interested in this metadata.
return false;
}
// Set the duration to the value contained in the metadata, if present.
Map<String, Object> metadata = readAmfEcmaArray(data);
if (metadata.containsKey(KEY_DURATION)) {
double durationSeconds = (double) metadata.get(KEY_DURATION);
// Set the duration to the value contained in the metadata, if present.
@Nullable Object durationSecondsObj = metadata.get(KEY_DURATION);
if (durationSecondsObj instanceof Double) {
double durationSeconds = (double) durationSecondsObj;
if (durationSeconds > 0.0) {
durationUs = (long) (durationSeconds * C.MICROS_PER_SECOND);
}
}
// Set the key frame times and positions to the value contained in the metadata, if present.
@Nullable Object keyFramesObj = metadata.get(KEY_KEY_FRAMES);
if (keyFramesObj instanceof Map) {
Map<?, ?> keyFrames = (Map<?, ?>) keyFramesObj;
@Nullable Object positionsObj = keyFrames.get(KEY_FILE_POSITIONS);
@Nullable Object timesSecondsObj = keyFrames.get(KEY_TIMES);
if (positionsObj instanceof List && timesSecondsObj instanceof List) {
List<?> positions = (List<?>) positionsObj;
List<?> timesSeconds = (List<?>) timesSecondsObj;
int keyFrameCount = timesSeconds.size();
keyFrameTimesUs = new long[keyFrameCount];
keyFrameTagPositions = new long[keyFrameCount];
for (int i = 0; i < keyFrameCount; i++) {
Object positionObj = positions.get(i);
Object timeSecondsObj = timesSeconds.get(i);
if (timeSecondsObj instanceof Double && positionObj instanceof Double) {
keyFrameTimesUs[i] = (long) (((Double) timeSecondsObj) * C.MICROS_PER_SECOND);
keyFrameTagPositions[i] = ((Double) positionObj).longValue();
} else {
keyFrameTimesUs = new long[0];
keyFrameTagPositions = new long[0];
break;
}
}
}
}
return false;
}

View File

@ -70,7 +70,7 @@ import com.google.android.exoplayer2.util.Util;
int targetIndex =
Util.binarySearchFloor(timesUs, timeUs, /* inclusive= */ true, /* stayInBounds= */ true);
SeekPoint seekPoint = new SeekPoint(timesUs.get(targetIndex), positions.get(targetIndex));
if (seekPoint.timeUs >= timeUs || targetIndex == timesUs.size() - 1) {
if (seekPoint.timeUs == timeUs || targetIndex == timesUs.size() - 1) {
return new SeekPoints(seekPoint);
} else {
SeekPoint nextSeekPoint =

View File

@ -0,0 +1,179 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.extractor.flv;
import static com.google.android.exoplayer2.testutil.TestUtil.extractAllSamplesFromFile;
import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.testutil.FakeExtractorOutput;
import com.google.android.exoplayer2.testutil.FakeTrackOutput;
import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.upstream.DefaultDataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Seeking tests for {@link FlvExtractor}. */
@RunWith(AndroidJUnit4.class)
public class FlvExtractorSeekTest {
private static final String TEST_FILE_KEY_FRAME_INDEX =
"media/flv/sample-with-key-frame-index.flv";
private static final long DURATION_US = 3_042_000;
private static final long KEY_FRAMES_INTERVAL_US = C.MICROS_PER_SECOND;
private FlvExtractor extractor;
private FakeExtractorOutput extractorOutput;
private DefaultDataSource dataSource;
@Before
public void setUp() throws Exception {
extractor = new FlvExtractor();
extractorOutput = new FakeExtractorOutput();
dataSource =
new DefaultDataSourceFactory(ApplicationProvider.getApplicationContext())
.createDataSource();
}
@Test
public void flvExtractorReads_returnsSeekableSeekMap() throws Exception {
Uri fileUri = TestUtil.buildAssetUri(TEST_FILE_KEY_FRAME_INDEX);
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
assertThat(seekMap.getDurationUs()).isEqualTo(DURATION_US);
assertThat(seekMap.isSeekable()).isTrue();
}
@Test
public void seeking_handlesSeekToZero() throws Exception {
String fileName = TEST_FILE_KEY_FRAME_INDEX;
Uri fileUri = TestUtil.buildAssetUri(fileName);
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
int trackId = extractorOutput.trackOutputs.keyAt(0);
FakeTrackOutput trackOutput = extractorOutput.trackOutputs.get(trackId);
long targetSeekTimeUs = 0;
int extractedFrameIndex =
TestUtil.seekToTimeUs(
extractor, seekMap, targetSeekTimeUs, dataSource, trackOutput, fileUri);
assertThat(extractedFrameIndex).isNotEqualTo(C.INDEX_UNSET);
assertFirstFrameAfterSeekIsWithinKeyFrameInterval(
fileName, trackId, trackOutput, extractedFrameIndex, targetSeekTimeUs);
}
@Test
public void seeking_handlesSeekToEof() throws Exception {
String fileName = TEST_FILE_KEY_FRAME_INDEX;
Uri fileUri = TestUtil.buildAssetUri(fileName);
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
int trackId = extractorOutput.trackOutputs.keyAt(0);
FakeTrackOutput trackOutput = extractorOutput.trackOutputs.get(trackId);
long targetSeekTimeUs = seekMap.getDurationUs();
int extractedFrameIndex =
TestUtil.seekToTimeUs(
extractor, seekMap, targetSeekTimeUs, dataSource, trackOutput, fileUri);
assertThat(extractedFrameIndex).isNotEqualTo(C.INDEX_UNSET);
assertFirstFrameAfterSeekIsWithinKeyFrameInterval(
fileName, trackId, trackOutput, extractedFrameIndex, targetSeekTimeUs);
}
@Test
public void seeking_handlesSeekingBackward() throws Exception {
String fileName = TEST_FILE_KEY_FRAME_INDEX;
Uri fileUri = TestUtil.buildAssetUri(fileName);
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
int trackId = extractorOutput.trackOutputs.keyAt(0);
FakeTrackOutput trackOutput = extractorOutput.trackOutputs.get(trackId);
long firstSeekTimeUs = seekMap.getDurationUs() * 2 / 3;
TestUtil.seekToTimeUs(extractor, seekMap, firstSeekTimeUs, dataSource, trackOutput, fileUri);
long targetSeekTimeUs = seekMap.getDurationUs() / 3;
int extractedFrameIndex =
TestUtil.seekToTimeUs(
extractor, seekMap, targetSeekTimeUs, dataSource, trackOutput, fileUri);
assertThat(extractedFrameIndex).isNotEqualTo(C.INDEX_UNSET);
assertFirstFrameAfterSeekIsWithinKeyFrameInterval(
fileName, trackId, trackOutput, extractedFrameIndex, targetSeekTimeUs);
}
@Test
public void seeking_handlesSeekingForward() throws Exception {
String fileName = TEST_FILE_KEY_FRAME_INDEX;
Uri fileUri = TestUtil.buildAssetUri(fileName);
SeekMap seekMap = TestUtil.extractSeekMap(extractor, extractorOutput, dataSource, fileUri);
int trackId = extractorOutput.trackOutputs.keyAt(0);
FakeTrackOutput trackOutput = extractorOutput.trackOutputs.get(trackId);
long firstSeekTimeUs = seekMap.getDurationUs() / 3;
TestUtil.seekToTimeUs(extractor, seekMap, firstSeekTimeUs, dataSource, trackOutput, fileUri);
long targetSeekTimeUs = seekMap.getDurationUs() * 2 / 3;
int extractedFrameIndex =
TestUtil.seekToTimeUs(
extractor, seekMap, targetSeekTimeUs, dataSource, trackOutput, fileUri);
assertThat(extractedFrameIndex).isNotEqualTo(C.INDEX_UNSET);
assertFirstFrameAfterSeekIsWithinKeyFrameInterval(
fileName, trackId, trackOutput, extractedFrameIndex, targetSeekTimeUs);
}
private static void assertFirstFrameAfterSeekIsWithinKeyFrameInterval(
String fileName,
int trackId,
FakeTrackOutput trackOutput,
int firstFrameIndexAfterSeek,
long targetSeekTimeUs)
throws IOException {
long foundFrameTimeUs = trackOutput.getSampleTimeUs(firstFrameIndexAfterSeek);
assertThat(targetSeekTimeUs - foundFrameTimeUs).isAtMost(KEY_FRAMES_INTERVAL_US);
FakeTrackOutput expectedTrackOutput = getTrackOutput(fileName, trackId);
int foundFrameIndex = getFrameIndex(expectedTrackOutput, foundFrameTimeUs);
trackOutput.assertSample(
firstFrameIndexAfterSeek,
expectedTrackOutput.getSampleData(foundFrameIndex),
expectedTrackOutput.getSampleTimeUs(foundFrameIndex),
expectedTrackOutput.getSampleFlags(foundFrameIndex),
expectedTrackOutput.getSampleCryptoData(foundFrameIndex));
}
private static FakeTrackOutput getTrackOutput(String fileName, int trackId) throws IOException {
return extractAllSamplesFromFile(
new FlvExtractor(), ApplicationProvider.getApplicationContext(), fileName)
.trackOutputs
.get(trackId);
}
private static int getFrameIndex(FakeTrackOutput trackOutput, long targetSeekTimeUs) {
List<Long> frameTimes = trackOutput.getSampleTimesUs();
return Util.binarySearchFloor(
frameTimes, targetSeekTimeUs, /* inclusive= */ true, /* stayInBounds= */ false);
}
}

View File

@ -38,4 +38,10 @@ public final class FlvExtractorTest {
public void sample() throws Exception {
ExtractorAsserts.assertBehavior(FlvExtractor::new, "media/flv/sample.flv", simulationConfig);
}
@Test
public void sampleSeekable() throws Exception {
ExtractorAsserts.assertBehavior(
FlvExtractor::new, "media/flv/sample-with-key-frame-index.flv", simulationConfig);
}
}

View File

@ -0,0 +1,303 @@
seekMap:
isSeekable = true
duration = 3042000
getPosition(0) = [[timeUs=0, position=788]]
getPosition(1) = [[timeUs=0, position=788], [timeUs=1000000, position=6537]]
getPosition(1521000) = [[timeUs=1000000, position=6537], [timeUs=2000000, position=17543]]
getPosition(3042000) = [[timeUs=2000000, position=17543]]
numberOfTracks = 1
track 9:
total output bytes = 28759
sample count = 71
format 0:
sampleMimeType = video/avc
width = 320
height = 180
initializationData:
data = length 30, hash 962338CC
data = length 10, hash 7A0D0F2B
sample 0:
time = 84000
flags = 1
data = length 747, hash 59AEB08
sample 1:
time = 250000
flags = 0
data = length 117, hash 57A315CB
sample 2:
time = 167000
flags = 0
data = length 16, hash 7E8FA845
sample 3:
time = 125000
flags = 0
data = length 13, hash 7AEB9BE0
sample 4:
time = 209000
flags = 0
data = length 16, hash 644DA4CC
sample 5:
time = 334000
flags = 0
data = length 200, hash E5BF3A39
sample 6:
time = 292000
flags = 0
data = length 167, hash 74FCA726
sample 7:
time = 375000
flags = 0
data = length 134, hash 3B12FEC0
sample 8:
time = 459000
flags = 0
data = length 264, hash 7D9323C7
sample 9:
time = 417000
flags = 0
data = length 141, hash B5AAF09F
sample 10:
time = 500000
flags = 0
data = length 229, hash 181AD475
sample 11:
time = 625000
flags = 0
data = length 279, hash 11A95D98
sample 12:
time = 542000
flags = 0
data = length 39, hash 6F87AFD9
sample 13:
time = 584000
flags = 0
data = length 88, hash 6E7EC1EF
sample 14:
time = 750000
flags = 0
data = length 481, hash 82246706
sample 15:
time = 667000
flags = 0
data = length 103, hash A201C852
sample 16:
time = 709000
flags = 0
data = length 85, hash 7D6F33C4
sample 17:
time = 875000
flags = 0
data = length 659, hash 3BF583EF
sample 18:
time = 792000
flags = 0
data = length 134, hash 46C97FD9
sample 19:
time = 834000
flags = 0
data = length 153, hash 5E737D26
sample 20:
time = 1000000
flags = 0
data = length 652, hash E3151CCE
sample 21:
time = 917000
flags = 0
data = length 86, hash A1884AD8
sample 22:
time = 959000
flags = 0
data = length 150, hash 6C7DEF31
sample 23:
time = 1042000
flags = 0
data = length 316, hash E7867
sample 24:
time = 1084000
flags = 1
data = length 1950, hash 28E6760E
sample 25:
time = 1250000
flags = 0
data = length 561, hash 8394BDB5
sample 26:
time = 1167000
flags = 0
data = length 130, hash B50D0F26
sample 27:
time = 1125000
flags = 0
data = length 185, hash 359FC134
sample 28:
time = 1209000
flags = 0
data = length 130, hash C53797EC
sample 29:
time = 1417000
flags = 0
data = length 867, hash B87AD770
sample 30:
time = 1334000
flags = 0
data = length 155, hash 73B4B0E7
sample 31:
time = 1292000
flags = 0
data = length 168, hash 9C9C9994
sample 32:
time = 1375000
flags = 0
data = length 145, hash 2D3F2527
sample 33:
time = 1584000
flags = 0
data = length 991, hash 78143488
sample 34:
time = 1500000
flags = 0
data = length 174, hash 6C778CE7
sample 35:
time = 1459000
flags = 0
data = length 82, hash D605F20D
sample 36:
time = 1542000
flags = 0
data = length 125, hash 248E8190
sample 37:
time = 1750000
flags = 0
data = length 1095, hash 21B08B6C
sample 38:
time = 1667000
flags = 0
data = length 238, hash AE5854DF
sample 39:
time = 1625000
flags = 0
data = length 151, hash DF20C082
sample 40:
time = 1709000
flags = 0
data = length 45, hash 35165468
sample 41:
time = 1875000
flags = 0
data = length 1425, hash D20DA4F0
sample 42:
time = 1792000
flags = 0
data = length 67, hash 49E25397
sample 43:
time = 1834000
flags = 0
data = length 72, hash EEDD2F83
sample 44:
time = 2042000
flags = 0
data = length 1382, hash 6C35D237
sample 45:
time = 1959000
flags = 0
data = length 186, hash CDE97917
sample 46:
time = 1917000
flags = 0
data = length 80, hash 923EC2C
sample 47:
time = 2000000
flags = 0
data = length 122, hash EB3EEF54
sample 48:
time = 2084000
flags = 1
data = length 4380, hash 9221E054
sample 49:
time = 2167000
flags = 0
data = length 819, hash 46A722D6
sample 50:
time = 2125000
flags = 0
data = length 140, hash E9AA6D8B
sample 51:
time = 2250000
flags = 0
data = length 711, hash C49CB26
sample 52:
time = 2209000
flags = 0
data = length 111, hash A53830B7
sample 53:
time = 2417000
flags = 0
data = length 1062, hash B95BF284
sample 54:
time = 2334000
flags = 0
data = length 312, hash 1C667DA3
sample 55:
time = 2292000
flags = 0
data = length 132, hash 59C0F906
sample 56:
time = 2375000
flags = 0
data = length 149, hash B7F8F4A5
sample 57:
time = 2584000
flags = 0
data = length 1040, hash 82D4CCFD
sample 58:
time = 2500000
flags = 0
data = length 349, hash C1236BA4
sample 59:
time = 2459000
flags = 0
data = length 140, hash 67015D1B
sample 60:
time = 2542000
flags = 0
data = length 186, hash C0DF4AB0
sample 61:
time = 2750000
flags = 0
data = length 811, hash EEA6FBFF
sample 62:
time = 2667000
flags = 0
data = length 356, hash A9847C12
sample 63:
time = 2625000
flags = 0
data = length 156, hash 61E72801
sample 64:
time = 2709000
flags = 0
data = length 212, hash F1F7EBE8
sample 65:
time = 2917000
flags = 0
data = length 681, hash FA95355F
sample 66:
time = 2834000
flags = 0
data = length 351, hash F771D4DD
sample 67:
time = 2792000
flags = 0
data = length 174, hash 325A7512
sample 68:
time = 2875000
flags = 0
data = length 199, hash A22FAA40
sample 69:
time = 3000000
flags = 0
data = length 322, hash C494E5A7
sample 70:
time = 2959000
flags = 0
data = length 171, hash 2DA9ECEC
tracksEnded = true

View File

@ -0,0 +1,207 @@
seekMap:
isSeekable = true
duration = 3042000
getPosition(0) = [[timeUs=0, position=788]]
getPosition(1) = [[timeUs=0, position=788], [timeUs=1000000, position=6537]]
getPosition(1521000) = [[timeUs=1000000, position=6537], [timeUs=2000000, position=17543]]
getPosition(3042000) = [[timeUs=2000000, position=17543]]
numberOfTracks = 1
track 9:
total output bytes = 23490
sample count = 47
format 0:
sampleMimeType = video/avc
width = 320
height = 180
initializationData:
data = length 30, hash 962338CC
data = length 10, hash 7A0D0F2B
sample 0:
time = 1084000
flags = 1
data = length 1950, hash 28E6760E
sample 1:
time = 1250000
flags = 0
data = length 561, hash 8394BDB5
sample 2:
time = 1167000
flags = 0
data = length 130, hash B50D0F26
sample 3:
time = 1125000
flags = 0
data = length 185, hash 359FC134
sample 4:
time = 1209000
flags = 0
data = length 130, hash C53797EC
sample 5:
time = 1417000
flags = 0
data = length 867, hash B87AD770
sample 6:
time = 1334000
flags = 0
data = length 155, hash 73B4B0E7
sample 7:
time = 1292000
flags = 0
data = length 168, hash 9C9C9994
sample 8:
time = 1375000
flags = 0
data = length 145, hash 2D3F2527
sample 9:
time = 1584000
flags = 0
data = length 991, hash 78143488
sample 10:
time = 1500000
flags = 0
data = length 174, hash 6C778CE7
sample 11:
time = 1459000
flags = 0
data = length 82, hash D605F20D
sample 12:
time = 1542000
flags = 0
data = length 125, hash 248E8190
sample 13:
time = 1750000
flags = 0
data = length 1095, hash 21B08B6C
sample 14:
time = 1667000
flags = 0
data = length 238, hash AE5854DF
sample 15:
time = 1625000
flags = 0
data = length 151, hash DF20C082
sample 16:
time = 1709000
flags = 0
data = length 45, hash 35165468
sample 17:
time = 1875000
flags = 0
data = length 1425, hash D20DA4F0
sample 18:
time = 1792000
flags = 0
data = length 67, hash 49E25397
sample 19:
time = 1834000
flags = 0
data = length 72, hash EEDD2F83
sample 20:
time = 2042000
flags = 0
data = length 1382, hash 6C35D237
sample 21:
time = 1959000
flags = 0
data = length 186, hash CDE97917
sample 22:
time = 1917000
flags = 0
data = length 80, hash 923EC2C
sample 23:
time = 2000000
flags = 0
data = length 122, hash EB3EEF54
sample 24:
time = 2084000
flags = 1
data = length 4380, hash 9221E054
sample 25:
time = 2167000
flags = 0
data = length 819, hash 46A722D6
sample 26:
time = 2125000
flags = 0
data = length 140, hash E9AA6D8B
sample 27:
time = 2250000
flags = 0
data = length 711, hash C49CB26
sample 28:
time = 2209000
flags = 0
data = length 111, hash A53830B7
sample 29:
time = 2417000
flags = 0
data = length 1062, hash B95BF284
sample 30:
time = 2334000
flags = 0
data = length 312, hash 1C667DA3
sample 31:
time = 2292000
flags = 0
data = length 132, hash 59C0F906
sample 32:
time = 2375000
flags = 0
data = length 149, hash B7F8F4A5
sample 33:
time = 2584000
flags = 0
data = length 1040, hash 82D4CCFD
sample 34:
time = 2500000
flags = 0
data = length 349, hash C1236BA4
sample 35:
time = 2459000
flags = 0
data = length 140, hash 67015D1B
sample 36:
time = 2542000
flags = 0
data = length 186, hash C0DF4AB0
sample 37:
time = 2750000
flags = 0
data = length 811, hash EEA6FBFF
sample 38:
time = 2667000
flags = 0
data = length 356, hash A9847C12
sample 39:
time = 2625000
flags = 0
data = length 156, hash 61E72801
sample 40:
time = 2709000
flags = 0
data = length 212, hash F1F7EBE8
sample 41:
time = 2917000
flags = 0
data = length 681, hash FA95355F
sample 42:
time = 2834000
flags = 0
data = length 351, hash F771D4DD
sample 43:
time = 2792000
flags = 0
data = length 174, hash 325A7512
sample 44:
time = 2875000
flags = 0
data = length 199, hash A22FAA40
sample 45:
time = 3000000
flags = 0
data = length 322, hash C494E5A7
sample 46:
time = 2959000
flags = 0
data = length 171, hash 2DA9ECEC
tracksEnded = true

View File

@ -0,0 +1,111 @@
seekMap:
isSeekable = true
duration = 3042000
getPosition(0) = [[timeUs=0, position=788]]
getPosition(1) = [[timeUs=0, position=788], [timeUs=1000000, position=6537]]
getPosition(1521000) = [[timeUs=1000000, position=6537], [timeUs=2000000, position=17543]]
getPosition(3042000) = [[timeUs=2000000, position=17543]]
numberOfTracks = 1
track 9:
total output bytes = 12964
sample count = 23
format 0:
sampleMimeType = video/avc
width = 320
height = 180
initializationData:
data = length 30, hash 962338CC
data = length 10, hash 7A0D0F2B
sample 0:
time = 2084000
flags = 1
data = length 4380, hash 9221E054
sample 1:
time = 2167000
flags = 0
data = length 819, hash 46A722D6
sample 2:
time = 2125000
flags = 0
data = length 140, hash E9AA6D8B
sample 3:
time = 2250000
flags = 0
data = length 711, hash C49CB26
sample 4:
time = 2209000
flags = 0
data = length 111, hash A53830B7
sample 5:
time = 2417000
flags = 0
data = length 1062, hash B95BF284
sample 6:
time = 2334000
flags = 0
data = length 312, hash 1C667DA3
sample 7:
time = 2292000
flags = 0
data = length 132, hash 59C0F906
sample 8:
time = 2375000
flags = 0
data = length 149, hash B7F8F4A5
sample 9:
time = 2584000
flags = 0
data = length 1040, hash 82D4CCFD
sample 10:
time = 2500000
flags = 0
data = length 349, hash C1236BA4
sample 11:
time = 2459000
flags = 0
data = length 140, hash 67015D1B
sample 12:
time = 2542000
flags = 0
data = length 186, hash C0DF4AB0
sample 13:
time = 2750000
flags = 0
data = length 811, hash EEA6FBFF
sample 14:
time = 2667000
flags = 0
data = length 356, hash A9847C12
sample 15:
time = 2625000
flags = 0
data = length 156, hash 61E72801
sample 16:
time = 2709000
flags = 0
data = length 212, hash F1F7EBE8
sample 17:
time = 2917000
flags = 0
data = length 681, hash FA95355F
sample 18:
time = 2834000
flags = 0
data = length 351, hash F771D4DD
sample 19:
time = 2792000
flags = 0
data = length 174, hash 325A7512
sample 20:
time = 2875000
flags = 0
data = length 199, hash A22FAA40
sample 21:
time = 3000000
flags = 0
data = length 322, hash C494E5A7
sample 22:
time = 2959000
flags = 0
data = length 171, hash 2DA9ECEC
tracksEnded = true

View File

@ -0,0 +1,111 @@
seekMap:
isSeekable = true
duration = 3042000
getPosition(0) = [[timeUs=0, position=788]]
getPosition(1) = [[timeUs=0, position=788], [timeUs=1000000, position=6537]]
getPosition(1521000) = [[timeUs=1000000, position=6537], [timeUs=2000000, position=17543]]
getPosition(3042000) = [[timeUs=2000000, position=17543]]
numberOfTracks = 1
track 9:
total output bytes = 12964
sample count = 23
format 0:
sampleMimeType = video/avc
width = 320
height = 180
initializationData:
data = length 30, hash 962338CC
data = length 10, hash 7A0D0F2B
sample 0:
time = 2084000
flags = 1
data = length 4380, hash 9221E054
sample 1:
time = 2167000
flags = 0
data = length 819, hash 46A722D6
sample 2:
time = 2125000
flags = 0
data = length 140, hash E9AA6D8B
sample 3:
time = 2250000
flags = 0
data = length 711, hash C49CB26
sample 4:
time = 2209000
flags = 0
data = length 111, hash A53830B7
sample 5:
time = 2417000
flags = 0
data = length 1062, hash B95BF284
sample 6:
time = 2334000
flags = 0
data = length 312, hash 1C667DA3
sample 7:
time = 2292000
flags = 0
data = length 132, hash 59C0F906
sample 8:
time = 2375000
flags = 0
data = length 149, hash B7F8F4A5
sample 9:
time = 2584000
flags = 0
data = length 1040, hash 82D4CCFD
sample 10:
time = 2500000
flags = 0
data = length 349, hash C1236BA4
sample 11:
time = 2459000
flags = 0
data = length 140, hash 67015D1B
sample 12:
time = 2542000
flags = 0
data = length 186, hash C0DF4AB0
sample 13:
time = 2750000
flags = 0
data = length 811, hash EEA6FBFF
sample 14:
time = 2667000
flags = 0
data = length 356, hash A9847C12
sample 15:
time = 2625000
flags = 0
data = length 156, hash 61E72801
sample 16:
time = 2709000
flags = 0
data = length 212, hash F1F7EBE8
sample 17:
time = 2917000
flags = 0
data = length 681, hash FA95355F
sample 18:
time = 2834000
flags = 0
data = length 351, hash F771D4DD
sample 19:
time = 2792000
flags = 0
data = length 174, hash 325A7512
sample 20:
time = 2875000
flags = 0
data = length 199, hash A22FAA40
sample 21:
time = 3000000
flags = 0
data = length 322, hash C494E5A7
sample 22:
time = 2959000
flags = 0
data = length 171, hash 2DA9ECEC
tracksEnded = true

View File

@ -0,0 +1,303 @@
seekMap:
isSeekable = true
duration = 3042000
getPosition(0) = [[timeUs=0, position=788]]
getPosition(1) = [[timeUs=0, position=788], [timeUs=1000000, position=6537]]
getPosition(1521000) = [[timeUs=1000000, position=6537], [timeUs=2000000, position=17543]]
getPosition(3042000) = [[timeUs=2000000, position=17543]]
numberOfTracks = 1
track 9:
total output bytes = 28759
sample count = 71
format 0:
sampleMimeType = video/avc
width = 320
height = 180
initializationData:
data = length 30, hash 962338CC
data = length 10, hash 7A0D0F2B
sample 0:
time = 84000
flags = 1
data = length 747, hash 59AEB08
sample 1:
time = 250000
flags = 0
data = length 117, hash 57A315CB
sample 2:
time = 167000
flags = 0
data = length 16, hash 7E8FA845
sample 3:
time = 125000
flags = 0
data = length 13, hash 7AEB9BE0
sample 4:
time = 209000
flags = 0
data = length 16, hash 644DA4CC
sample 5:
time = 334000
flags = 0
data = length 200, hash E5BF3A39
sample 6:
time = 292000
flags = 0
data = length 167, hash 74FCA726
sample 7:
time = 375000
flags = 0
data = length 134, hash 3B12FEC0
sample 8:
time = 459000
flags = 0
data = length 264, hash 7D9323C7
sample 9:
time = 417000
flags = 0
data = length 141, hash B5AAF09F
sample 10:
time = 500000
flags = 0
data = length 229, hash 181AD475
sample 11:
time = 625000
flags = 0
data = length 279, hash 11A95D98
sample 12:
time = 542000
flags = 0
data = length 39, hash 6F87AFD9
sample 13:
time = 584000
flags = 0
data = length 88, hash 6E7EC1EF
sample 14:
time = 750000
flags = 0
data = length 481, hash 82246706
sample 15:
time = 667000
flags = 0
data = length 103, hash A201C852
sample 16:
time = 709000
flags = 0
data = length 85, hash 7D6F33C4
sample 17:
time = 875000
flags = 0
data = length 659, hash 3BF583EF
sample 18:
time = 792000
flags = 0
data = length 134, hash 46C97FD9
sample 19:
time = 834000
flags = 0
data = length 153, hash 5E737D26
sample 20:
time = 1000000
flags = 0
data = length 652, hash E3151CCE
sample 21:
time = 917000
flags = 0
data = length 86, hash A1884AD8
sample 22:
time = 959000
flags = 0
data = length 150, hash 6C7DEF31
sample 23:
time = 1042000
flags = 0
data = length 316, hash E7867
sample 24:
time = 1084000
flags = 1
data = length 1950, hash 28E6760E
sample 25:
time = 1250000
flags = 0
data = length 561, hash 8394BDB5
sample 26:
time = 1167000
flags = 0
data = length 130, hash B50D0F26
sample 27:
time = 1125000
flags = 0
data = length 185, hash 359FC134
sample 28:
time = 1209000
flags = 0
data = length 130, hash C53797EC
sample 29:
time = 1417000
flags = 0
data = length 867, hash B87AD770
sample 30:
time = 1334000
flags = 0
data = length 155, hash 73B4B0E7
sample 31:
time = 1292000
flags = 0
data = length 168, hash 9C9C9994
sample 32:
time = 1375000
flags = 0
data = length 145, hash 2D3F2527
sample 33:
time = 1584000
flags = 0
data = length 991, hash 78143488
sample 34:
time = 1500000
flags = 0
data = length 174, hash 6C778CE7
sample 35:
time = 1459000
flags = 0
data = length 82, hash D605F20D
sample 36:
time = 1542000
flags = 0
data = length 125, hash 248E8190
sample 37:
time = 1750000
flags = 0
data = length 1095, hash 21B08B6C
sample 38:
time = 1667000
flags = 0
data = length 238, hash AE5854DF
sample 39:
time = 1625000
flags = 0
data = length 151, hash DF20C082
sample 40:
time = 1709000
flags = 0
data = length 45, hash 35165468
sample 41:
time = 1875000
flags = 0
data = length 1425, hash D20DA4F0
sample 42:
time = 1792000
flags = 0
data = length 67, hash 49E25397
sample 43:
time = 1834000
flags = 0
data = length 72, hash EEDD2F83
sample 44:
time = 2042000
flags = 0
data = length 1382, hash 6C35D237
sample 45:
time = 1959000
flags = 0
data = length 186, hash CDE97917
sample 46:
time = 1917000
flags = 0
data = length 80, hash 923EC2C
sample 47:
time = 2000000
flags = 0
data = length 122, hash EB3EEF54
sample 48:
time = 2084000
flags = 1
data = length 4380, hash 9221E054
sample 49:
time = 2167000
flags = 0
data = length 819, hash 46A722D6
sample 50:
time = 2125000
flags = 0
data = length 140, hash E9AA6D8B
sample 51:
time = 2250000
flags = 0
data = length 711, hash C49CB26
sample 52:
time = 2209000
flags = 0
data = length 111, hash A53830B7
sample 53:
time = 2417000
flags = 0
data = length 1062, hash B95BF284
sample 54:
time = 2334000
flags = 0
data = length 312, hash 1C667DA3
sample 55:
time = 2292000
flags = 0
data = length 132, hash 59C0F906
sample 56:
time = 2375000
flags = 0
data = length 149, hash B7F8F4A5
sample 57:
time = 2584000
flags = 0
data = length 1040, hash 82D4CCFD
sample 58:
time = 2500000
flags = 0
data = length 349, hash C1236BA4
sample 59:
time = 2459000
flags = 0
data = length 140, hash 67015D1B
sample 60:
time = 2542000
flags = 0
data = length 186, hash C0DF4AB0
sample 61:
time = 2750000
flags = 0
data = length 811, hash EEA6FBFF
sample 62:
time = 2667000
flags = 0
data = length 356, hash A9847C12
sample 63:
time = 2625000
flags = 0
data = length 156, hash 61E72801
sample 64:
time = 2709000
flags = 0
data = length 212, hash F1F7EBE8
sample 65:
time = 2917000
flags = 0
data = length 681, hash FA95355F
sample 66:
time = 2834000
flags = 0
data = length 351, hash F771D4DD
sample 67:
time = 2792000
flags = 0
data = length 174, hash 325A7512
sample 68:
time = 2875000
flags = 0
data = length 199, hash A22FAA40
sample 69:
time = 3000000
flags = 0
data = length 322, hash C494E5A7
sample 70:
time = 2959000
flags = 0
data = length 171, hash 2DA9ECEC
tracksEnded = true

Binary file not shown.