mirror of
https://github.com/samsonjs/media.git
synced 2026-04-04 11:05:47 +00:00
Test and fix H265Reader
- Update H265Reader to output the same samples after a seek to 0. - Add a TsExtractor test for H.265. PiperOrigin-RevId: 306675050
This commit is contained in:
parent
7214ad2d6f
commit
ed977d1429
8 changed files with 504 additions and 13 deletions
|
|
@ -172,9 +172,8 @@ public final class H265Reader implements ElementaryStreamReader {
|
|||
|
||||
@RequiresNonNull("sampleReader")
|
||||
private void startNalUnit(long position, int offset, int nalUnitType, long pesTimeUs) {
|
||||
if (hasOutputFormat) {
|
||||
sampleReader.startNalUnit(position, offset, nalUnitType, pesTimeUs);
|
||||
} else {
|
||||
sampleReader.startNalUnit(position, offset, nalUnitType, pesTimeUs, hasOutputFormat);
|
||||
if (!hasOutputFormat) {
|
||||
vps.startNalUnit(nalUnitType);
|
||||
sps.startNalUnit(nalUnitType);
|
||||
pps.startNalUnit(nalUnitType);
|
||||
|
|
@ -185,9 +184,8 @@ public final class H265Reader implements ElementaryStreamReader {
|
|||
|
||||
@RequiresNonNull("sampleReader")
|
||||
private void nalUnitData(byte[] dataArray, int offset, int limit) {
|
||||
if (hasOutputFormat) {
|
||||
sampleReader.readNalUnitData(dataArray, offset, limit);
|
||||
} else {
|
||||
sampleReader.readNalUnitData(dataArray, offset, limit);
|
||||
if (!hasOutputFormat) {
|
||||
vps.appendToNalUnit(dataArray, offset, limit);
|
||||
sps.appendToNalUnit(dataArray, offset, limit);
|
||||
pps.appendToNalUnit(dataArray, offset, limit);
|
||||
|
|
@ -198,9 +196,8 @@ public final class H265Reader implements ElementaryStreamReader {
|
|||
|
||||
@RequiresNonNull({"output", "sampleReader"})
|
||||
private void endNalUnit(long position, int offset, int discardPadding, long pesTimeUs) {
|
||||
if (hasOutputFormat) {
|
||||
sampleReader.endNalUnit(position, offset);
|
||||
} else {
|
||||
sampleReader.endNalUnit(position, offset, hasOutputFormat);
|
||||
if (!hasOutputFormat) {
|
||||
vps.endNalUnit(discardPadding);
|
||||
sps.endNalUnit(discardPadding);
|
||||
pps.endNalUnit(discardPadding);
|
||||
|
|
@ -454,7 +451,8 @@ public final class H265Reader implements ElementaryStreamReader {
|
|||
writingParameterSets = false;
|
||||
}
|
||||
|
||||
public void startNalUnit(long position, int offset, int nalUnitType, long pesTimeUs) {
|
||||
public void startNalUnit(
|
||||
long position, int offset, int nalUnitType, long pesTimeUs, boolean hasOutputFormat) {
|
||||
isFirstSlice = false;
|
||||
isFirstParameterSet = false;
|
||||
nalUnitTimeUs = pesTimeUs;
|
||||
|
|
@ -464,7 +462,9 @@ public final class H265Reader implements ElementaryStreamReader {
|
|||
if (nalUnitType >= VPS_NUT) {
|
||||
if (!writingParameterSets && readingSample) {
|
||||
// This is a non-VCL NAL unit, so flush the previous sample.
|
||||
outputSample(offset);
|
||||
if (hasOutputFormat) {
|
||||
outputSample(offset);
|
||||
}
|
||||
readingSample = false;
|
||||
}
|
||||
if (nalUnitType <= PPS_NUT) {
|
||||
|
|
@ -491,14 +491,14 @@ public final class H265Reader implements ElementaryStreamReader {
|
|||
}
|
||||
}
|
||||
|
||||
public void endNalUnit(long position, int offset) {
|
||||
public void endNalUnit(long position, int offset, boolean hasOutputFormat) {
|
||||
if (writingParameterSets && isFirstSlice) {
|
||||
// This sample has parameter sets. Reset the key-frame flag based on the first slice.
|
||||
sampleIsKeyframe = nalUnitHasKeyframeData;
|
||||
writingParameterSets = false;
|
||||
} else if (isFirstParameterSet || isFirstSlice) {
|
||||
// This NAL unit is at the start of a new sample (access unit).
|
||||
if (readingSample) {
|
||||
if (hasOutputFormat && readingSample) {
|
||||
// Output the sample ending before this NAL unit.
|
||||
int nalUnitLength = (int) (position - nalUnitStartPosition);
|
||||
outputSample(offset + nalUnitLength);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ public final class TsExtractorTest {
|
|||
ExtractorAsserts.assertBehavior(TsExtractor::new, "ts/sample_h264_mpeg_audio.ts");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sampleWithH265() throws Exception {
|
||||
ExtractorAsserts.assertBehavior(TsExtractor::new, "ts/sample_h265.ts");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
// TODO(internal: b/153539929) Re-enable when ExtractorAsserts is less strict around repeated
|
||||
|
|
|
|||
BIN
testdata/src/test/assets/ts/sample_h265.ts
vendored
Normal file
BIN
testdata/src/test/assets/ts/sample_h265.ts
vendored
Normal file
Binary file not shown.
141
testdata/src/test/assets/ts/sample_h265.ts.0.dump
vendored
Normal file
141
testdata/src/test/assets/ts/sample_h265.ts.0.dump
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 900000
|
||||
getPosition(0) = [[timeUs=0, position=0]]
|
||||
getPosition(1) = [[timeUs=1, position=0]]
|
||||
getPosition(450000) = [[timeUs=450000, position=11421]]
|
||||
getPosition(900000) = [[timeUs=900000, position=23030]]
|
||||
numberOfTracks = 2
|
||||
track 256:
|
||||
total output bytes = 19364
|
||||
sample count = 29
|
||||
format 0:
|
||||
id = 1/256
|
||||
sampleMimeType = video/hevc
|
||||
width = 854
|
||||
height = 480
|
||||
initializationData:
|
||||
data = length 83, hash 7F428
|
||||
sample 0:
|
||||
time = 66666
|
||||
flags = 1
|
||||
data = length 2510, hash 796A98BE
|
||||
sample 1:
|
||||
time = 100000
|
||||
flags = 0
|
||||
data = length 1219, hash 131AA4E4
|
||||
sample 2:
|
||||
time = 266666
|
||||
flags = 0
|
||||
data = length 7810, hash 3F881DB9
|
||||
sample 3:
|
||||
time = 200000
|
||||
flags = 0
|
||||
data = length 2306, hash 9A77959C
|
||||
sample 4:
|
||||
time = 133333
|
||||
flags = 0
|
||||
data = length 1058, hash B887F7EF
|
||||
sample 5:
|
||||
time = 166666
|
||||
flags = 0
|
||||
data = length 98, hash D95BF6E3
|
||||
sample 6:
|
||||
time = 233333
|
||||
flags = 0
|
||||
data = length 61, hash 574C41C3
|
||||
sample 7:
|
||||
time = 433333
|
||||
flags = 0
|
||||
data = length 296, hash E92DB288
|
||||
sample 8:
|
||||
time = 366666
|
||||
flags = 0
|
||||
data = length 137, hash 586DADD6
|
||||
sample 9:
|
||||
time = 300000
|
||||
flags = 0
|
||||
data = length 218, hash 91E82C9F
|
||||
sample 10:
|
||||
time = 333333
|
||||
flags = 0
|
||||
data = length 177, hash 4A4FEEC0
|
||||
sample 11:
|
||||
time = 400000
|
||||
flags = 0
|
||||
data = length 82, hash 2E2ADD8
|
||||
sample 12:
|
||||
time = 533333
|
||||
flags = 0
|
||||
data = length 290, hash 63CF7D90
|
||||
sample 13:
|
||||
time = 500000
|
||||
flags = 0
|
||||
data = length 268, hash E8CBAC11
|
||||
sample 14:
|
||||
time = 466666
|
||||
flags = 0
|
||||
data = length 178, hash C5B1613E
|
||||
sample 15:
|
||||
time = 566666
|
||||
flags = 0
|
||||
data = length 271, hash 76652FC5
|
||||
sample 16:
|
||||
time = 733333
|
||||
flags = 0
|
||||
data = length 257, hash 960B5DF4
|
||||
sample 17:
|
||||
time = 666666
|
||||
flags = 0
|
||||
data = length 206, hash 87358D00
|
||||
sample 18:
|
||||
time = 600000
|
||||
flags = 0
|
||||
data = length 130, hash 4D7A038D
|
||||
sample 19:
|
||||
time = 633333
|
||||
flags = 0
|
||||
data = length 114, hash 2B3C616E
|
||||
sample 20:
|
||||
time = 700000
|
||||
flags = 0
|
||||
data = length 95, hash 37D79559
|
||||
sample 21:
|
||||
time = 900000
|
||||
flags = 0
|
||||
data = length 233, hash 80308C9E
|
||||
sample 22:
|
||||
time = 833333
|
||||
flags = 0
|
||||
data = length 203, hash E70BA5F2
|
||||
sample 23:
|
||||
time = 766666
|
||||
flags = 0
|
||||
data = length 95, hash BA6FA2D3
|
||||
sample 24:
|
||||
time = 800000
|
||||
flags = 0
|
||||
data = length 103, hash 51291041
|
||||
sample 25:
|
||||
time = 866666
|
||||
flags = 0
|
||||
data = length 111, hash EE9DCFC9
|
||||
sample 26:
|
||||
time = 1033333
|
||||
flags = 0
|
||||
data = length 253, hash D0CEFBA7
|
||||
sample 27:
|
||||
time = 966666
|
||||
flags = 0
|
||||
data = length 134, hash 8802EEF0
|
||||
sample 28:
|
||||
time = 933333
|
||||
flags = 0
|
||||
data = length 80, hash C635D9C2
|
||||
track 8448:
|
||||
total output bytes = 0
|
||||
sample count = 0
|
||||
format 0:
|
||||
id = 1/8448
|
||||
sampleMimeType = application/cea-608
|
||||
tracksEnded = true
|
||||
105
testdata/src/test/assets/ts/sample_h265.ts.1.dump
vendored
Normal file
105
testdata/src/test/assets/ts/sample_h265.ts.1.dump
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 900000
|
||||
getPosition(0) = [[timeUs=0, position=0]]
|
||||
getPosition(1) = [[timeUs=1, position=0]]
|
||||
getPosition(450000) = [[timeUs=450000, position=11421]]
|
||||
getPosition(900000) = [[timeUs=900000, position=23030]]
|
||||
numberOfTracks = 2
|
||||
track 256:
|
||||
total output bytes = 3806
|
||||
sample count = 20
|
||||
format 0:
|
||||
id = 1/256
|
||||
sampleMimeType = video/hevc
|
||||
width = 854
|
||||
height = 480
|
||||
initializationData:
|
||||
data = length 83, hash 7F428
|
||||
sample 0:
|
||||
time = 300000
|
||||
flags = 0
|
||||
data = length 218, hash 91E82C9F
|
||||
sample 1:
|
||||
time = 333333
|
||||
flags = 0
|
||||
data = length 177, hash 4A4FEEC0
|
||||
sample 2:
|
||||
time = 400000
|
||||
flags = 0
|
||||
data = length 82, hash 2E2ADD8
|
||||
sample 3:
|
||||
time = 533333
|
||||
flags = 0
|
||||
data = length 290, hash 63CF7D90
|
||||
sample 4:
|
||||
time = 500000
|
||||
flags = 0
|
||||
data = length 268, hash E8CBAC11
|
||||
sample 5:
|
||||
time = 466666
|
||||
flags = 0
|
||||
data = length 178, hash C5B1613E
|
||||
sample 6:
|
||||
time = 566666
|
||||
flags = 0
|
||||
data = length 271, hash 76652FC5
|
||||
sample 7:
|
||||
time = 733333
|
||||
flags = 0
|
||||
data = length 257, hash 960B5DF4
|
||||
sample 8:
|
||||
time = 666666
|
||||
flags = 0
|
||||
data = length 206, hash 87358D00
|
||||
sample 9:
|
||||
time = 600000
|
||||
flags = 0
|
||||
data = length 130, hash 4D7A038D
|
||||
sample 10:
|
||||
time = 633333
|
||||
flags = 0
|
||||
data = length 114, hash 2B3C616E
|
||||
sample 11:
|
||||
time = 700000
|
||||
flags = 0
|
||||
data = length 95, hash 37D79559
|
||||
sample 12:
|
||||
time = 900000
|
||||
flags = 0
|
||||
data = length 233, hash 80308C9E
|
||||
sample 13:
|
||||
time = 833333
|
||||
flags = 0
|
||||
data = length 203, hash E70BA5F2
|
||||
sample 14:
|
||||
time = 766666
|
||||
flags = 0
|
||||
data = length 95, hash BA6FA2D3
|
||||
sample 15:
|
||||
time = 800000
|
||||
flags = 0
|
||||
data = length 103, hash 51291041
|
||||
sample 16:
|
||||
time = 866666
|
||||
flags = 0
|
||||
data = length 111, hash EE9DCFC9
|
||||
sample 17:
|
||||
time = 1033333
|
||||
flags = 0
|
||||
data = length 253, hash D0CEFBA7
|
||||
sample 18:
|
||||
time = 966666
|
||||
flags = 0
|
||||
data = length 134, hash 8802EEF0
|
||||
sample 19:
|
||||
time = 933333
|
||||
flags = 0
|
||||
data = length 80, hash C635D9C2
|
||||
track 8448:
|
||||
total output bytes = 0
|
||||
sample count = 0
|
||||
format 0:
|
||||
id = 1/8448
|
||||
sampleMimeType = application/cea-608
|
||||
tracksEnded = true
|
||||
69
testdata/src/test/assets/ts/sample_h265.ts.2.dump
vendored
Normal file
69
testdata/src/test/assets/ts/sample_h265.ts.2.dump
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 900000
|
||||
getPosition(0) = [[timeUs=0, position=0]]
|
||||
getPosition(1) = [[timeUs=1, position=0]]
|
||||
getPosition(450000) = [[timeUs=450000, position=11421]]
|
||||
getPosition(900000) = [[timeUs=900000, position=23030]]
|
||||
numberOfTracks = 2
|
||||
track 256:
|
||||
total output bytes = 1796
|
||||
sample count = 11
|
||||
format 0:
|
||||
id = 1/256
|
||||
sampleMimeType = video/hevc
|
||||
width = 854
|
||||
height = 480
|
||||
initializationData:
|
||||
data = length 83, hash 7F428
|
||||
sample 0:
|
||||
time = 600000
|
||||
flags = 0
|
||||
data = length 130, hash 4D7A038D
|
||||
sample 1:
|
||||
time = 633333
|
||||
flags = 0
|
||||
data = length 114, hash 2B3C616E
|
||||
sample 2:
|
||||
time = 700000
|
||||
flags = 0
|
||||
data = length 95, hash 37D79559
|
||||
sample 3:
|
||||
time = 900000
|
||||
flags = 0
|
||||
data = length 233, hash 80308C9E
|
||||
sample 4:
|
||||
time = 833333
|
||||
flags = 0
|
||||
data = length 203, hash E70BA5F2
|
||||
sample 5:
|
||||
time = 766666
|
||||
flags = 0
|
||||
data = length 95, hash BA6FA2D3
|
||||
sample 6:
|
||||
time = 800000
|
||||
flags = 0
|
||||
data = length 103, hash 51291041
|
||||
sample 7:
|
||||
time = 866666
|
||||
flags = 0
|
||||
data = length 111, hash EE9DCFC9
|
||||
sample 8:
|
||||
time = 1033333
|
||||
flags = 0
|
||||
data = length 253, hash D0CEFBA7
|
||||
sample 9:
|
||||
time = 966666
|
||||
flags = 0
|
||||
data = length 134, hash 8802EEF0
|
||||
sample 10:
|
||||
time = 933333
|
||||
flags = 0
|
||||
data = length 80, hash C635D9C2
|
||||
track 8448:
|
||||
total output bytes = 0
|
||||
sample count = 0
|
||||
format 0:
|
||||
id = 1/8448
|
||||
sampleMimeType = application/cea-608
|
||||
tracksEnded = true
|
||||
33
testdata/src/test/assets/ts/sample_h265.ts.3.dump
vendored
Normal file
33
testdata/src/test/assets/ts/sample_h265.ts.3.dump
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 900000
|
||||
getPosition(0) = [[timeUs=0, position=0]]
|
||||
getPosition(1) = [[timeUs=1, position=0]]
|
||||
getPosition(450000) = [[timeUs=450000, position=11421]]
|
||||
getPosition(900000) = [[timeUs=900000, position=23030]]
|
||||
numberOfTracks = 2
|
||||
track 256:
|
||||
total output bytes = 396
|
||||
sample count = 2
|
||||
format 0:
|
||||
id = 1/256
|
||||
sampleMimeType = video/hevc
|
||||
width = 854
|
||||
height = 480
|
||||
initializationData:
|
||||
data = length 83, hash 7F428
|
||||
sample 0:
|
||||
time = 966666
|
||||
flags = 0
|
||||
data = length 134, hash 8802EEF0
|
||||
sample 1:
|
||||
time = 933333
|
||||
flags = 0
|
||||
data = length 80, hash C635D9C2
|
||||
track 8448:
|
||||
total output bytes = 0
|
||||
sample count = 0
|
||||
format 0:
|
||||
id = 1/8448
|
||||
sampleMimeType = application/cea-608
|
||||
tracksEnded = true
|
||||
138
testdata/src/test/assets/ts/sample_h265.ts.unknown_length.dump
vendored
Normal file
138
testdata/src/test/assets/ts/sample_h265.ts.unknown_length.dump
vendored
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
seekMap:
|
||||
isSeekable = false
|
||||
duration = UNSET TIME
|
||||
getPosition(0) = [[timeUs=0, position=0]]
|
||||
numberOfTracks = 2
|
||||
track 256:
|
||||
total output bytes = 19364
|
||||
sample count = 29
|
||||
format 0:
|
||||
id = 1/256
|
||||
sampleMimeType = video/hevc
|
||||
width = 854
|
||||
height = 480
|
||||
initializationData:
|
||||
data = length 83, hash 7F428
|
||||
sample 0:
|
||||
time = 66666
|
||||
flags = 1
|
||||
data = length 2510, hash 796A98BE
|
||||
sample 1:
|
||||
time = 100000
|
||||
flags = 0
|
||||
data = length 1219, hash 131AA4E4
|
||||
sample 2:
|
||||
time = 266666
|
||||
flags = 0
|
||||
data = length 7810, hash 3F881DB9
|
||||
sample 3:
|
||||
time = 200000
|
||||
flags = 0
|
||||
data = length 2306, hash 9A77959C
|
||||
sample 4:
|
||||
time = 133333
|
||||
flags = 0
|
||||
data = length 1058, hash B887F7EF
|
||||
sample 5:
|
||||
time = 166666
|
||||
flags = 0
|
||||
data = length 98, hash D95BF6E3
|
||||
sample 6:
|
||||
time = 233333
|
||||
flags = 0
|
||||
data = length 61, hash 574C41C3
|
||||
sample 7:
|
||||
time = 433333
|
||||
flags = 0
|
||||
data = length 296, hash E92DB288
|
||||
sample 8:
|
||||
time = 366666
|
||||
flags = 0
|
||||
data = length 137, hash 586DADD6
|
||||
sample 9:
|
||||
time = 300000
|
||||
flags = 0
|
||||
data = length 218, hash 91E82C9F
|
||||
sample 10:
|
||||
time = 333333
|
||||
flags = 0
|
||||
data = length 177, hash 4A4FEEC0
|
||||
sample 11:
|
||||
time = 400000
|
||||
flags = 0
|
||||
data = length 82, hash 2E2ADD8
|
||||
sample 12:
|
||||
time = 533333
|
||||
flags = 0
|
||||
data = length 290, hash 63CF7D90
|
||||
sample 13:
|
||||
time = 500000
|
||||
flags = 0
|
||||
data = length 268, hash E8CBAC11
|
||||
sample 14:
|
||||
time = 466666
|
||||
flags = 0
|
||||
data = length 178, hash C5B1613E
|
||||
sample 15:
|
||||
time = 566666
|
||||
flags = 0
|
||||
data = length 271, hash 76652FC5
|
||||
sample 16:
|
||||
time = 733333
|
||||
flags = 0
|
||||
data = length 257, hash 960B5DF4
|
||||
sample 17:
|
||||
time = 666666
|
||||
flags = 0
|
||||
data = length 206, hash 87358D00
|
||||
sample 18:
|
||||
time = 600000
|
||||
flags = 0
|
||||
data = length 130, hash 4D7A038D
|
||||
sample 19:
|
||||
time = 633333
|
||||
flags = 0
|
||||
data = length 114, hash 2B3C616E
|
||||
sample 20:
|
||||
time = 700000
|
||||
flags = 0
|
||||
data = length 95, hash 37D79559
|
||||
sample 21:
|
||||
time = 900000
|
||||
flags = 0
|
||||
data = length 233, hash 80308C9E
|
||||
sample 22:
|
||||
time = 833333
|
||||
flags = 0
|
||||
data = length 203, hash E70BA5F2
|
||||
sample 23:
|
||||
time = 766666
|
||||
flags = 0
|
||||
data = length 95, hash BA6FA2D3
|
||||
sample 24:
|
||||
time = 800000
|
||||
flags = 0
|
||||
data = length 103, hash 51291041
|
||||
sample 25:
|
||||
time = 866666
|
||||
flags = 0
|
||||
data = length 111, hash EE9DCFC9
|
||||
sample 26:
|
||||
time = 1033333
|
||||
flags = 0
|
||||
data = length 253, hash D0CEFBA7
|
||||
sample 27:
|
||||
time = 966666
|
||||
flags = 0
|
||||
data = length 134, hash 8802EEF0
|
||||
sample 28:
|
||||
time = 933333
|
||||
flags = 0
|
||||
data = length 80, hash C635D9C2
|
||||
track 8448:
|
||||
total output bytes = 0
|
||||
sample count = 0
|
||||
format 0:
|
||||
id = 1/8448
|
||||
sampleMimeType = application/cea-608
|
||||
tracksEnded = true
|
||||
Loading…
Reference in a new issue