Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
79db618b
authored
Jul 15, 2015
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add support for header stripping in Matroska streams.
Issue: #589
parent
6c2b3c87
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
181 additions
and
72 deletions
library/src/main/java/com/google/android/exoplayer/extractor/webm/WebmExtractor.java
library/src/test/java/com/google/android/exoplayer/extractor/webm/StreamBuilder.java
library/src/test/java/com/google/android/exoplayer/extractor/webm/WebmExtractorTest.java
library/src/main/java/com/google/android/exoplayer/extractor/webm/WebmExtractor.java
View file @
79db618b
...
...
@@ -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
sampleEnc
ryptionDataRea
d
;
private
boolean
sampleEnc
odingHandle
d
;
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
.
encryptionKeyId
==
null
)
{
throw
new
ParserException
(
"Encrypted Track found but ContentEncKeyID was not found"
);
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
(!
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
(
"Content
EncodingType
"
+
value
+
" not supported"
);
case
ID_CONTENT_
COMPRESSION_ALGORITHM
:
// This extractor only supports
header stripping
.
if
(
value
!=
3
)
{
throw
new
ParserException
(
"Content
CompAlgo
"
+
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
);
}
}
...
...
@@ -815,6 +830,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.
*
* @return The built {@link ChunkIndex}.
...
...
@@ -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
;
...
...
library/src/test/java/com/google/android/exoplayer/extractor/webm/StreamBuilder.java
View file @
79db618b
...
...
@@ -28,7 +28,7 @@ import java.util.List;
*/
/* package */
final
class
StreamBuilder
{
/** Used by {@link #addVp9Track} to create a
Track header with Encrypt
ion. */
/** Used by {@link #addVp9Track} to create a
track header with encryption/compress
ion. */
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
();
}
...
...
library/src/test/java/com/google/android/exoplayer/extractor/webm/WebmExtractorTest.java
View file @
79db618b
...
...
@@ -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
(
"Content
EncodingType
0 not supported"
,
exception
.
getMessage
());
assertEquals
(
"Content
CompAlgo
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
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment