Commit 103bd419 by kimvde Committed by Ian Baker

Add IndexSeeker to MP3 extractor

This seeker is only seeking to frames that have already been read by the
extractor for playback. Seeking to not-yet-read frames will be
implemented in another change.

Issue: #6787
PiperOrigin-RevId: 291888899
parent bb9b3fd4
/*
* 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.mp3;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.SeekPoint;
import com.google.android.exoplayer2.util.LongArray;
import com.google.android.exoplayer2.util.Util;
/** MP3 seeker that builds a time-to-byte mapping as the stream is read. */
/* package */ final class IndexSeeker implements Seeker {
private static final long MIN_TIME_BETWEEN_POINTS_US = C.MICROS_PER_SECOND / 10;
private final long durationUs;
private final long dataEndPosition;
private final LongArray timesUs;
private final LongArray positions;
public IndexSeeker(long durationUs, long dataStartPosition, long dataEndPosition) {
this.durationUs = durationUs;
this.dataEndPosition = dataEndPosition;
timesUs = new LongArray();
positions = new LongArray();
timesUs.add(0L);
positions.add(dataStartPosition);
}
@Override
public long getTimeUs(long position) {
int targetIndex =
Util.binarySearchFloor(
positions, position, /* inclusive= */ true, /* stayInBounds= */ true);
return timesUs.get(targetIndex);
}
@Override
public long getDataEndPosition() {
return dataEndPosition;
}
@Override
public boolean isSeekable() {
return true;
}
@Override
public long getDurationUs() {
return durationUs;
}
@Override
public SeekPoints getSeekPoints(long timeUs) {
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) {
return new SeekPoints(seekPoint);
} else {
SeekPoint nextSeekPoint =
new SeekPoint(timesUs.get(targetIndex + 1), positions.get(targetIndex + 1));
return new SeekPoints(seekPoint, nextSeekPoint);
}
}
/**
* Adds a seek point to the index if it is sufficiently distant from the other points.
*
* <p>Seek points must be added in order.
*
* @param timeUs The time corresponding to the seek point to add in microseconds.
* @param position The position corresponding to the seek point to add in bytes.
*/
public void maybeAddSeekPoint(long timeUs, long position) {
long lastTimeUs = timesUs.get(timesUs.size() - 1);
if (timeUs - lastTimeUs < MIN_TIME_BETWEEN_POINTS_US) {
return;
}
timesUs.add(timeUs);
positions.add(position);
}
}
...@@ -56,24 +56,35 @@ public final class Mp3Extractor implements Extractor { ...@@ -56,24 +56,35 @@ public final class Mp3Extractor implements Extractor {
/** /**
* Flags controlling the behavior of the extractor. Possible flag values are {@link * Flags controlling the behavior of the extractor. Possible flag values are {@link
* #FLAG_ENABLE_CONSTANT_BITRATE_SEEKING} and {@link #FLAG_DISABLE_ID3_METADATA}. * #FLAG_ENABLE_CONSTANT_BITRATE_SEEKING}, {@link #FLAG_ENABLE_INDEX_SEEKING} and {@link
* #FLAG_DISABLE_ID3_METADATA}.
*/ */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef( @IntDef(
flag = true, flag = true,
value = {FLAG_ENABLE_CONSTANT_BITRATE_SEEKING, FLAG_DISABLE_ID3_METADATA}) value = {
FLAG_ENABLE_CONSTANT_BITRATE_SEEKING,
FLAG_ENABLE_INDEX_SEEKING,
FLAG_DISABLE_ID3_METADATA
})
public @interface Flags {} public @interface Flags {}
/** /**
* Flag to force enable seeking using a constant bitrate assumption in cases where seeking would * Flag to force enable seeking using a constant bitrate assumption in cases where seeking would
* otherwise not be possible. * otherwise not be possible.
*
* <p>This flag is ignored if {@link #FLAG_ENABLE_INDEX_SEEKING} is set.
*/ */
public static final int FLAG_ENABLE_CONSTANT_BITRATE_SEEKING = 1; public static final int FLAG_ENABLE_CONSTANT_BITRATE_SEEKING = 1;
/** /**
* Flag to force index seeking, consisting in building a time-to-byte mapping as the file is read.
*/
public static final int FLAG_ENABLE_INDEX_SEEKING = 1 << 1;
/**
* Flag to disable parsing of ID3 metadata. Can be set to save memory if ID3 metadata is not * Flag to disable parsing of ID3 metadata. Can be set to save memory if ID3 metadata is not
* required. * required.
*/ */
public static final int FLAG_DISABLE_ID3_METADATA = 2; public static final int FLAG_DISABLE_ID3_METADATA = 1 << 2;
/** Predicate that matches ID3 frames containing only required gapless/seeking metadata. */ /** Predicate that matches ID3 frames containing only required gapless/seeking metadata. */
private static final FramePredicate REQUIRED_ID3_FRAME_PREDICATE = private static final FramePredicate REQUIRED_ID3_FRAME_PREDICATE =
...@@ -256,6 +267,9 @@ public final class Mp3Extractor implements Extractor { ...@@ -256,6 +267,9 @@ public final class Mp3Extractor implements Extractor {
} }
} }
sampleBytesRemaining = synchronizedHeader.frameSize; sampleBytesRemaining = synchronizedHeader.frameSize;
maybeAddSeekPointToIndexSeeker(
computeTimeUs(samplesRead + synchronizedHeader.samplesPerFrame),
extractorInput.getPosition() + synchronizedHeader.frameSize);
} }
int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true); int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true);
if (bytesAppended == C.RESULT_END_OF_INPUT) { if (bytesAppended == C.RESULT_END_OF_INPUT) {
...@@ -265,14 +279,24 @@ public final class Mp3Extractor implements Extractor { ...@@ -265,14 +279,24 @@ public final class Mp3Extractor implements Extractor {
if (sampleBytesRemaining > 0) { if (sampleBytesRemaining > 0) {
return RESULT_CONTINUE; return RESULT_CONTINUE;
} }
long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate); trackOutput.sampleMetadata(
trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0, computeTimeUs(samplesRead), C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0, null);
null);
samplesRead += synchronizedHeader.samplesPerFrame; samplesRead += synchronizedHeader.samplesPerFrame;
sampleBytesRemaining = 0; sampleBytesRemaining = 0;
return RESULT_CONTINUE; return RESULT_CONTINUE;
} }
private long computeTimeUs(long samplesRead) {
return basisTimeUs + samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate;
}
private void maybeAddSeekPointToIndexSeeker(long timeUs, long position) {
if (!(seeker instanceof IndexSeeker)) {
return;
}
((IndexSeeker) seeker).maybeAddSeekPoint(timeUs, position);
}
private boolean synchronize(ExtractorInput input, boolean sniffing) private boolean synchronize(ExtractorInput input, boolean sniffing)
throws IOException, InterruptedException { throws IOException, InterruptedException {
int validFrameCount = 0; int validFrameCount = 0;
...@@ -379,7 +403,20 @@ public final class Mp3Extractor implements Extractor { ...@@ -379,7 +403,20 @@ public final class Mp3Extractor implements Extractor {
} }
@Nullable Seeker resultSeeker = null; @Nullable Seeker resultSeeker = null;
if (metadataSeeker != null) { if ((flags & FLAG_ENABLE_INDEX_SEEKING) != 0) {
long durationUs = C.TIME_UNSET;
long dataEndPosition = C.POSITION_UNSET;
if (metadataSeeker != null) {
durationUs = metadataSeeker.getDurationUs();
dataEndPosition = metadataSeeker.getDataEndPosition();
} else if (seekFrameSeeker != null) {
durationUs = seekFrameSeeker.getDurationUs();
dataEndPosition = seekFrameSeeker.getDataEndPosition();
}
resultSeeker =
new IndexSeeker(
durationUs, /* dataStartPosition= */ input.getPosition(), dataEndPosition);
} else if (metadataSeeker != null) {
resultSeeker = metadataSeeker; resultSeeker = metadataSeeker;
} else if (seekFrameSeeker != null) { } else if (seekFrameSeeker != null) {
resultSeeker = seekFrameSeeker; resultSeeker = seekFrameSeeker;
......
seekMap:
isSeekable = true
duration = 2808000
getPosition(0) = [[timeUs=0, position=237]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/mpeg
maxInputSize = 4096
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 2
sampleRate = 48000
pcmEncoding = -1
encoderDelay = 576
encoderPadding = 576
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
metadata = entries=[TSSE: description=null: value=Lavf58.29.100]
initializationData:
total output bytes = 38160
sample count = 117
sample 0:
time = 0
flags = 1
data = length 96, hash 1F161542
sample 1:
time = 24000
flags = 1
data = length 768, hash CD1DC50F
sample 2:
time = 48000
flags = 1
data = length 336, hash 3F64124B
sample 3:
time = 72000
flags = 1
data = length 336, hash 8FFED94E
sample 4:
time = 96000
flags = 1
data = length 288, hash 9CD77D47
sample 5:
time = 120000
flags = 1
data = length 384, hash 24607BB5
sample 6:
time = 144000
flags = 1
data = length 480, hash 4937EBAB
sample 7:
time = 168000
flags = 1
data = length 336, hash 546342B1
sample 8:
time = 192000
flags = 1
data = length 336, hash 79E0923F
sample 9:
time = 216000
flags = 1
data = length 336, hash AB1F3948
sample 10:
time = 240000
flags = 1
data = length 336, hash C3A4D888
sample 11:
time = 264000
flags = 1
data = length 288, hash 7867DA45
sample 12:
time = 288000
flags = 1
data = length 336, hash B1240B73
sample 13:
time = 312000
flags = 1
data = length 336, hash 94CFCD35
sample 14:
time = 336000
flags = 1
data = length 288, hash 94F412C
sample 15:
time = 360000
flags = 1
data = length 336, hash A1D9FF41
sample 16:
time = 384000
flags = 1
data = length 288, hash 2A8DA21B
sample 17:
time = 408000
flags = 1
data = length 336, hash 6A429CE
sample 18:
time = 432000
flags = 1
data = length 336, hash 68853982
sample 19:
time = 456000
flags = 1
data = length 384, hash 1D6F779C
sample 20:
time = 480000
flags = 1
data = length 480, hash 6B31EBEE
sample 21:
time = 504000
flags = 1
data = length 336, hash 888335BE
sample 22:
time = 528000
flags = 1
data = length 336, hash 6072AC8B
sample 23:
time = 552000
flags = 1
data = length 336, hash C9D24234
sample 24:
time = 576000
flags = 1
data = length 288, hash 52BF4D1E
sample 25:
time = 600000
flags = 1
data = length 336, hash F93F4F0
sample 26:
time = 624000
flags = 1
data = length 336, hash 8617688A
sample 27:
time = 648000
flags = 1
data = length 480, hash FAB0D31B
sample 28:
time = 672000
flags = 1
data = length 384, hash FA4B53E2
sample 29:
time = 696000
flags = 1
data = length 336, hash 8C435F6A
sample 30:
time = 720000
flags = 1
data = length 336, hash 60D3F80C
sample 31:
time = 744000
flags = 1
data = length 336, hash DC15B68B
sample 32:
time = 768000
flags = 1
data = length 288, hash FF3DF141
sample 33:
time = 792000
flags = 1
data = length 336, hash A64B3042
sample 34:
time = 816000
flags = 1
data = length 336, hash ACA622A1
sample 35:
time = 840000
flags = 1
data = length 288, hash 3E34B8D4
sample 36:
time = 864000
flags = 1
data = length 288, hash 9B96F72A
sample 37:
time = 888000
flags = 1
data = length 336, hash E917C122
sample 38:
time = 912000
flags = 1
data = length 336, hash 10ED1470
sample 39:
time = 936000
flags = 1
data = length 288, hash 706B8A7C
sample 40:
time = 960000
flags = 1
data = length 336, hash 71FFE4A0
sample 41:
time = 984000
flags = 1
data = length 336, hash D4160463
sample 42:
time = 1008000
flags = 1
data = length 336, hash EC557B14
sample 43:
time = 1032000
flags = 1
data = length 288, hash 5598CF8B
sample 44:
time = 1056000
flags = 1
data = length 336, hash 7E0AB41
sample 45:
time = 1080000
flags = 1
data = length 336, hash 1C585FEF
sample 46:
time = 1104000
flags = 1
data = length 336, hash A4A4855E
sample 47:
time = 1128000
flags = 1
data = length 336, hash CECA51D3
sample 48:
time = 1152000
flags = 1
data = length 288, hash 2D362DC5
sample 49:
time = 1176000
flags = 1
data = length 336, hash 9EB2609D
sample 50:
time = 1200000
flags = 1
data = length 336, hash 28FFB3FE
sample 51:
time = 1224000
flags = 1
data = length 288, hash 2AA2D216
sample 52:
time = 1248000
flags = 1
data = length 336, hash CDBC7032
sample 53:
time = 1272000
flags = 1
data = length 336, hash 25B13FE7
sample 54:
time = 1296000
flags = 1
data = length 336, hash DB6BB1E
sample 55:
time = 1320000
flags = 1
data = length 336, hash EBE951F4
sample 56:
time = 1344000
flags = 1
data = length 288, hash 9E2EBFF7
sample 57:
time = 1368000
flags = 1
data = length 336, hash 36A7D455
sample 58:
time = 1392000
flags = 1
data = length 336, hash 84545F8C
sample 59:
time = 1416000
flags = 1
data = length 336, hash F66F3045
sample 60:
time = 1440000
flags = 1
data = length 576, hash 5AB089EA
sample 61:
time = 1464000
flags = 1
data = length 336, hash 8868086
sample 62:
time = 1488000
flags = 1
data = length 336, hash D5EB6D63
sample 63:
time = 1512000
flags = 1
data = length 288, hash 7A5374B7
sample 64:
time = 1536000
flags = 1
data = length 336, hash BEB27A75
sample 65:
time = 1560000
flags = 1
data = length 336, hash E251E0FD
sample 66:
time = 1584000
flags = 1
data = length 288, hash D54C970
sample 67:
time = 1608000
flags = 1
data = length 336, hash 52C473B9
sample 68:
time = 1632000
flags = 1
data = length 336, hash F5F13334
sample 69:
time = 1656000
flags = 1
data = length 480, hash A5F1E987
sample 70:
time = 1680000
flags = 1
data = length 288, hash 453A1267
sample 71:
time = 1704000
flags = 1
data = length 288, hash 7C6C2EA9
sample 72:
time = 1728000
flags = 1
data = length 336, hash F4BFECA4
sample 73:
time = 1752000
flags = 1
data = length 336, hash 751A395A
sample 74:
time = 1776000
flags = 1
data = length 336, hash EE38DB02
sample 75:
time = 1800000
flags = 1
data = length 336, hash F18837E2
sample 76:
time = 1824000
flags = 1
data = length 336, hash ED36B78E
sample 77:
time = 1848000
flags = 1
data = length 336, hash B3D28289
sample 78:
time = 1872000
flags = 1
data = length 288, hash 8BDE28E1
sample 79:
time = 1896000
flags = 1
data = length 336, hash CFD5E966
sample 80:
time = 1920000
flags = 1
data = length 288, hash DC08E267
sample 81:
time = 1944000
flags = 1
data = length 336, hash 6530CB78
sample 82:
time = 1968000
flags = 1
data = length 336, hash 6CC6636E
sample 83:
time = 1992000
flags = 1
data = length 336, hash 613047C1
sample 84:
time = 2016000
flags = 1
data = length 288, hash CDC747BF
sample 85:
time = 2040000
flags = 1
data = length 336, hash AF22AA74
sample 86:
time = 2064000
flags = 1
data = length 384, hash 82F326AA
sample 87:
time = 2088000
flags = 1
data = length 384, hash EDA26C4D
sample 88:
time = 2112000
flags = 1
data = length 336, hash 94C643DC
sample 89:
time = 2136000
flags = 1
data = length 288, hash CB5D9C40
sample 90:
time = 2160000
flags = 1
data = length 336, hash 1E69DE3F
sample 91:
time = 2184000
flags = 1
data = length 336, hash 7E472219
sample 92:
time = 2208000
flags = 1
data = length 336, hash DA47B9FA
sample 93:
time = 2232000
flags = 1
data = length 336, hash DD0ABB7C
sample 94:
time = 2256000
flags = 1
data = length 288, hash DBF93FAC
sample 95:
time = 2280000
flags = 1
data = length 336, hash 243F4B2
sample 96:
time = 2304000
flags = 1
data = length 336, hash 2E881490
sample 97:
time = 2328000
flags = 1
data = length 288, hash 1C28C8BE
sample 98:
time = 2352000
flags = 1
data = length 336, hash C73E5D30
sample 99:
time = 2376000
flags = 1
data = length 288, hash 98B5BFF6
sample 100:
time = 2400000
flags = 1
data = length 336, hash E0135533
sample 101:
time = 2424000
flags = 1
data = length 336, hash D13C9DBC
sample 102:
time = 2448000
flags = 1
data = length 336, hash 63D524CA
sample 103:
time = 2472000
flags = 1
data = length 288, hash A28514C3
sample 104:
time = 2496000
flags = 1
data = length 336, hash 72B647FF
sample 105:
time = 2520000
flags = 1
data = length 336, hash 8F740AB1
sample 106:
time = 2544000
flags = 1
data = length 336, hash 5E3C7E93
sample 107:
time = 2568000
flags = 1
data = length 336, hash 121B913B
sample 108:
time = 2592000
flags = 1
data = length 336, hash 578FCCF2
sample 109:
time = 2616000
flags = 1
data = length 336, hash 5B5823DE
sample 110:
time = 2640000
flags = 1
data = length 384, hash D8B83F78
sample 111:
time = 2664000
flags = 1
data = length 240, hash E649682F
sample 112:
time = 2688000
flags = 1
data = length 96, hash C559A6F4
sample 113:
time = 2712000
flags = 1
data = length 96, hash 792796BC
sample 114:
time = 2736000
flags = 1
data = length 120, hash 8172CD0E
sample 115:
time = 2760000
flags = 1
data = length 120, hash F562B52F
sample 116:
time = 2784000
flags = 1
data = length 96, hash FF8D5B98
tracksEnded = true
seekMap:
isSeekable = true
duration = 2808000
getPosition(0) = [[timeUs=0, position=237]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/mpeg
maxInputSize = 4096
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 2
sampleRate = 48000
pcmEncoding = -1
encoderDelay = 576
encoderPadding = 576
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
metadata = entries=[TSSE: description=null: value=Lavf58.29.100]
initializationData:
total output bytes = 25920
sample count = 82
sample 0:
time = 840000
flags = 1
data = length 288, hash 3E34B8D4
sample 1:
time = 864000
flags = 1
data = length 288, hash 9B96F72A
sample 2:
time = 888000
flags = 1
data = length 336, hash E917C122
sample 3:
time = 912000
flags = 1
data = length 336, hash 10ED1470
sample 4:
time = 936000
flags = 1
data = length 288, hash 706B8A7C
sample 5:
time = 960000
flags = 1
data = length 336, hash 71FFE4A0
sample 6:
time = 984000
flags = 1
data = length 336, hash D4160463
sample 7:
time = 1008000
flags = 1
data = length 336, hash EC557B14
sample 8:
time = 1032000
flags = 1
data = length 288, hash 5598CF8B
sample 9:
time = 1056000
flags = 1
data = length 336, hash 7E0AB41
sample 10:
time = 1080000
flags = 1
data = length 336, hash 1C585FEF
sample 11:
time = 1104000
flags = 1
data = length 336, hash A4A4855E
sample 12:
time = 1128000
flags = 1
data = length 336, hash CECA51D3
sample 13:
time = 1152000
flags = 1
data = length 288, hash 2D362DC5
sample 14:
time = 1176000
flags = 1
data = length 336, hash 9EB2609D
sample 15:
time = 1200000
flags = 1
data = length 336, hash 28FFB3FE
sample 16:
time = 1224000
flags = 1
data = length 288, hash 2AA2D216
sample 17:
time = 1248000
flags = 1
data = length 336, hash CDBC7032
sample 18:
time = 1272000
flags = 1
data = length 336, hash 25B13FE7
sample 19:
time = 1296000
flags = 1
data = length 336, hash DB6BB1E
sample 20:
time = 1320000
flags = 1
data = length 336, hash EBE951F4
sample 21:
time = 1344000
flags = 1
data = length 288, hash 9E2EBFF7
sample 22:
time = 1368000
flags = 1
data = length 336, hash 36A7D455
sample 23:
time = 1392000
flags = 1
data = length 336, hash 84545F8C
sample 24:
time = 1416000
flags = 1
data = length 336, hash F66F3045
sample 25:
time = 1440000
flags = 1
data = length 576, hash 5AB089EA
sample 26:
time = 1464000
flags = 1
data = length 336, hash 8868086
sample 27:
time = 1488000
flags = 1
data = length 336, hash D5EB6D63
sample 28:
time = 1512000
flags = 1
data = length 288, hash 7A5374B7
sample 29:
time = 1536000
flags = 1
data = length 336, hash BEB27A75
sample 30:
time = 1560000
flags = 1
data = length 336, hash E251E0FD
sample 31:
time = 1584000
flags = 1
data = length 288, hash D54C970
sample 32:
time = 1608000
flags = 1
data = length 336, hash 52C473B9
sample 33:
time = 1632000
flags = 1
data = length 336, hash F5F13334
sample 34:
time = 1656000
flags = 1
data = length 480, hash A5F1E987
sample 35:
time = 1680000
flags = 1
data = length 288, hash 453A1267
sample 36:
time = 1704000
flags = 1
data = length 288, hash 7C6C2EA9
sample 37:
time = 1728000
flags = 1
data = length 336, hash F4BFECA4
sample 38:
time = 1752000
flags = 1
data = length 336, hash 751A395A
sample 39:
time = 1776000
flags = 1
data = length 336, hash EE38DB02
sample 40:
time = 1800000
flags = 1
data = length 336, hash F18837E2
sample 41:
time = 1824000
flags = 1
data = length 336, hash ED36B78E
sample 42:
time = 1848000
flags = 1
data = length 336, hash B3D28289
sample 43:
time = 1872000
flags = 1
data = length 288, hash 8BDE28E1
sample 44:
time = 1896000
flags = 1
data = length 336, hash CFD5E966
sample 45:
time = 1920000
flags = 1
data = length 288, hash DC08E267
sample 46:
time = 1944000
flags = 1
data = length 336, hash 6530CB78
sample 47:
time = 1968000
flags = 1
data = length 336, hash 6CC6636E
sample 48:
time = 1992000
flags = 1
data = length 336, hash 613047C1
sample 49:
time = 2016000
flags = 1
data = length 288, hash CDC747BF
sample 50:
time = 2040000
flags = 1
data = length 336, hash AF22AA74
sample 51:
time = 2064000
flags = 1
data = length 384, hash 82F326AA
sample 52:
time = 2088000
flags = 1
data = length 384, hash EDA26C4D
sample 53:
time = 2112000
flags = 1
data = length 336, hash 94C643DC
sample 54:
time = 2136000
flags = 1
data = length 288, hash CB5D9C40
sample 55:
time = 2160000
flags = 1
data = length 336, hash 1E69DE3F
sample 56:
time = 2184000
flags = 1
data = length 336, hash 7E472219
sample 57:
time = 2208000
flags = 1
data = length 336, hash DA47B9FA
sample 58:
time = 2232000
flags = 1
data = length 336, hash DD0ABB7C
sample 59:
time = 2256000
flags = 1
data = length 288, hash DBF93FAC
sample 60:
time = 2280000
flags = 1
data = length 336, hash 243F4B2
sample 61:
time = 2304000
flags = 1
data = length 336, hash 2E881490
sample 62:
time = 2328000
flags = 1
data = length 288, hash 1C28C8BE
sample 63:
time = 2352000
flags = 1
data = length 336, hash C73E5D30
sample 64:
time = 2376000
flags = 1
data = length 288, hash 98B5BFF6
sample 65:
time = 2400000
flags = 1
data = length 336, hash E0135533
sample 66:
time = 2424000
flags = 1
data = length 336, hash D13C9DBC
sample 67:
time = 2448000
flags = 1
data = length 336, hash 63D524CA
sample 68:
time = 2472000
flags = 1
data = length 288, hash A28514C3
sample 69:
time = 2496000
flags = 1
data = length 336, hash 72B647FF
sample 70:
time = 2520000
flags = 1
data = length 336, hash 8F740AB1
sample 71:
time = 2544000
flags = 1
data = length 336, hash 5E3C7E93
sample 72:
time = 2568000
flags = 1
data = length 336, hash 121B913B
sample 73:
time = 2592000
flags = 1
data = length 336, hash 578FCCF2
sample 74:
time = 2616000
flags = 1
data = length 336, hash 5B5823DE
sample 75:
time = 2640000
flags = 1
data = length 384, hash D8B83F78
sample 76:
time = 2664000
flags = 1
data = length 240, hash E649682F
sample 77:
time = 2688000
flags = 1
data = length 96, hash C559A6F4
sample 78:
time = 2712000
flags = 1
data = length 96, hash 792796BC
sample 79:
time = 2736000
flags = 1
data = length 120, hash 8172CD0E
sample 80:
time = 2760000
flags = 1
data = length 120, hash F562B52F
sample 81:
time = 2784000
flags = 1
data = length 96, hash FF8D5B98
tracksEnded = true
seekMap:
isSeekable = true
duration = 2808000
getPosition(0) = [[timeUs=0, position=237]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/mpeg
maxInputSize = 4096
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 2
sampleRate = 48000
pcmEncoding = -1
encoderDelay = 576
encoderPadding = 576
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
metadata = entries=[TSSE: description=null: value=Lavf58.29.100]
initializationData:
total output bytes = 12624
sample count = 42
sample 0:
time = 1800000
flags = 1
data = length 336, hash F18837E2
sample 1:
time = 1824000
flags = 1
data = length 336, hash ED36B78E
sample 2:
time = 1848000
flags = 1
data = length 336, hash B3D28289
sample 3:
time = 1872000
flags = 1
data = length 288, hash 8BDE28E1
sample 4:
time = 1896000
flags = 1
data = length 336, hash CFD5E966
sample 5:
time = 1920000
flags = 1
data = length 288, hash DC08E267
sample 6:
time = 1944000
flags = 1
data = length 336, hash 6530CB78
sample 7:
time = 1968000
flags = 1
data = length 336, hash 6CC6636E
sample 8:
time = 1992000
flags = 1
data = length 336, hash 613047C1
sample 9:
time = 2016000
flags = 1
data = length 288, hash CDC747BF
sample 10:
time = 2040000
flags = 1
data = length 336, hash AF22AA74
sample 11:
time = 2064000
flags = 1
data = length 384, hash 82F326AA
sample 12:
time = 2088000
flags = 1
data = length 384, hash EDA26C4D
sample 13:
time = 2112000
flags = 1
data = length 336, hash 94C643DC
sample 14:
time = 2136000
flags = 1
data = length 288, hash CB5D9C40
sample 15:
time = 2160000
flags = 1
data = length 336, hash 1E69DE3F
sample 16:
time = 2184000
flags = 1
data = length 336, hash 7E472219
sample 17:
time = 2208000
flags = 1
data = length 336, hash DA47B9FA
sample 18:
time = 2232000
flags = 1
data = length 336, hash DD0ABB7C
sample 19:
time = 2256000
flags = 1
data = length 288, hash DBF93FAC
sample 20:
time = 2280000
flags = 1
data = length 336, hash 243F4B2
sample 21:
time = 2304000
flags = 1
data = length 336, hash 2E881490
sample 22:
time = 2328000
flags = 1
data = length 288, hash 1C28C8BE
sample 23:
time = 2352000
flags = 1
data = length 336, hash C73E5D30
sample 24:
time = 2376000
flags = 1
data = length 288, hash 98B5BFF6
sample 25:
time = 2400000
flags = 1
data = length 336, hash E0135533
sample 26:
time = 2424000
flags = 1
data = length 336, hash D13C9DBC
sample 27:
time = 2448000
flags = 1
data = length 336, hash 63D524CA
sample 28:
time = 2472000
flags = 1
data = length 288, hash A28514C3
sample 29:
time = 2496000
flags = 1
data = length 336, hash 72B647FF
sample 30:
time = 2520000
flags = 1
data = length 336, hash 8F740AB1
sample 31:
time = 2544000
flags = 1
data = length 336, hash 5E3C7E93
sample 32:
time = 2568000
flags = 1
data = length 336, hash 121B913B
sample 33:
time = 2592000
flags = 1
data = length 336, hash 578FCCF2
sample 34:
time = 2616000
flags = 1
data = length 336, hash 5B5823DE
sample 35:
time = 2640000
flags = 1
data = length 384, hash D8B83F78
sample 36:
time = 2664000
flags = 1
data = length 240, hash E649682F
sample 37:
time = 2688000
flags = 1
data = length 96, hash C559A6F4
sample 38:
time = 2712000
flags = 1
data = length 96, hash 792796BC
sample 39:
time = 2736000
flags = 1
data = length 120, hash 8172CD0E
sample 40:
time = 2760000
flags = 1
data = length 120, hash F562B52F
sample 41:
time = 2784000
flags = 1
data = length 96, hash FF8D5B98
tracksEnded = true
seekMap:
isSeekable = true
duration = 2808000
getPosition(0) = [[timeUs=0, position=237]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/mpeg
maxInputSize = 4096
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 2
sampleRate = 48000
pcmEncoding = -1
encoderDelay = 576
encoderPadding = 576
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
metadata = entries=[TSSE: description=null: value=Lavf58.29.100]
initializationData:
total output bytes = 216
sample count = 2
sample 0:
time = 2760000
flags = 1
data = length 120, hash F562B52F
sample 1:
time = 2784000
flags = 1
data = length 96, hash FF8D5B98
tracksEnded = true
...@@ -36,6 +36,12 @@ public final class Mp3ExtractorTest { ...@@ -36,6 +36,12 @@ public final class Mp3ExtractorTest {
} }
@Test @Test
public void testMp3SampleWithIndexSeeker() throws Exception {
ExtractorAsserts.assertBehavior(
() -> new Mp3Extractor(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING), "mp3/bear-vbr.mp3");
}
@Test
public void testTrimmedMp3Sample() throws Exception { public void testTrimmedMp3Sample() throws Exception {
ExtractorAsserts.assertBehavior(Mp3Extractor::new, "mp3/play-trimmed.mp3"); ExtractorAsserts.assertBehavior(Mp3Extractor::new, "mp3/play-trimmed.mp3");
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment