mirror of
https://github.com/samsonjs/media.git
synced 2026-03-29 10:05:48 +00:00
parent
6c2b3c875d
commit
79db618ba6
3 changed files with 181 additions and 72 deletions
|
|
@ -113,7 +113,9 @@ public final class WebmExtractor implements Extractor {
|
|||
private static final int ID_CONTENT_ENCODING = 0x6240;
|
||||
private static final int ID_CONTENT_ENCODING_ORDER = 0x5031;
|
||||
private static final int ID_CONTENT_ENCODING_SCOPE = 0x5032;
|
||||
private static final int ID_CONTENT_ENCODING_TYPE = 0x5033;
|
||||
private static final int ID_CONTENT_COMPRESSION = 0x5034;
|
||||
private static final int ID_CONTENT_COMPRESSION_ALGORITHM = 0x4254;
|
||||
private static final int ID_CONTENT_COMPRESSION_SETTINGS = 0x4255;
|
||||
private static final int ID_CONTENT_ENCRYPTION = 0x5035;
|
||||
private static final int ID_CONTENT_ENCRYPTION_ALGORITHM = 0x47E1;
|
||||
private static final int ID_CONTENT_ENCRYPTION_KEY_ID = 0x47E2;
|
||||
|
|
@ -139,6 +141,7 @@ public final class WebmExtractor implements Extractor {
|
|||
private final ParsableByteArray scratch;
|
||||
private final ParsableByteArray vorbisNumPageSamples;
|
||||
private final ParsableByteArray seekEntryIdBytes;
|
||||
private final ParsableByteArray sampleStrippedBytes;
|
||||
|
||||
private long segmentContentPosition = UNKNOWN;
|
||||
private long segmentContentSize = UNKNOWN;
|
||||
|
|
@ -178,7 +181,7 @@ public final class WebmExtractor implements Extractor {
|
|||
|
||||
// Sample reading state.
|
||||
private int sampleBytesRead;
|
||||
private boolean sampleEncryptionDataRead;
|
||||
private boolean sampleEncodingHandled;
|
||||
private int sampleCurrentNalBytesRemaining;
|
||||
private int sampleBytesWritten;
|
||||
private boolean sampleRead;
|
||||
|
|
@ -200,6 +203,7 @@ public final class WebmExtractor implements Extractor {
|
|||
seekEntryIdBytes = new ParsableByteArray(4);
|
||||
nalStartCode = new ParsableByteArray(NalUnitUtil.NAL_START_CODE);
|
||||
nalLength = new ParsableByteArray(4);
|
||||
sampleStrippedBytes = new ParsableByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -213,10 +217,7 @@ public final class WebmExtractor implements Extractor {
|
|||
blockState = BLOCK_STATE_START;
|
||||
reader.reset();
|
||||
varintReader.reset();
|
||||
sampleCurrentNalBytesRemaining = 0;
|
||||
sampleBytesRead = 0;
|
||||
sampleBytesWritten = 0;
|
||||
sampleEncryptionDataRead = false;
|
||||
resetSample();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -247,6 +248,7 @@ public final class WebmExtractor implements Extractor {
|
|||
case ID_VIDEO:
|
||||
case ID_CONTENT_ENCODINGS:
|
||||
case ID_CONTENT_ENCODING:
|
||||
case ID_CONTENT_COMPRESSION:
|
||||
case ID_CONTENT_ENCRYPTION:
|
||||
case ID_CONTENT_ENCRYPTION_AES_SETTINGS:
|
||||
case ID_CUES:
|
||||
|
|
@ -269,7 +271,7 @@ public final class WebmExtractor implements Extractor {
|
|||
case ID_CHANNELS:
|
||||
case ID_CONTENT_ENCODING_ORDER:
|
||||
case ID_CONTENT_ENCODING_SCOPE:
|
||||
case ID_CONTENT_ENCODING_TYPE:
|
||||
case ID_CONTENT_COMPRESSION_ALGORITHM:
|
||||
case ID_CONTENT_ENCRYPTION_ALGORITHM:
|
||||
case ID_CONTENT_ENCRYPTION_AES_SETTINGS_CIPHER_MODE:
|
||||
case ID_CUE_TIME:
|
||||
|
|
@ -280,6 +282,7 @@ public final class WebmExtractor implements Extractor {
|
|||
case ID_CODEC_ID:
|
||||
return EbmlReader.TYPE_STRING;
|
||||
case ID_SEEK_ID:
|
||||
case ID_CONTENT_COMPRESSION_SETTINGS:
|
||||
case ID_CONTENT_ENCRYPTION_KEY_ID:
|
||||
case ID_SIMPLE_BLOCK:
|
||||
case ID_BLOCK:
|
||||
|
|
@ -371,17 +374,20 @@ public final class WebmExtractor implements Extractor {
|
|||
blockState = BLOCK_STATE_START;
|
||||
return;
|
||||
case ID_CONTENT_ENCODING:
|
||||
if (!trackFormat.hasContentEncryption) {
|
||||
// We found a ContentEncoding other than Encryption.
|
||||
throw new ParserException("Found an unsupported ContentEncoding");
|
||||
if (trackFormat.hasContentEncryption) {
|
||||
if (trackFormat.encryptionKeyId == null) {
|
||||
throw new ParserException("Encrypted Track found but ContentEncKeyID was not found");
|
||||
}
|
||||
if (!sentDrmInitData) {
|
||||
extractorOutput.drmInitData(
|
||||
new DrmInitData.Universal(MimeTypes.VIDEO_WEBM, trackFormat.encryptionKeyId));
|
||||
sentDrmInitData = true;
|
||||
}
|
||||
}
|
||||
if (trackFormat.encryptionKeyId == null) {
|
||||
throw new ParserException("Encrypted Track found but ContentEncKeyID was not found");
|
||||
}
|
||||
if (!sentDrmInitData) {
|
||||
extractorOutput.drmInitData(
|
||||
new DrmInitData.Universal(MimeTypes.VIDEO_WEBM, trackFormat.encryptionKeyId));
|
||||
sentDrmInitData = true;
|
||||
return;
|
||||
case ID_CONTENT_ENCODINGS:
|
||||
if (trackFormat.hasContentEncryption && trackFormat.sampleStrippedBytes != null) {
|
||||
throw new ParserException("Combining encryption and compression is not supported");
|
||||
}
|
||||
return;
|
||||
case ID_TRACK_ENTRY:
|
||||
|
|
@ -474,16 +480,15 @@ public final class WebmExtractor implements Extractor {
|
|||
}
|
||||
return;
|
||||
case ID_CONTENT_ENCODING_SCOPE:
|
||||
// This extractor only supports the scope of all frames (since that's the only scope used
|
||||
// for Encryption).
|
||||
// This extractor only supports the scope of all frames.
|
||||
if (value != 1) {
|
||||
throw new ParserException("ContentEncodingScope " + value + " not supported");
|
||||
}
|
||||
return;
|
||||
case ID_CONTENT_ENCODING_TYPE:
|
||||
// This extractor only supports Encrypted ContentEncodingType.
|
||||
if (value != 1) {
|
||||
throw new ParserException("ContentEncodingType " + value + " not supported");
|
||||
case ID_CONTENT_COMPRESSION_ALGORITHM:
|
||||
// This extractor only supports header stripping.
|
||||
if (value != 3) {
|
||||
throw new ParserException("ContentCompAlgo " + value + " not supported");
|
||||
}
|
||||
return;
|
||||
case ID_CONTENT_ENCRYPTION_ALGORITHM:
|
||||
|
|
@ -560,6 +565,11 @@ public final class WebmExtractor implements Extractor {
|
|||
trackFormat.codecPrivate = new byte[contentSize];
|
||||
input.readFully(trackFormat.codecPrivate, 0, contentSize);
|
||||
return;
|
||||
case ID_CONTENT_COMPRESSION_SETTINGS:
|
||||
// This extractor only supports header stripping, so the payload is the stripped bytes.
|
||||
trackFormat.sampleStrippedBytes = new byte[contentSize];
|
||||
input.readFully(trackFormat.sampleStrippedBytes, 0, contentSize);
|
||||
return;
|
||||
case ID_CONTENT_ENCRYPTION_KEY_ID:
|
||||
trackFormat.encryptionKeyId = new byte[contentSize];
|
||||
input.readFully(trackFormat.encryptionKeyId, 0, contentSize);
|
||||
|
|
@ -714,9 +724,15 @@ public final class WebmExtractor implements Extractor {
|
|||
private void outputSampleMetadata(TrackOutput trackOutput, long timeUs) {
|
||||
trackOutput.sampleMetadata(timeUs, blockFlags, sampleBytesWritten, 0, blockEncryptionKeyId);
|
||||
sampleRead = true;
|
||||
resetSample();
|
||||
}
|
||||
|
||||
private void resetSample() {
|
||||
sampleBytesRead = 0;
|
||||
sampleBytesWritten = 0;
|
||||
sampleEncryptionDataRead = false;
|
||||
sampleCurrentNalBytesRemaining = 0;
|
||||
sampleEncodingHandled = false;
|
||||
sampleStrippedBytes.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -738,26 +754,30 @@ public final class WebmExtractor implements Extractor {
|
|||
|
||||
private void writeSampleData(ExtractorInput input, TrackOutput output, TrackFormat format,
|
||||
int size) throws IOException, InterruptedException {
|
||||
// Read the sample's encryption signal byte and set the IV size if necessary.
|
||||
if (format.hasContentEncryption && !sampleEncryptionDataRead) {
|
||||
// Clear the encrypted flag.
|
||||
blockFlags &= ~C.SAMPLE_FLAG_ENCRYPTED;
|
||||
input.readFully(scratch.data, 0, 1);
|
||||
sampleBytesRead++;
|
||||
if ((scratch.data[0] & 0x80) == 0x80) {
|
||||
throw new ParserException("Extension bit is set in signal byte");
|
||||
}
|
||||
sampleEncryptionDataRead = true;
|
||||
|
||||
// If the sample is encrypted, write the IV size instead of the signal byte, and set the flag.
|
||||
if ((scratch.data[0] & 0x01) == 0x01) {
|
||||
scratch.data[0] = (byte) ENCRYPTION_IV_SIZE;
|
||||
scratch.setPosition(0);
|
||||
output.sampleData(scratch, 1);
|
||||
sampleBytesWritten++;
|
||||
blockFlags |= C.SAMPLE_FLAG_ENCRYPTED;
|
||||
if (!sampleEncodingHandled) {
|
||||
if (format.hasContentEncryption) {
|
||||
// If the sample is encrypted, read its encryption signal byte and set the IV size.
|
||||
// Clear the encrypted flag.
|
||||
blockFlags &= ~C.SAMPLE_FLAG_ENCRYPTED;
|
||||
input.readFully(scratch.data, 0, 1);
|
||||
sampleBytesRead++;
|
||||
if ((scratch.data[0] & 0x80) == 0x80) {
|
||||
throw new ParserException("Extension bit is set in signal byte");
|
||||
}
|
||||
if ((scratch.data[0] & 0x01) == 0x01) {
|
||||
scratch.data[0] = (byte) ENCRYPTION_IV_SIZE;
|
||||
scratch.setPosition(0);
|
||||
output.sampleData(scratch, 1);
|
||||
sampleBytesWritten++;
|
||||
blockFlags |= C.SAMPLE_FLAG_ENCRYPTED;
|
||||
}
|
||||
} else if (format.sampleStrippedBytes != null) {
|
||||
// If the sample has header stripping, prepare to read/output the stripped bytes first.
|
||||
sampleStrippedBytes.reset(format.sampleStrippedBytes, format.sampleStrippedBytes.length);
|
||||
}
|
||||
sampleEncodingHandled = true;
|
||||
}
|
||||
size += sampleStrippedBytes.limit();
|
||||
|
||||
if (CODEC_ID_H264.equals(format.codecId)) {
|
||||
// TODO: Deduplicate with Mp4Extractor.
|
||||
|
|
@ -776,28 +796,23 @@ public final class WebmExtractor implements Extractor {
|
|||
while (sampleBytesRead < size) {
|
||||
if (sampleCurrentNalBytesRemaining == 0) {
|
||||
// Read the NAL length so that we know where we find the next one.
|
||||
input.readFully(nalLengthData, nalUnitLengthFieldLengthDiff,
|
||||
readToTarget(input, nalLengthData, nalUnitLengthFieldLengthDiff,
|
||||
nalUnitLengthFieldLength);
|
||||
nalLength.setPosition(0);
|
||||
sampleCurrentNalBytesRemaining = nalLength.readUnsignedIntToInt();
|
||||
// Write a start code for the current NAL unit.
|
||||
nalStartCode.setPosition(0);
|
||||
output.sampleData(nalStartCode, 4);
|
||||
sampleBytesRead += nalUnitLengthFieldLength;
|
||||
sampleBytesWritten += 4;
|
||||
} else {
|
||||
// Write the payload of the NAL unit.
|
||||
int writtenBytes = output.sampleData(input, sampleCurrentNalBytesRemaining);
|
||||
sampleCurrentNalBytesRemaining -= writtenBytes;
|
||||
sampleBytesRead += writtenBytes;
|
||||
sampleBytesWritten += writtenBytes;
|
||||
sampleCurrentNalBytesRemaining -=
|
||||
readToOutput(input, output, sampleCurrentNalBytesRemaining);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (sampleBytesRead < size) {
|
||||
int writtenBytes = output.sampleData(input, size - sampleBytesRead);
|
||||
sampleBytesRead += writtenBytes;
|
||||
sampleBytesWritten += writtenBytes;
|
||||
readToOutput(input, output, size - sampleBytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -814,6 +829,39 @@ public final class WebmExtractor implements Extractor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes {@code length} bytes of sample data into {@code target} at {@code offset}, consisting of
|
||||
* pending {@link #sampleStrippedBytes} and any remaining data read from {@code input}.
|
||||
*/
|
||||
private void readToTarget(ExtractorInput input, byte[] target, int offset, int length)
|
||||
throws IOException, InterruptedException {
|
||||
int pendingStrippedBytes = Math.min(length, sampleStrippedBytes.bytesLeft());
|
||||
input.readFully(target, offset + pendingStrippedBytes, length - pendingStrippedBytes);
|
||||
if (pendingStrippedBytes > 0) {
|
||||
sampleStrippedBytes.readBytes(target, offset, pendingStrippedBytes);
|
||||
}
|
||||
sampleBytesRead += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs up to {@code length} bytes of sample data to {@code output}, consisting of either
|
||||
* {@link #sampleStrippedBytes} or data read from {@code input}.
|
||||
*/
|
||||
private int readToOutput(ExtractorInput input, TrackOutput output, int length)
|
||||
throws IOException, InterruptedException {
|
||||
int bytesRead;
|
||||
int strippedBytesLeft = sampleStrippedBytes.bytesLeft();
|
||||
if (strippedBytesLeft > 0) {
|
||||
bytesRead = Math.min(length, strippedBytesLeft);
|
||||
output.sampleData(sampleStrippedBytes, bytesRead);
|
||||
} else {
|
||||
bytesRead = output.sampleData(input, length);
|
||||
}
|
||||
sampleBytesRead += bytesRead;
|
||||
sampleBytesWritten += bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link ChunkIndex} containing recently gathered Cues information.
|
||||
*
|
||||
|
|
@ -958,6 +1006,7 @@ public final class WebmExtractor implements Extractor {
|
|||
public int type = UNKNOWN;
|
||||
public int defaultSampleDurationNs = UNKNOWN;
|
||||
public boolean hasContentEncryption;
|
||||
public byte[] sampleStrippedBytes;
|
||||
public byte[] encryptionKeyId;
|
||||
public byte[] codecPrivate;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import java.util.List;
|
|||
*/
|
||||
/* package */ final class StreamBuilder {
|
||||
|
||||
/** Used by {@link #addVp9Track} to create a Track header with Encryption. */
|
||||
/** Used by {@link #addVp9Track} to create a track header with encryption/compression. */
|
||||
public static final class ContentEncodingSettings {
|
||||
|
||||
private final int order;
|
||||
|
|
@ -36,14 +36,24 @@ import java.util.List;
|
|||
private final int type;
|
||||
private final int algorithm;
|
||||
private final int aesCipherMode;
|
||||
private final byte[] strippedBytes;
|
||||
|
||||
public ContentEncodingSettings(int order, int scope, int type, int algorithm,
|
||||
int aesCipherMode) {
|
||||
public ContentEncodingSettings(int order, int scope, int algorithm, int aesCipherMode) {
|
||||
this.order = order;
|
||||
this.scope = scope;
|
||||
this.type = type;
|
||||
this.type = 1; // Encryption
|
||||
this.algorithm = algorithm;
|
||||
this.aesCipherMode = aesCipherMode;
|
||||
this.strippedBytes = null;
|
||||
}
|
||||
|
||||
public ContentEncodingSettings(int order, int scope, int algorithm, byte[] strippedBytes) {
|
||||
this.order = order;
|
||||
this.scope = scope;
|
||||
this.type = 0; // Compression
|
||||
this.algorithm = algorithm;
|
||||
this.aesCipherMode = 0;
|
||||
this.strippedBytes = strippedBytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -225,6 +235,23 @@ import java.util.List;
|
|||
byte[] heightBytes = getIntegerBytes(pixelHeight);
|
||||
EbmlElement contentEncodingSettingsElement;
|
||||
if (contentEncodingSettings != null) {
|
||||
EbmlElement encryptionOrCompressionElement;
|
||||
if (contentEncodingSettings.type == 0) {
|
||||
encryptionOrCompressionElement = element(0x5034, // ContentCompression
|
||||
element(0x4254, (byte) (contentEncodingSettings.algorithm & 0xFF)), // ContentCompAlgo
|
||||
element(0x4255, contentEncodingSettings.strippedBytes)); // ContentCompSettings
|
||||
} else if (contentEncodingSettings.type == 1) {
|
||||
encryptionOrCompressionElement = element(0x5035, // ContentEncryption
|
||||
// ContentEncAlgo
|
||||
element(0x47E1, (byte) (contentEncodingSettings.algorithm & 0xFF)),
|
||||
element(0x47E2, TEST_ENCRYPTION_KEY_ID), // ContentEncKeyID
|
||||
element(0x47E7, // ContentEncAESSettings
|
||||
// AESSettingsCipherMode
|
||||
element(0x47E8, (byte) (contentEncodingSettings.aesCipherMode & 0xFF))));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected encoding type.");
|
||||
}
|
||||
|
||||
contentEncodingSettingsElement =
|
||||
element(0x6D80, // ContentEncodings
|
||||
element(0x6240, // ContentEncoding
|
||||
|
|
@ -234,13 +261,7 @@ import java.util.List;
|
|||
element(0x5032, (byte) (contentEncodingSettings.scope & 0xFF)),
|
||||
// ContentEncodingType
|
||||
element(0x5033, (byte) (contentEncodingSettings.type & 0xFF)),
|
||||
element(0x5035, // ContentEncryption
|
||||
// ContentEncAlgo
|
||||
element(0x47E1, (byte) (contentEncodingSettings.algorithm & 0xFF)),
|
||||
element(0x47E2, TEST_ENCRYPTION_KEY_ID), // ContentEncKeyID
|
||||
element(0x47E7, // ContentEncAESSettings
|
||||
// AESSettingsCipherMode
|
||||
element(0x47E8, (byte) (contentEncodingSettings.aesCipherMode & 0xFF))))));
|
||||
encryptionOrCompressionElement));
|
||||
} else {
|
||||
contentEncodingSettingsElement = empty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
}
|
||||
|
||||
public void testPrepareContentEncodingEncryption() throws IOException, InterruptedException {
|
||||
ContentEncodingSettings settings = new StreamBuilder.ContentEncodingSettings(0, 1, 1, 5, 1);
|
||||
ContentEncodingSettings settings = new StreamBuilder.ContentEncodingSettings(0, 1, 5, 1);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
|
|
@ -305,7 +305,7 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
}
|
||||
|
||||
public void testPrepareInvalidContentEncodingOrder() throws IOException, InterruptedException {
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(1, 1, 1, 5, 1);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(1, 1, 5, 1);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
|
|
@ -320,7 +320,7 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
}
|
||||
|
||||
public void testPrepareInvalidContentEncodingScope() throws IOException, InterruptedException {
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 0, 1, 5, 1);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 0, 5, 1);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
|
|
@ -334,8 +334,9 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testPrepareInvalidContentEncodingType() throws IOException, InterruptedException {
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 0, 5, 1);
|
||||
public void testPrepareInvalidContentCompAlgo()
|
||||
throws IOException, InterruptedException {
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 0, new byte[0]);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
|
|
@ -345,12 +346,12 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
TestUtil.consumeTestData(extractor, data);
|
||||
fail();
|
||||
} catch (ParserException exception) {
|
||||
assertEquals("ContentEncodingType 0 not supported", exception.getMessage());
|
||||
assertEquals("ContentCompAlgo 0 not supported", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testPrepareInvalidContentEncAlgo() throws IOException, InterruptedException {
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 1, 4, 1);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 4, 1);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
|
|
@ -365,7 +366,7 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
}
|
||||
|
||||
public void testPrepareInvalidAESSettingsCipherMode() throws IOException, InterruptedException {
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 1, 5, 0);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 5, 0);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
|
|
@ -395,6 +396,44 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
assertSample(0, media, 0, true, false, null, getVideoOutput());
|
||||
}
|
||||
|
||||
public void testReadSampleKeyframeStripped() throws IOException, InterruptedException {
|
||||
byte[] strippedBytes = new byte[] {-1, -1};
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 3, strippedBytes);
|
||||
byte[] sampleBytes = createFrameData(100);
|
||||
byte[] unstrippedSampleBytes = TestUtil.joinByteArrays(strippedBytes, sampleBytes);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
.addVp9Track(TEST_WIDTH, TEST_HEIGHT, settings)
|
||||
.addSimpleBlockMedia(1 /* trackNumber */, 0 /* clusterTimecode */, 0 /* blockTimecode */,
|
||||
true /* keyframe */, false /* invisible */, sampleBytes)
|
||||
.build(1);
|
||||
|
||||
TestUtil.consumeTestData(extractor, data);
|
||||
|
||||
assertVp9VideoFormat();
|
||||
assertSample(0, unstrippedSampleBytes, 0, true, false, null, getVideoOutput());
|
||||
}
|
||||
|
||||
public void testReadSampleKeyframeManyBytesStripped() throws IOException, InterruptedException {
|
||||
byte[] strippedBytes = createFrameData(100);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 3, strippedBytes);
|
||||
byte[] sampleBytes = createFrameData(5);
|
||||
byte[] unstrippedSampleBytes = TestUtil.joinByteArrays(strippedBytes, sampleBytes);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
.addVp9Track(TEST_WIDTH, TEST_HEIGHT, settings)
|
||||
.addSimpleBlockMedia(1 /* trackNumber */, 0 /* clusterTimecode */, 0 /* blockTimecode */,
|
||||
true /* keyframe */, false /* invisible */, sampleBytes)
|
||||
.build(1);
|
||||
|
||||
TestUtil.consumeTestData(extractor, data);
|
||||
|
||||
assertVp9VideoFormat();
|
||||
assertSample(0, unstrippedSampleBytes, 0, true, false, null, getVideoOutput());
|
||||
}
|
||||
|
||||
public void testReadTwoTrackSamples() throws IOException, InterruptedException {
|
||||
byte[] media = createFrameData(100);
|
||||
byte[] data = new StreamBuilder()
|
||||
|
|
@ -479,7 +518,7 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
|
||||
public void testReadEncryptedFrame() throws IOException, InterruptedException {
|
||||
byte[] media = createFrameData(100);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 1, 5, 1);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 5, 1);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
|
|
@ -498,7 +537,7 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
|
|||
public void testReadEncryptedFrameWithInvalidSignalByte()
|
||||
throws IOException, InterruptedException {
|
||||
byte[] media = createFrameData(100);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 1, 5, 1);
|
||||
ContentEncodingSettings settings = new ContentEncodingSettings(0, 1, 5, 1);
|
||||
byte[] data = new StreamBuilder()
|
||||
.setHeader(WEBM_DOC_TYPE)
|
||||
.setInfo(DEFAULT_TIMECODE_SCALE, TEST_DURATION_US)
|
||||
|
|
|
|||
Loading…
Reference in a new issue