Commit fb6a8a2c by ibaker Committed by bachinger

Allow AdtsExtractor to encounter EOF

Fixes issue:#6700

sample_cbs_truncated.adts test file produced using
`$ split -b 31795 sample_truncated.adts` to remove the last 10 bytes

PiperOrigin-RevId: 283530136
parent b84bde02
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
clarifying the distinction between `Format` and `MediaFormat`. clarifying the distinction between `Format` and `MediaFormat`.
* Downloads: Merge downloads in `SegmentDownloader` to improve overall download * Downloads: Merge downloads in `SegmentDownloader` to improve overall download
speed ([#5978](https://github.com/google/ExoPlayer/issues/5978)). speed ([#5978](https://github.com/google/ExoPlayer/issues/5978)).
* Allow `AdtsExtractor` to encounter EoF when calculating average frame size
([#6700](https://github.com/google/ExoPlayer/issues/6700)).
### 2.11.0 (not yet released) ### ### 2.11.0 (not yet released) ###
......
...@@ -34,6 +34,7 @@ import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerat ...@@ -34,6 +34,7 @@ import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerat
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableBitArray;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
...@@ -218,7 +219,7 @@ public final class AdtsExtractor implements Extractor { ...@@ -218,7 +219,7 @@ public final class AdtsExtractor implements Extractor {
} }
scratch.skipBytes(3); scratch.skipBytes(3);
int length = scratch.readSynchSafeInt(); int length = scratch.readSynchSafeInt();
firstFramePosition += 10 + length; firstFramePosition += ID3_HEADER_LENGTH + length;
input.advancePeekPosition(length); input.advancePeekPosition(length);
} }
input.resetPeekPosition(); input.resetPeekPosition();
...@@ -266,36 +267,43 @@ public final class AdtsExtractor implements Extractor { ...@@ -266,36 +267,43 @@ public final class AdtsExtractor implements Extractor {
int numValidFrames = 0; int numValidFrames = 0;
long totalValidFramesSize = 0; long totalValidFramesSize = 0;
while (input.peekFully( try {
scratch.data, /* offset= */ 0, /* length= */ 2, /* allowEndOfInput= */ true)) { while (input.peekFully(
scratch.setPosition(0); scratch.data, /* offset= */ 0, /* length= */ 2, /* allowEndOfInput= */ true)) {
int syncBytes = scratch.readUnsignedShort(); scratch.setPosition(0);
if (!AdtsReader.isAdtsSyncWord(syncBytes)) { int syncBytes = scratch.readUnsignedShort();
// Invalid sync byte pattern. if (!AdtsReader.isAdtsSyncWord(syncBytes)) {
// Constant bit-rate seeking will probably fail for this stream. // Invalid sync byte pattern.
numValidFrames = 0; // Constant bit-rate seeking will probably fail for this stream.
break; numValidFrames = 0;
} else {
// Read the frame size.
if (!input.peekFully(
scratch.data, /* offset= */ 0, /* length= */ 4, /* allowEndOfInput= */ true)) {
break;
}
scratchBits.setPosition(14);
int currentFrameSize = scratchBits.readBits(13);
// Either the stream is malformed OR we're not parsing an ADTS stream.
if (currentFrameSize <= 6) {
hasCalculatedAverageFrameSize = true;
throw new ParserException("Malformed ADTS stream");
}
totalValidFramesSize += currentFrameSize;
if (++numValidFrames == NUM_FRAMES_FOR_AVERAGE_FRAME_SIZE) {
break;
}
if (!input.advancePeekPosition(currentFrameSize - 6, /* allowEndOfInput= */ true)) {
break; break;
} else {
// Read the frame size.
if (!input.peekFully(
scratch.data, /* offset= */ 0, /* length= */ 4, /* allowEndOfInput= */ true)) {
break;
}
scratchBits.setPosition(14);
int currentFrameSize = scratchBits.readBits(13);
// Either the stream is malformed OR we're not parsing an ADTS stream.
if (currentFrameSize <= 6) {
hasCalculatedAverageFrameSize = true;
throw new ParserException("Malformed ADTS stream");
}
totalValidFramesSize += currentFrameSize;
if (++numValidFrames == NUM_FRAMES_FOR_AVERAGE_FRAME_SIZE) {
break;
}
if (!input.advancePeekPosition(currentFrameSize - 6, /* allowEndOfInput= */ true)) {
break;
}
} }
} }
} catch (EOFException e) {
// We reached the end of the input during a peekFully() or advancePeekPosition() operation.
// This is OK, it just means the input has an incomplete ADTS frame at the end. Ideally
// ExtractorInput would these operations to encounter end-of-input without throwing an
// exception [internal: b/145586657].
} }
input.resetPeekPosition(); input.resetPeekPosition();
if (numValidFrames > 0) { if (numValidFrames > 0) {
......
seekMap:
isSeekable = true
duration = 3355717
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 2
track 0:
format:
bitrate = -1
id = 0
containerMimeType = null
sampleMimeType = audio/mp4a-latm
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 44100
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
data = length 2, hash 5F7
total output bytes = 20523
sample count = 93
sample 0:
time = 1118572
flags = 1
data = length 232, hash 4B5BF5E8
sample 1:
time = 1141791
flags = 1
data = length 233, hash F3D80836
sample 2:
time = 1165010
flags = 1
data = length 237, hash 32E0A11E
sample 3:
time = 1188229
flags = 1
data = length 228, hash E1B89F13
sample 4:
time = 1211448
flags = 1
data = length 237, hash 8BDD9E38
sample 5:
time = 1234667
flags = 1
data = length 235, hash 3C84161F
sample 6:
time = 1257886
flags = 1
data = length 227, hash A47E1789
sample 7:
time = 1281105
flags = 1
data = length 228, hash 869FDFD3
sample 8:
time = 1304324
flags = 1
data = length 233, hash 272ECE2
sample 9:
time = 1327543
flags = 1
data = length 227, hash DB6B9618
sample 10:
time = 1350762
flags = 1
data = length 212, hash 63214325
sample 11:
time = 1373981
flags = 1
data = length 221, hash 9BA588A1
sample 12:
time = 1397200
flags = 1
data = length 225, hash 21EFD50C
sample 13:
time = 1420419
flags = 1
data = length 231, hash F3AD0BF
sample 14:
time = 1443638
flags = 1
data = length 224, hash 822C9210
sample 15:
time = 1466857
flags = 1
data = length 195, hash D4EF53EE
sample 16:
time = 1490076
flags = 1
data = length 195, hash A816647A
sample 17:
time = 1513295
flags = 1
data = length 184, hash 9A2B7E6
sample 18:
time = 1536514
flags = 1
data = length 210, hash 956E3600
sample 19:
time = 1559733
flags = 1
data = length 234, hash 35CFDA0A
sample 20:
time = 1582952
flags = 1
data = length 239, hash 9E15AC1E
sample 21:
time = 1606171
flags = 1
data = length 228, hash F3B70641
sample 22:
time = 1629390
flags = 1
data = length 237, hash 124E3194
sample 23:
time = 1652609
flags = 1
data = length 231, hash 950CD7C8
sample 24:
time = 1675828
flags = 1
data = length 236, hash A12E49AF
sample 25:
time = 1699047
flags = 1
data = length 242, hash 43BC9C24
sample 26:
time = 1722266
flags = 1
data = length 241, hash DCF0B17
sample 27:
time = 1745485
flags = 1
data = length 251, hash C0B99968
sample 28:
time = 1768704
flags = 1
data = length 245, hash 9B38ED1C
sample 29:
time = 1791923
flags = 1
data = length 238, hash 1BA69079
sample 30:
time = 1815142
flags = 1
data = length 233, hash 44C8C6BF
sample 31:
time = 1838361
flags = 1
data = length 231, hash EABBEE02
sample 32:
time = 1861580
flags = 1
data = length 226, hash D09C44FB
sample 33:
time = 1884799
flags = 1
data = length 235, hash BE6A6608
sample 34:
time = 1908018
flags = 1
data = length 235, hash 2735F454
sample 35:
time = 1931237
flags = 1
data = length 238, hash B160DFE7
sample 36:
time = 1954456
flags = 1
data = length 232, hash 1B217D2E
sample 37:
time = 1977675
flags = 1
data = length 251, hash D1C14CEA
sample 38:
time = 2000894
flags = 1
data = length 256, hash 97C87F08
sample 39:
time = 2024113
flags = 1
data = length 237, hash 6645DB3
sample 40:
time = 2047332
flags = 1
data = length 235, hash 727A1C82
sample 41:
time = 2070551
flags = 1
data = length 234, hash 5015F8B5
sample 42:
time = 2093770
flags = 1
data = length 241, hash 9102144B
sample 43:
time = 2116989
flags = 1
data = length 224, hash 64E0D807
sample 44:
time = 2140208
flags = 1
data = length 228, hash 1922B852
sample 45:
time = 2163427
flags = 1
data = length 224, hash 953502D8
sample 46:
time = 2186646
flags = 1
data = length 214, hash 92B87FE7
sample 47:
time = 2209865
flags = 1
data = length 213, hash BB0C8D86
sample 48:
time = 2233084
flags = 1
data = length 206, hash 9AD21017
sample 49:
time = 2256303
flags = 1
data = length 209, hash C479FE94
sample 50:
time = 2279522
flags = 1
data = length 220, hash 3033DCE1
sample 51:
time = 2302741
flags = 1
data = length 217, hash 7D589C94
sample 52:
time = 2325960
flags = 1
data = length 216, hash AAF6C183
sample 53:
time = 2349179
flags = 1
data = length 206, hash 1EE1207F
sample 54:
time = 2372398
flags = 1
data = length 204, hash 4BEB1210
sample 55:
time = 2395617
flags = 1
data = length 213, hash 21A841C9
sample 56:
time = 2418836
flags = 1
data = length 207, hash B80B0424
sample 57:
time = 2442055
flags = 1
data = length 212, hash 4785A1C3
sample 58:
time = 2465274
flags = 1
data = length 205, hash 59BF7229
sample 59:
time = 2488493
flags = 1
data = length 208, hash FA313DDE
sample 60:
time = 2511712
flags = 1
data = length 211, hash 190D85FD
sample 61:
time = 2534931
flags = 1
data = length 211, hash BA050052
sample 62:
time = 2558150
flags = 1
data = length 211, hash F3080F10
sample 63:
time = 2581369
flags = 1
data = length 210, hash F41B7BE7
sample 64:
time = 2604588
flags = 1
data = length 207, hash 2176C97E
sample 65:
time = 2627807
flags = 1
data = length 220, hash 32087455
sample 66:
time = 2651026
flags = 1
data = length 213, hash 4E5649A8
sample 67:
time = 2674245
flags = 1
data = length 213, hash 5F12FDCF
sample 68:
time = 2697464
flags = 1
data = length 204, hash 1E895C2A
sample 69:
time = 2720683
flags = 1
data = length 219, hash 45382270
sample 70:
time = 2743902
flags = 1
data = length 205, hash D66C6A1D
sample 71:
time = 2767121
flags = 1
data = length 204, hash 467AD01F
sample 72:
time = 2790340
flags = 1
data = length 211, hash F0435574
sample 73:
time = 2813559
flags = 1
data = length 206, hash 8C96B75F
sample 74:
time = 2836778
flags = 1
data = length 200, hash 82553248
sample 75:
time = 2859997
flags = 1
data = length 180, hash 1E51E6CE
sample 76:
time = 2883216
flags = 1
data = length 196, hash 33151DC4
sample 77:
time = 2906435
flags = 1
data = length 197, hash 1E62A7D6
sample 78:
time = 2929654
flags = 1
data = length 206, hash 6A6C4CC9
sample 79:
time = 2952873
flags = 1
data = length 209, hash A72FABAA
sample 80:
time = 2976092
flags = 1
data = length 217, hash BA33B985
sample 81:
time = 2999311
flags = 1
data = length 235, hash 9919CFD9
sample 82:
time = 3022530
flags = 1
data = length 236, hash A22C7267
sample 83:
time = 3045749
flags = 1
data = length 213, hash 3D57C901
sample 84:
time = 3068968
flags = 1
data = length 205, hash 47F68FDE
sample 85:
time = 3092187
flags = 1
data = length 210, hash 9A756E9C
sample 86:
time = 3115406
flags = 1
data = length 210, hash BD45C31F
sample 87:
time = 3138625
flags = 1
data = length 207, hash 8774FF7B
sample 88:
time = 3161844
flags = 1
data = length 149, hash 4678C0E5
sample 89:
time = 3185063
flags = 1
data = length 161, hash E991035D
sample 90:
time = 3208282
flags = 1
data = length 197, hash C3013689
sample 91:
time = 3231501
flags = 1
data = length 208, hash E6C0237
sample 92:
time = 3254720
flags = 1
data = length 232, hash A330F188
track 1:
format:
bitrate = -1
id = 1
containerMimeType = null
sampleMimeType = application/id3
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = -1
sampleRate = -1
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 0
sample count = 0
tracksEnded = true
seekMap:
isSeekable = true
duration = 3355717
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 2
track 0:
format:
bitrate = -1
id = 0
containerMimeType = null
sampleMimeType = audio/mp4a-latm
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 44100
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
data = length 2, hash 5F7
total output bytes = 10151
sample count = 48
sample 0:
time = 2237144
flags = 1
data = length 224, hash 953502D8
sample 1:
time = 2260363
flags = 1
data = length 214, hash 92B87FE7
sample 2:
time = 2283582
flags = 1
data = length 213, hash BB0C8D86
sample 3:
time = 2306801
flags = 1
data = length 206, hash 9AD21017
sample 4:
time = 2330020
flags = 1
data = length 209, hash C479FE94
sample 5:
time = 2353239
flags = 1
data = length 220, hash 3033DCE1
sample 6:
time = 2376458
flags = 1
data = length 217, hash 7D589C94
sample 7:
time = 2399677
flags = 1
data = length 216, hash AAF6C183
sample 8:
time = 2422896
flags = 1
data = length 206, hash 1EE1207F
sample 9:
time = 2446115
flags = 1
data = length 204, hash 4BEB1210
sample 10:
time = 2469334
flags = 1
data = length 213, hash 21A841C9
sample 11:
time = 2492553
flags = 1
data = length 207, hash B80B0424
sample 12:
time = 2515772
flags = 1
data = length 212, hash 4785A1C3
sample 13:
time = 2538991
flags = 1
data = length 205, hash 59BF7229
sample 14:
time = 2562210
flags = 1
data = length 208, hash FA313DDE
sample 15:
time = 2585429
flags = 1
data = length 211, hash 190D85FD
sample 16:
time = 2608648
flags = 1
data = length 211, hash BA050052
sample 17:
time = 2631867
flags = 1
data = length 211, hash F3080F10
sample 18:
time = 2655086
flags = 1
data = length 210, hash F41B7BE7
sample 19:
time = 2678305
flags = 1
data = length 207, hash 2176C97E
sample 20:
time = 2701524
flags = 1
data = length 220, hash 32087455
sample 21:
time = 2724743
flags = 1
data = length 213, hash 4E5649A8
sample 22:
time = 2747962
flags = 1
data = length 213, hash 5F12FDCF
sample 23:
time = 2771181
flags = 1
data = length 204, hash 1E895C2A
sample 24:
time = 2794400
flags = 1
data = length 219, hash 45382270
sample 25:
time = 2817619
flags = 1
data = length 205, hash D66C6A1D
sample 26:
time = 2840838
flags = 1
data = length 204, hash 467AD01F
sample 27:
time = 2864057
flags = 1
data = length 211, hash F0435574
sample 28:
time = 2887276
flags = 1
data = length 206, hash 8C96B75F
sample 29:
time = 2910495
flags = 1
data = length 200, hash 82553248
sample 30:
time = 2933714
flags = 1
data = length 180, hash 1E51E6CE
sample 31:
time = 2956933
flags = 1
data = length 196, hash 33151DC4
sample 32:
time = 2980152
flags = 1
data = length 197, hash 1E62A7D6
sample 33:
time = 3003371
flags = 1
data = length 206, hash 6A6C4CC9
sample 34:
time = 3026590
flags = 1
data = length 209, hash A72FABAA
sample 35:
time = 3049809
flags = 1
data = length 217, hash BA33B985
sample 36:
time = 3073028
flags = 1
data = length 235, hash 9919CFD9
sample 37:
time = 3096247
flags = 1
data = length 236, hash A22C7267
sample 38:
time = 3119466
flags = 1
data = length 213, hash 3D57C901
sample 39:
time = 3142685
flags = 1
data = length 205, hash 47F68FDE
sample 40:
time = 3165904
flags = 1
data = length 210, hash 9A756E9C
sample 41:
time = 3189123
flags = 1
data = length 210, hash BD45C31F
sample 42:
time = 3212342
flags = 1
data = length 207, hash 8774FF7B
sample 43:
time = 3235561
flags = 1
data = length 149, hash 4678C0E5
sample 44:
time = 3258780
flags = 1
data = length 161, hash E991035D
sample 45:
time = 3281999
flags = 1
data = length 197, hash C3013689
sample 46:
time = 3305218
flags = 1
data = length 208, hash E6C0237
sample 47:
time = 3328437
flags = 1
data = length 232, hash A330F188
track 1:
format:
bitrate = -1
id = 1
containerMimeType = null
sampleMimeType = application/id3
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = -1
sampleRate = -1
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 0
sample count = 0
tracksEnded = true
seekMap:
isSeekable = true
duration = 3355717
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 2
track 0:
format:
bitrate = -1
id = 0
containerMimeType = null
sampleMimeType = audio/mp4a-latm
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 44100
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
data = length 2, hash 5F7
total output bytes = 164
sample count = 0
track 1:
format:
bitrate = -1
id = 1
containerMimeType = null
sampleMimeType = application/id3
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = -1
sampleRate = -1
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 0
sample count = 0
tracksEnded = true
...@@ -35,4 +35,12 @@ public final class AdtsExtractorTest { ...@@ -35,4 +35,12 @@ public final class AdtsExtractorTest {
() -> new AdtsExtractor(/* flags= */ AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING), () -> new AdtsExtractor(/* flags= */ AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING),
"ts/sample_cbs.adts"); "ts/sample_cbs.adts");
} }
// https://github.com/google/ExoPlayer/issues/6700
@Test
public void testSample_withSeekingAndTruncatedFile() throws Exception {
ExtractorAsserts.assertBehavior(
() -> new AdtsExtractor(/* flags= */ AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING),
"ts/sample_cbs_truncated.adts");
}
} }
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