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
b303ecea
authored
Feb 12, 2021
by
kimvde
Committed by
Oliver Woodman
Feb 12, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add support for MP4/QuickTime non-full meta atoms
#minor-release PiperOrigin-RevId: 357160215
parent
158e6de2
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
34 additions
and
28 deletions
RELEASENOTES.md
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java
RELEASENOTES.md
View file @
b303ecea
...
...
@@ -11,6 +11,8 @@
*
DASH:
*
Fix playback issue for multi-period DASH live streams
(
[
#8537
](
https://github.com/google/ExoPlayer/issues/8537
)
).
*
Extractors:
*
Add support for MP4 and QuickTime meta atoms that are not full atoms.
*
UI:
*
Add builder for
`PlayerNotificationManager`
.
*
IMA extension:
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
View file @
b303ecea
...
...
@@ -145,12 +145,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
* Parses a udta atom.
*
* @param udtaAtom The udta (user data) atom to decode.
* @param isQuickTime True for QuickTime media. False otherwise.
* @return A {@link Pair} containing the metadata from the meta child atom as first value (if
* any), and the metadata from the smta child atom as second value (if any).
*/
public
static
Pair
<
@NullableType
Metadata
,
@NullableType
Metadata
>
parseUdta
(
Atom
.
LeafAtom
udtaAtom
,
boolean
isQuickTime
)
{
Atom
.
LeafAtom
udtaAtom
)
{
ParsableByteArray
udtaData
=
udtaAtom
.
data
;
udtaData
.
setPosition
(
Atom
.
HEADER_SIZE
);
@Nullable
Metadata
metaMetadata
=
null
;
...
...
@@ -159,8 +158,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
int
atomPosition
=
udtaData
.
getPosition
();
int
atomSize
=
udtaData
.
readInt
();
int
atomType
=
udtaData
.
readInt
();
// Meta boxes are regular boxes rather than full boxes in QuickTime. Ignore them for now.
if
(
atomType
==
Atom
.
TYPE_meta
&&
!
isQuickTime
)
{
if
(
atomType
==
Atom
.
TYPE_meta
)
{
udtaData
.
setPosition
(
atomPosition
);
metaMetadata
=
parseUdtaMeta
(
udtaData
,
atomPosition
+
atomSize
);
}
else
if
(
atomType
==
Atom
.
TYPE_smta
)
{
...
...
@@ -228,6 +226,28 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
/**
* Possibly skips the version and flags fields (1+3 byte) of a full meta atom.
*
* <p>Atoms of type {@link Atom#TYPE_meta} are defined to be full atoms which have four additional
* bytes for a version and a flags field (see 4.2 'Object Structure' in ISO/IEC 14496-12:2005).
* QuickTime do not have such a full box structure. Since some of these files are encoded wrongly,
* we can't rely on the file type though. Instead we must check the 4 bytes after the common
* header bytes ourselves.
*
* @param meta The 4 or more bytes following the meta atom size and type.
*/
public
static
void
maybeSkipRemainingMetaAtomHeaderBytes
(
ParsableByteArray
meta
)
{
int
startPosition
=
meta
.
getPosition
();
// The next 4 bytes can be either:
// (iso) 4 zero bytes (version + flags)
// (qt) 4 byte size of next atom
// In case of (iso) we need to skip the next 4 bytes.
if
(
meta
.
readInt
()
!=
0
)
{
meta
.
setPosition
(
startPosition
);
}
}
/**
* Parses a trak atom (defined in ISO/IEC 14496-12).
*
* @param trak Atom to decode.
...
...
@@ -677,7 +697,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Nullable
private
static
Metadata
parseUdtaMeta
(
ParsableByteArray
meta
,
int
limit
)
{
meta
.
skipBytes
(
Atom
.
FULL_HEADER_SIZE
);
meta
.
skipBytes
(
Atom
.
HEADER_SIZE
);
maybeSkipRemainingMetaAtomHeaderBytes
(
meta
);
while
(
meta
.
getPosition
()
<
limit
)
{
int
atomPosition
=
meta
.
getPosition
();
int
atomSize
=
meta
.
readInt
();
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java
View file @
b303ecea
...
...
@@ -470,7 +470,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
@Nullable
Atom
.
LeafAtom
udta
=
moov
.
getLeafAtomOfType
(
Atom
.
TYPE_udta
);
if
(
udta
!=
null
)
{
Pair
<
@NullableType
Metadata
,
@NullableType
Metadata
>
udtaMetadata
=
AtomParsers
.
parseUdta
(
udta
,
isQuickTime
);
AtomParsers
.
parseUdta
(
udta
);
udtaMetaMetadata
=
udtaMetadata
.
first
;
smtaMetadata
=
udtaMetadata
.
second
;
if
(
udtaMetaMetadata
!=
null
)
{
...
...
@@ -727,29 +727,12 @@ public final class Mp4Extractor implements Extractor, SeekMap {
}
}
/**
* Possibly skips the version and flags fields (1+3 byte) of a full meta atom of the {@code
* input}.
*
* <p>Atoms of type {@link Atom#TYPE_meta} are defined to be full atoms which have four additional
* bytes for a version and a flags field (see 4.2 'Object Structure' in ISO/IEC 14496-12:2005).
* QuickTime do not have such a full box structure. Since some of these files are encoded wrongly,
* we can't rely on the file type though. Instead we must check the 8 bytes after the common
* header bytes ourselves.
*/
private
void
maybeSkipRemainingMetaAtomHeaderBytes
(
ExtractorInput
input
)
throws
IOException
{
scratch
.
reset
(
8
);
// Peek the next 8 bytes which can be either
// (iso) [1 byte version + 3 bytes flags][4 byte size of next atom]
// (qt) [4 byte size of next atom ][4 byte hdlr atom type ]
// In case of (iso) we need to skip the next 4 bytes.
input
.
peekFully
(
scratch
.
getData
(),
0
,
8
);
scratch
.
skipBytes
(
4
);
if
(
scratch
.
readInt
()
==
Atom
.
TYPE_hdlr
)
{
input
.
resetPeekPosition
();
}
else
{
input
.
skipFully
(
4
);
}
scratch
.
reset
(
4
);
input
.
peekFully
(
scratch
.
getData
(),
0
,
4
);
AtomParsers
.
maybeSkipRemainingMetaAtomHeaderBytes
(
scratch
);
input
.
skipFully
(
scratch
.
getPosition
());
input
.
resetPeekPosition
();
}
/** Processes an atom whose payload does not need to be parsed. */
...
...
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