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
1fa61feb
authored
May 21, 2021
by
aquilescanta
Committed by
Oliver Woodman
May 26, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Migrate AtomParsers to using new ParserException fields
PiperOrigin-RevId: 375133184
parent
e793a903
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
30 additions
and
25 deletions
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/AtomParsersTest.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
View file @
1fa61feb
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.mp4;
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.mp4;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkNotNull
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkNotNull
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
MimeTypes
.
getMimeTypeFromMp4ObjectType
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
MimeTypes
.
getMimeTypeFromMp4ObjectType
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
static
java
.
lang
.
Math
.
max
;
import
static
java
.
lang
.
Math
.
max
;
import
android.util.Pair
;
import
android.util.Pair
;
...
@@ -29,10 +30,10 @@ import com.google.android.exoplayer2.audio.Ac3Util;
...
@@ -29,10 +30,10 @@ import com.google.android.exoplayer2.audio.Ac3Util;
import
com.google.android.exoplayer2.audio.Ac4Util
;
import
com.google.android.exoplayer2.audio.Ac4Util
;
import
com.google.android.exoplayer2.audio.OpusUtil
;
import
com.google.android.exoplayer2.audio.OpusUtil
;
import
com.google.android.exoplayer2.drm.DrmInitData
;
import
com.google.android.exoplayer2.drm.DrmInitData
;
import
com.google.android.exoplayer2.extractor.ExtractorUtil
;
import
com.google.android.exoplayer2.extractor.GaplessInfoHolder
;
import
com.google.android.exoplayer2.extractor.GaplessInfoHolder
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.metadata.mp4.SmtaMetadataEntry
;
import
com.google.android.exoplayer2.metadata.mp4.SmtaMetadataEntry
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
...
@@ -351,7 +352,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -351,7 +352,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
else
{
}
else
{
@Nullable
Atom
.
LeafAtom
stz2Atom
=
stblAtom
.
getLeafAtomOfType
(
Atom
.
TYPE_stz2
);
@Nullable
Atom
.
LeafAtom
stz2Atom
=
stblAtom
.
getLeafAtomOfType
(
Atom
.
TYPE_stz2
);
if
(
stz2Atom
==
null
)
{
if
(
stz2Atom
==
null
)
{
throw
new
ParserException
(
"Track has no sample table size information"
);
throw
ParserException
.
createForMalformedContainer
(
"Track has no sample table size information"
,
/* cause= */
null
);
}
}
sampleSizeBox
=
new
Stz2SampleSizeBox
(
stz2Atom
);
sampleSizeBox
=
new
Stz2SampleSizeBox
(
stz2Atom
);
}
}
...
@@ -919,7 +921,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -919,7 +921,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
for
(
int
i
=
0
;
i
<
numberOfEntries
;
i
++)
{
for
(
int
i
=
0
;
i
<
numberOfEntries
;
i
++)
{
int
childStartPosition
=
stsd
.
getPosition
();
int
childStartPosition
=
stsd
.
getPosition
();
int
childAtomSize
=
stsd
.
readInt
();
int
childAtomSize
=
stsd
.
readInt
();
Assertions
.
checkState
(
childAtomSize
>
0
,
"childAtomSize should
be positive"
);
ExtractorUtil
.
checkContainerInput
(
childAtomSize
>
0
,
"childAtomSize must
be positive"
);
int
childAtomType
=
stsd
.
readInt
();
int
childAtomType
=
stsd
.
readInt
();
if
(
childAtomType
==
Atom
.
TYPE_avc1
if
(
childAtomType
==
Atom
.
TYPE_avc1
||
childAtomType
==
Atom
.
TYPE_avc3
||
childAtomType
==
Atom
.
TYPE_avc3
...
@@ -1105,10 +1107,10 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1105,10 +1107,10 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
// Handle optional terminating four zero bytes in MOV files.
// Handle optional terminating four zero bytes in MOV files.
break
;
break
;
}
}
Assertions
.
checkState
(
childAtomSize
>
0
,
"childAtomSize should
be positive"
);
ExtractorUtil
.
checkContainerInput
(
childAtomSize
>
0
,
"childAtomSize must
be positive"
);
int
childAtomType
=
parent
.
readInt
();
int
childAtomType
=
parent
.
readInt
();
if
(
childAtomType
==
Atom
.
TYPE_avcC
)
{
if
(
childAtomType
==
Atom
.
TYPE_avcC
)
{
Assertions
.
checkState
(
mimeType
==
null
);
ExtractorUtil
.
checkContainerInput
(
mimeType
==
null
,
/* message= */
null
);
mimeType
=
MimeTypes
.
VIDEO_H264
;
mimeType
=
MimeTypes
.
VIDEO_H264
;
parent
.
setPosition
(
childStartPosition
+
Atom
.
HEADER_SIZE
);
parent
.
setPosition
(
childStartPosition
+
Atom
.
HEADER_SIZE
);
AvcConfig
avcConfig
=
AvcConfig
.
parse
(
parent
);
AvcConfig
avcConfig
=
AvcConfig
.
parse
(
parent
);
...
@@ -1119,7 +1121,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1119,7 +1121,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
}
codecs
=
avcConfig
.
codecs
;
codecs
=
avcConfig
.
codecs
;
}
else
if
(
childAtomType
==
Atom
.
TYPE_hvcC
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_hvcC
)
{
Assertions
.
checkState
(
mimeType
==
null
);
ExtractorUtil
.
checkContainerInput
(
mimeType
==
null
,
/* message= */
null
);
mimeType
=
MimeTypes
.
VIDEO_H265
;
mimeType
=
MimeTypes
.
VIDEO_H265
;
parent
.
setPosition
(
childStartPosition
+
Atom
.
HEADER_SIZE
);
parent
.
setPosition
(
childStartPosition
+
Atom
.
HEADER_SIZE
);
HevcConfig
hevcConfig
=
HevcConfig
.
parse
(
parent
);
HevcConfig
hevcConfig
=
HevcConfig
.
parse
(
parent
);
...
@@ -1133,16 +1135,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1133,16 +1135,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
mimeType
=
MimeTypes
.
VIDEO_DOLBY_VISION
;
mimeType
=
MimeTypes
.
VIDEO_DOLBY_VISION
;
}
}
}
else
if
(
childAtomType
==
Atom
.
TYPE_vpcC
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_vpcC
)
{
Assertions
.
checkState
(
mimeType
==
null
);
ExtractorUtil
.
checkContainerInput
(
mimeType
==
null
,
/* message= */
null
);
mimeType
=
(
atomType
==
Atom
.
TYPE_vp08
)
?
MimeTypes
.
VIDEO_VP8
:
MimeTypes
.
VIDEO_VP9
;
mimeType
=
(
atomType
==
Atom
.
TYPE_vp08
)
?
MimeTypes
.
VIDEO_VP8
:
MimeTypes
.
VIDEO_VP9
;
}
else
if
(
childAtomType
==
Atom
.
TYPE_av1C
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_av1C
)
{
Assertions
.
checkState
(
mimeType
==
null
);
ExtractorUtil
.
checkContainerInput
(
mimeType
==
null
,
/* message= */
null
);
mimeType
=
MimeTypes
.
VIDEO_AV1
;
mimeType
=
MimeTypes
.
VIDEO_AV1
;
}
else
if
(
childAtomType
==
Atom
.
TYPE_d263
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_d263
)
{
Assertions
.
checkState
(
mimeType
==
null
);
ExtractorUtil
.
checkContainerInput
(
mimeType
==
null
,
/* message= */
null
);
mimeType
=
MimeTypes
.
VIDEO_H263
;
mimeType
=
MimeTypes
.
VIDEO_H263
;
}
else
if
(
childAtomType
==
Atom
.
TYPE_esds
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_esds
)
{
Assertions
.
checkState
(
mimeType
==
null
);
ExtractorUtil
.
checkContainerInput
(
mimeType
==
null
,
/* message= */
null
);
Pair
<
@NullableType
String
,
byte
@NullableType
[]>
mimeTypeAndInitializationDataBytes
=
Pair
<
@NullableType
String
,
byte
@NullableType
[]>
mimeTypeAndInitializationDataBytes
=
parseEsdsFromParent
(
parent
,
childStartPosition
);
parseEsdsFromParent
(
parent
,
childStartPosition
);
mimeType
=
mimeTypeAndInitializationDataBytes
.
first
;
mimeType
=
mimeTypeAndInitializationDataBytes
.
first
;
...
@@ -1370,7 +1372,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1370,7 +1372,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
while
(
childPosition
-
position
<
size
)
{
while
(
childPosition
-
position
<
size
)
{
parent
.
setPosition
(
childPosition
);
parent
.
setPosition
(
childPosition
);
int
childAtomSize
=
parent
.
readInt
();
int
childAtomSize
=
parent
.
readInt
();
Assertions
.
checkState
(
childAtomSize
>
0
,
"childAtomSize should
be positive"
);
ExtractorUtil
.
checkContainerInput
(
childAtomSize
>
0
,
"childAtomSize must
be positive"
);
int
childAtomType
=
parent
.
readInt
();
int
childAtomType
=
parent
.
readInt
();
if
(
childAtomType
==
Atom
.
TYPE_mhaC
)
{
if
(
childAtomType
==
Atom
.
TYPE_mhaC
)
{
// See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord
// See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord
...
@@ -1481,12 +1483,13 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1481,12 +1483,13 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
* Returns the position of the esds box within a parent, or {@link C#POSITION_UNSET} if no esds
* Returns the position of the esds box within a parent, or {@link C#POSITION_UNSET} if no esds
* box is found
* box is found
*/
*/
private
static
int
findEsdsPosition
(
ParsableByteArray
parent
,
int
position
,
int
size
)
{
private
static
int
findEsdsPosition
(
ParsableByteArray
parent
,
int
position
,
int
size
)
throws
ParserException
{
int
childAtomPosition
=
parent
.
getPosition
();
int
childAtomPosition
=
parent
.
getPosition
();
while
(
childAtomPosition
-
position
<
size
)
{
while
(
childAtomPosition
-
position
<
size
)
{
parent
.
setPosition
(
childAtomPosition
);
parent
.
setPosition
(
childAtomPosition
);
int
childAtomSize
=
parent
.
readInt
();
int
childAtomSize
=
parent
.
readInt
();
Assertions
.
checkState
(
childAtomSize
>
0
,
"childAtomSize should
be positive"
);
ExtractorUtil
.
checkContainerInput
(
childAtomSize
>
0
,
"childAtomSize must
be positive"
);
int
childType
=
parent
.
readInt
();
int
childType
=
parent
.
readInt
();
if
(
childType
==
Atom
.
TYPE_esds
)
{
if
(
childType
==
Atom
.
TYPE_esds
)
{
return
childAtomPosition
;
return
childAtomPosition
;
...
@@ -1546,12 +1549,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1546,12 +1549,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
*/
*/
@Nullable
@Nullable
private
static
Pair
<
Integer
,
TrackEncryptionBox
>
parseSampleEntryEncryptionData
(
private
static
Pair
<
Integer
,
TrackEncryptionBox
>
parseSampleEntryEncryptionData
(
ParsableByteArray
parent
,
int
position
,
int
size
)
{
ParsableByteArray
parent
,
int
position
,
int
size
)
throws
ParserException
{
int
childPosition
=
parent
.
getPosition
();
int
childPosition
=
parent
.
getPosition
();
while
(
childPosition
-
position
<
size
)
{
while
(
childPosition
-
position
<
size
)
{
parent
.
setPosition
(
childPosition
);
parent
.
setPosition
(
childPosition
);
int
childAtomSize
=
parent
.
readInt
();
int
childAtomSize
=
parent
.
readInt
();
Assertions
.
checkState
(
childAtomSize
>
0
,
"childAtomSize should
be positive"
);
ExtractorUtil
.
checkContainerInput
(
childAtomSize
>
0
,
"childAtomSize must
be positive"
);
int
childAtomType
=
parent
.
readInt
();
int
childAtomType
=
parent
.
readInt
();
if
(
childAtomType
==
Atom
.
TYPE_sinf
)
{
if
(
childAtomType
==
Atom
.
TYPE_sinf
)
{
@Nullable
@Nullable
...
@@ -1568,7 +1571,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1568,7 +1571,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Nullable
@Nullable
/* package */
static
Pair
<
Integer
,
TrackEncryptionBox
>
parseCommonEncryptionSinfFromParent
(
/* package */
static
Pair
<
Integer
,
TrackEncryptionBox
>
parseCommonEncryptionSinfFromParent
(
ParsableByteArray
parent
,
int
position
,
int
size
)
{
ParsableByteArray
parent
,
int
position
,
int
size
)
throws
ParserException
{
int
childPosition
=
position
+
Atom
.
HEADER_SIZE
;
int
childPosition
=
position
+
Atom
.
HEADER_SIZE
;
int
schemeInformationBoxPosition
=
C
.
POSITION_UNSET
;
int
schemeInformationBoxPosition
=
C
.
POSITION_UNSET
;
int
schemeInformationBoxSize
=
0
;
int
schemeInformationBoxSize
=
0
;
...
@@ -1595,15 +1598,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1595,15 +1598,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
||
C
.
CENC_TYPE_cbc1
.
equals
(
schemeType
)
||
C
.
CENC_TYPE_cbc1
.
equals
(
schemeType
)
||
C
.
CENC_TYPE_cens
.
equals
(
schemeType
)
||
C
.
CENC_TYPE_cens
.
equals
(
schemeType
)
||
C
.
CENC_TYPE_cbcs
.
equals
(
schemeType
))
{
||
C
.
CENC_TYPE_cbcs
.
equals
(
schemeType
))
{
Assertions
.
checkStateNotNull
(
dataFormat
,
"frma atom is mandatory"
);
ExtractorUtil
.
checkContainerInput
(
dataFormat
!=
null
,
"frma atom is mandatory"
);
Assertions
.
checkState
(
ExtractorUtil
.
checkContainerInput
(
schemeInformationBoxPosition
!=
C
.
POSITION_UNSET
,
"schi atom is mandatory"
);
schemeInformationBoxPosition
!=
C
.
POSITION_UNSET
,
"schi atom is mandatory"
);
@Nullable
TrackEncryptionBox
encryptionBox
=
TrackEncryptionBox
encryptionBox
=
Assertions
.
checkStateNotNull
(
parseSchiFromParent
(
parseSchiFromParent
(
parent
,
schemeInformationBoxPosition
,
schemeInformationBoxSize
,
schemeType
),
parent
,
schemeInformationBoxPosition
,
schemeInformationBoxSize
,
schemeType
);
"tenc atom is mandatory"
);
ExtractorUtil
.
checkContainerInput
(
encryptionBox
!=
null
,
"tenc atom is mandatory"
);
return
Pair
.
create
(
dataFormat
,
encryptionBox
);
return
Pair
.
create
(
dataFormat
,
castNonNull
(
encryptionBox
)
);
}
else
{
}
else
{
return
null
;
return
null
;
}
}
...
@@ -1714,7 +1717,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1714,7 +1717,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private
int
remainingSamplesPerChunkChanges
;
private
int
remainingSamplesPerChunkChanges
;
public
ChunkIterator
(
public
ChunkIterator
(
ParsableByteArray
stsc
,
ParsableByteArray
chunkOffsets
,
boolean
chunkOffsetsAreLongs
)
{
ParsableByteArray
stsc
,
ParsableByteArray
chunkOffsets
,
boolean
chunkOffsetsAreLongs
)
throws
ParserException
{
this
.
stsc
=
stsc
;
this
.
stsc
=
stsc
;
this
.
chunkOffsets
=
chunkOffsets
;
this
.
chunkOffsets
=
chunkOffsets
;
this
.
chunkOffsetsAreLongs
=
chunkOffsetsAreLongs
;
this
.
chunkOffsetsAreLongs
=
chunkOffsetsAreLongs
;
...
@@ -1722,7 +1726,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -1722,7 +1726,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
length
=
chunkOffsets
.
readUnsignedIntToInt
();
length
=
chunkOffsets
.
readUnsignedIntToInt
();
stsc
.
setPosition
(
Atom
.
FULL_HEADER_SIZE
);
stsc
.
setPosition
(
Atom
.
FULL_HEADER_SIZE
);
remainingSamplesPerChunkChanges
=
stsc
.
readUnsignedIntToInt
();
remainingSamplesPerChunkChanges
=
stsc
.
readUnsignedIntToInt
();
Assertions
.
checkState
(
stsc
.
readInt
()
==
1
,
"first_chunk must be 1"
);
ExtractorUtil
.
checkContainerInput
(
stsc
.
readInt
()
==
1
,
"first_chunk must be 1"
);
index
=
-
1
;
index
=
-
1
;
}
}
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/extractor/mp4/AtomParsersTest.java
View file @
1fa61feb
...
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
...
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ParserException
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
org.junit.Test
;
import
org.junit.Test
;
...
@@ -38,7 +39,7 @@ public final class AtomParsersTest {
...
@@ -38,7 +39,7 @@ public final class AtomParsersTest {
Util
.
getBytesFromHexString
(
ATOM_HEADER
+
"00000010"
+
SAMPLE_COUNT
+
"0001000200030004"
);
Util
.
getBytesFromHexString
(
ATOM_HEADER
+
"00000010"
+
SAMPLE_COUNT
+
"0001000200030004"
);
@Test
@Test
public
void
parseCommonEncryptionSinfFromParentIgnoresUnknownSchemeType
()
{
public
void
parseCommonEncryptionSinfFromParentIgnoresUnknownSchemeType
()
throws
ParserException
{
byte
[]
cencSinf
=
byte
[]
cencSinf
=
new
byte
[]
{
new
byte
[]
{
0
,
0
,
0
,
24
,
115
,
105
,
110
,
102
,
// size (4), 'sinf' (4)
0
,
0
,
0
,
24
,
115
,
105
,
110
,
102
,
// size (4), 'sinf' (4)
...
...
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