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
4a745b1c
authored
Aug 12, 2014
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Optimize out quite a few allocations in FragmentedMp4Parser.
parent
005e98fc
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
187 additions
and
127 deletions
library/src/main/java/com/google/android/exoplayer/chunk/Chunk.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/CodecSpecificDataUtil.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/ParsableByteArray.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/TrackEncryptionBox.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/TrackFragment.java
library/src/main/java/com/google/android/exoplayer/chunk/Chunk.java
View file @
4a745b1c
...
@@ -52,7 +52,7 @@ public abstract class Chunk implements Loadable {
...
@@ -52,7 +52,7 @@ public abstract class Chunk implements Loadable {
/**
/**
* @param dataSource The source from which the data should be loaded.
* @param dataSource The source from which the data should be loaded.
* @param dataSpec Defines the data to be loaded. {@code dataSpec.length} must not exceed
* @param dataSpec Defines the data to be loaded. {@code dataSpec.length} must not exceed
* {@link Integer#MAX_VALUE}. If {@code dataSpec.length ==
DataSpec
.LENGTH_UNBOUNDED} then
* {@link Integer#MAX_VALUE}. If {@code dataSpec.length ==
C
.LENGTH_UNBOUNDED} then
* the length resolved by {@code dataSource.open(dataSpec)} must not exceed
* the length resolved by {@code dataSource.open(dataSpec)} must not exceed
* {@link Integer#MAX_VALUE}.
* {@link Integer#MAX_VALUE}.
* @param format See {@link #format}.
* @param format See {@link #format}.
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
View file @
4a745b1c
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer
.
parser
.
mp4
;
package
com
.
google
.
android
.
exoplayer
.
parser
.
mp4
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
/* package */
abstract
class
Atom
{
/* package */
abstract
class
Atom
{
...
@@ -24,7 +23,6 @@ import java.util.List;
...
@@ -24,7 +23,6 @@ import java.util.List;
public
static
final
int
TYPE_avc3
=
0x61766333
;
public
static
final
int
TYPE_avc3
=
0x61766333
;
public
static
final
int
TYPE_esds
=
0x65736473
;
public
static
final
int
TYPE_esds
=
0x65736473
;
public
static
final
int
TYPE_mdat
=
0x6D646174
;
public
static
final
int
TYPE_mdat
=
0x6D646174
;
public
static
final
int
TYPE_mfhd
=
0x6D666864
;
public
static
final
int
TYPE_mp4a
=
0x6D703461
;
public
static
final
int
TYPE_mp4a
=
0x6D703461
;
public
static
final
int
TYPE_tfdt
=
0x74666474
;
public
static
final
int
TYPE_tfdt
=
0x74666474
;
public
static
final
int
TYPE_tfhd
=
0x74666864
;
public
static
final
int
TYPE_tfhd
=
0x74666864
;
...
@@ -64,17 +62,13 @@ import java.util.List;
...
@@ -64,17 +62,13 @@ import java.util.List;
public
final
static
class
LeafAtom
extends
Atom
{
public
final
static
class
LeafAtom
extends
Atom
{
p
rivate
final
ParsableByteArray
data
;
p
ublic
final
ParsableByteArray
data
;
public
LeafAtom
(
int
type
,
ParsableByteArray
data
)
{
public
LeafAtom
(
int
type
,
ParsableByteArray
data
)
{
super
(
type
);
super
(
type
);
this
.
data
=
data
;
this
.
data
=
data
;
}
}
public
ParsableByteArray
getData
()
{
return
data
;
}
}
}
public
final
static
class
ContainerAtom
extends
Atom
{
public
final
static
class
ContainerAtom
extends
Atom
{
...
@@ -91,7 +85,8 @@ import java.util.List;
...
@@ -91,7 +85,8 @@ import java.util.List;
}
}
public
LeafAtom
getLeafAtomOfType
(
int
type
)
{
public
LeafAtom
getLeafAtomOfType
(
int
type
)
{
for
(
int
i
=
0
;
i
<
children
.
size
();
i
++)
{
int
childrenSize
=
children
.
size
();
for
(
int
i
=
0
;
i
<
childrenSize
;
i
++)
{
Atom
atom
=
children
.
get
(
i
);
Atom
atom
=
children
.
get
(
i
);
if
(
atom
.
type
==
type
)
{
if
(
atom
.
type
==
type
)
{
return
(
LeafAtom
)
atom
;
return
(
LeafAtom
)
atom
;
...
@@ -101,7 +96,8 @@ import java.util.List;
...
@@ -101,7 +96,8 @@ import java.util.List;
}
}
public
ContainerAtom
getContainerAtomOfType
(
int
type
)
{
public
ContainerAtom
getContainerAtomOfType
(
int
type
)
{
for
(
int
i
=
0
;
i
<
children
.
size
();
i
++)
{
int
childrenSize
=
children
.
size
();
for
(
int
i
=
0
;
i
<
childrenSize
;
i
++)
{
Atom
atom
=
children
.
get
(
i
);
Atom
atom
=
children
.
get
(
i
);
if
(
atom
.
type
==
type
)
{
if
(
atom
.
type
==
type
)
{
return
(
ContainerAtom
)
atom
;
return
(
ContainerAtom
)
atom
;
...
@@ -110,10 +106,6 @@ import java.util.List;
...
@@ -110,10 +106,6 @@ import java.util.List;
return
null
;
return
null
;
}
}
public
List
<
Atom
>
getChildren
()
{
return
children
;
}
}
}
}
}
library/src/main/java/com/google/android/exoplayer/parser/mp4/CodecSpecificDataUtil.java
View file @
4a745b1c
...
@@ -27,7 +27,7 @@ import java.util.List;
...
@@ -27,7 +27,7 @@ import java.util.List;
/**
/**
* Provides static utility methods for manipulating various types of codec specific data.
* Provides static utility methods for manipulating various types of codec specific data.
*/
*/
public
class
CodecSpecificDataUtil
{
public
final
class
CodecSpecificDataUtil
{
private
static
final
byte
[]
NAL_START_CODE
=
new
byte
[]
{
0
,
0
,
0
,
1
};
private
static
final
byte
[]
NAL_START_CODE
=
new
byte
[]
{
0
,
0
,
0
,
1
};
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
View file @
4a745b1c
...
@@ -110,7 +110,6 @@ public final class FragmentedMp4Extractor {
...
@@ -110,7 +110,6 @@ public final class FragmentedMp4Extractor {
parsedAtoms
.
add
(
Atom
.
TYPE_hdlr
);
parsedAtoms
.
add
(
Atom
.
TYPE_hdlr
);
parsedAtoms
.
add
(
Atom
.
TYPE_mdat
);
parsedAtoms
.
add
(
Atom
.
TYPE_mdat
);
parsedAtoms
.
add
(
Atom
.
TYPE_mdhd
);
parsedAtoms
.
add
(
Atom
.
TYPE_mdhd
);
parsedAtoms
.
add
(
Atom
.
TYPE_mfhd
);
parsedAtoms
.
add
(
Atom
.
TYPE_moof
);
parsedAtoms
.
add
(
Atom
.
TYPE_moof
);
parsedAtoms
.
add
(
Atom
.
TYPE_moov
);
parsedAtoms
.
add
(
Atom
.
TYPE_moov
);
parsedAtoms
.
add
(
Atom
.
TYPE_mp4a
);
parsedAtoms
.
add
(
Atom
.
TYPE_mp4a
);
...
@@ -154,8 +153,10 @@ public final class FragmentedMp4Extractor {
...
@@ -154,8 +153,10 @@ public final class FragmentedMp4Extractor {
// Parser state
// Parser state
private
final
ParsableByteArray
atomHeader
;
private
final
ParsableByteArray
atomHeader
;
private
final
byte
[]
extendedTypeScratch
;
private
final
Stack
<
ContainerAtom
>
containerAtoms
;
private
final
Stack
<
ContainerAtom
>
containerAtoms
;
private
final
Stack
<
Integer
>
containerAtomEndPoints
;
private
final
Stack
<
Integer
>
containerAtomEndPoints
;
private
final
TrackFragment
fragmentRun
;
private
int
parserState
;
private
int
parserState
;
private
int
atomBytesRead
;
private
int
atomBytesRead
;
...
@@ -175,9 +176,6 @@ public final class FragmentedMp4Extractor {
...
@@ -175,9 +176,6 @@ public final class FragmentedMp4Extractor {
private
Track
track
;
private
Track
track
;
private
DefaultSampleValues
extendsDefaults
;
private
DefaultSampleValues
extendsDefaults
;
// Data parsed from the most recent moof atom
private
TrackFragment
fragmentRun
;
public
FragmentedMp4Extractor
()
{
public
FragmentedMp4Extractor
()
{
this
(
0
);
this
(
0
);
}
}
...
@@ -190,8 +188,10 @@ public final class FragmentedMp4Extractor {
...
@@ -190,8 +188,10 @@ public final class FragmentedMp4Extractor {
this
.
workaroundFlags
=
workaroundFlags
;
this
.
workaroundFlags
=
workaroundFlags
;
parserState
=
STATE_READING_ATOM_HEADER
;
parserState
=
STATE_READING_ATOM_HEADER
;
atomHeader
=
new
ParsableByteArray
(
ATOM_HEADER_SIZE
);
atomHeader
=
new
ParsableByteArray
(
ATOM_HEADER_SIZE
);
extendedTypeScratch
=
new
byte
[
16
];
containerAtoms
=
new
Stack
<
ContainerAtom
>();
containerAtoms
=
new
Stack
<
ContainerAtom
>();
containerAtomEndPoints
=
new
Stack
<
Integer
>();
containerAtomEndPoints
=
new
Stack
<
Integer
>();
fragmentRun
=
new
TrackFragment
();
psshData
=
new
HashMap
<
UUID
,
byte
[]>();
psshData
=
new
HashMap
<
UUID
,
byte
[]>();
}
}
...
@@ -335,7 +335,7 @@ public final class FragmentedMp4Extractor {
...
@@ -335,7 +335,7 @@ public final class FragmentedMp4Extractor {
private
int
readAtomHeader
(
NonBlockingInputStream
inputStream
)
{
private
int
readAtomHeader
(
NonBlockingInputStream
inputStream
)
{
int
remainingBytes
=
ATOM_HEADER_SIZE
-
atomBytesRead
;
int
remainingBytes
=
ATOM_HEADER_SIZE
-
atomBytesRead
;
int
bytesRead
=
inputStream
.
read
(
atomHeader
.
getData
()
,
atomBytesRead
,
remainingBytes
);
int
bytesRead
=
inputStream
.
read
(
atomHeader
.
data
,
atomBytesRead
,
remainingBytes
);
if
(
bytesRead
==
-
1
)
{
if
(
bytesRead
==
-
1
)
{
return
RESULT_END_OF_STREAM
;
return
RESULT_END_OF_STREAM
;
}
}
...
@@ -365,7 +365,7 @@ public final class FragmentedMp4Extractor {
...
@@ -365,7 +365,7 @@ public final class FragmentedMp4Extractor {
containerAtomEndPoints
.
add
(
rootAtomBytesRead
+
atomSize
-
ATOM_HEADER_SIZE
);
containerAtomEndPoints
.
add
(
rootAtomBytesRead
+
atomSize
-
ATOM_HEADER_SIZE
);
}
else
{
}
else
{
atomData
=
new
ParsableByteArray
(
atomSize
);
atomData
=
new
ParsableByteArray
(
atomSize
);
System
.
arraycopy
(
atomHeader
.
getData
(),
0
,
atomData
.
getData
()
,
0
,
ATOM_HEADER_SIZE
);
System
.
arraycopy
(
atomHeader
.
data
,
0
,
atomData
.
data
,
0
,
ATOM_HEADER_SIZE
);
enterState
(
STATE_READING_ATOM_PAYLOAD
);
enterState
(
STATE_READING_ATOM_PAYLOAD
);
}
}
}
else
{
}
else
{
...
@@ -379,7 +379,7 @@ public final class FragmentedMp4Extractor {
...
@@ -379,7 +379,7 @@ public final class FragmentedMp4Extractor {
private
int
readAtomPayload
(
NonBlockingInputStream
inputStream
)
{
private
int
readAtomPayload
(
NonBlockingInputStream
inputStream
)
{
int
bytesRead
;
int
bytesRead
;
if
(
atomData
!=
null
)
{
if
(
atomData
!=
null
)
{
bytesRead
=
inputStream
.
read
(
atomData
.
getData
()
,
atomBytesRead
,
atomSize
-
atomBytesRead
);
bytesRead
=
inputStream
.
read
(
atomData
.
data
,
atomBytesRead
,
atomSize
-
atomBytesRead
);
}
else
{
}
else
{
bytesRead
=
inputStream
.
skip
(
atomSize
-
atomBytesRead
);
bytesRead
=
inputStream
.
skip
(
atomSize
-
atomBytesRead
);
}
}
...
@@ -411,7 +411,7 @@ public final class FragmentedMp4Extractor {
...
@@ -411,7 +411,7 @@ public final class FragmentedMp4Extractor {
if
(!
containerAtoms
.
isEmpty
())
{
if
(!
containerAtoms
.
isEmpty
())
{
containerAtoms
.
peek
().
add
(
leaf
);
containerAtoms
.
peek
().
add
(
leaf
);
}
else
if
(
leaf
.
type
==
Atom
.
TYPE_sidx
)
{
}
else
if
(
leaf
.
type
==
Atom
.
TYPE_sidx
)
{
segmentIndex
=
parseSidx
(
leaf
.
getData
()
);
segmentIndex
=
parseSidx
(
leaf
.
data
);
return
RESULT_READ_INDEX
;
return
RESULT_READ_INDEX
;
}
}
return
0
;
return
0
;
...
@@ -430,11 +430,12 @@ public final class FragmentedMp4Extractor {
...
@@ -430,11 +430,12 @@ public final class FragmentedMp4Extractor {
}
}
private
void
onMoovContainerAtomRead
(
ContainerAtom
moov
)
{
private
void
onMoovContainerAtomRead
(
ContainerAtom
moov
)
{
List
<
Atom
>
moovChildren
=
moov
.
getChildren
();
List
<
Atom
>
moovChildren
=
moov
.
children
;
for
(
int
i
=
0
;
i
<
moovChildren
.
size
();
i
++)
{
int
moovChildrenSize
=
moovChildren
.
size
();
for
(
int
i
=
0
;
i
<
moovChildrenSize
;
i
++)
{
Atom
child
=
moovChildren
.
get
(
i
);
Atom
child
=
moovChildren
.
get
(
i
);
if
(
child
.
type
==
Atom
.
TYPE_pssh
)
{
if
(
child
.
type
==
Atom
.
TYPE_pssh
)
{
ParsableByteArray
psshAtom
=
((
LeafAtom
)
child
).
getData
()
;
ParsableByteArray
psshAtom
=
((
LeafAtom
)
child
).
data
;
psshAtom
.
setPosition
(
FULL_ATOM_HEADER_SIZE
);
psshAtom
.
setPosition
(
FULL_ATOM_HEADER_SIZE
);
UUID
uuid
=
new
UUID
(
psshAtom
.
readLong
(),
psshAtom
.
readLong
());
UUID
uuid
=
new
UUID
(
psshAtom
.
readLong
(),
psshAtom
.
readLong
());
int
dataSize
=
psshAtom
.
readInt
();
int
dataSize
=
psshAtom
.
readInt
();
...
@@ -444,13 +445,13 @@ public final class FragmentedMp4Extractor {
...
@@ -444,13 +445,13 @@ public final class FragmentedMp4Extractor {
}
}
}
}
ContainerAtom
mvex
=
moov
.
getContainerAtomOfType
(
Atom
.
TYPE_mvex
);
ContainerAtom
mvex
=
moov
.
getContainerAtomOfType
(
Atom
.
TYPE_mvex
);
extendsDefaults
=
parseTrex
(
mvex
.
getLeafAtomOfType
(
Atom
.
TYPE_trex
).
getData
()
);
extendsDefaults
=
parseTrex
(
mvex
.
getLeafAtomOfType
(
Atom
.
TYPE_trex
).
data
);
track
=
parseTrak
(
moov
.
getContainerAtomOfType
(
Atom
.
TYPE_trak
));
track
=
parseTrak
(
moov
.
getContainerAtomOfType
(
Atom
.
TYPE_trak
));
}
}
private
void
onMoofContainerAtomRead
(
ContainerAtom
moof
)
{
private
void
onMoofContainerAtomRead
(
ContainerAtom
moof
)
{
fragmentRun
=
new
TrackFragmen
t
();
fragmentRun
.
rese
t
();
parseMoof
(
track
,
extendsDefaults
,
moof
,
fragmentRun
,
workaroundFlags
);
parseMoof
(
track
,
extendsDefaults
,
moof
,
fragmentRun
,
workaroundFlags
,
extendedTypeScratch
);
sampleIndex
=
0
;
sampleIndex
=
0
;
lastSyncSampleIndex
=
0
;
lastSyncSampleIndex
=
0
;
pendingSeekSyncSampleIndex
=
0
;
pendingSeekSyncSampleIndex
=
0
;
...
@@ -484,21 +485,21 @@ public final class FragmentedMp4Extractor {
...
@@ -484,21 +485,21 @@ public final class FragmentedMp4Extractor {
*/
*/
private
static
Track
parseTrak
(
ContainerAtom
trak
)
{
private
static
Track
parseTrak
(
ContainerAtom
trak
)
{
ContainerAtom
mdia
=
trak
.
getContainerAtomOfType
(
Atom
.
TYPE_mdia
);
ContainerAtom
mdia
=
trak
.
getContainerAtomOfType
(
Atom
.
TYPE_mdia
);
int
trackType
=
parseHdlr
(
mdia
.
getLeafAtomOfType
(
Atom
.
TYPE_hdlr
).
getData
()
);
int
trackType
=
parseHdlr
(
mdia
.
getLeafAtomOfType
(
Atom
.
TYPE_hdlr
).
data
);
Assertions
.
checkState
(
trackType
==
Track
.
TYPE_AUDIO
||
trackType
==
Track
.
TYPE_VIDEO
);
Assertions
.
checkState
(
trackType
==
Track
.
TYPE_AUDIO
||
trackType
==
Track
.
TYPE_VIDEO
);
Pair
<
Integer
,
Long
>
header
=
parseTkhd
(
trak
.
getLeafAtomOfType
(
Atom
.
TYPE_tkhd
).
getData
()
);
Pair
<
Integer
,
Long
>
header
=
parseTkhd
(
trak
.
getLeafAtomOfType
(
Atom
.
TYPE_tkhd
).
data
);
int
id
=
header
.
first
;
int
id
=
header
.
first
;
// TODO: This value should be used to set a duration field on the Track object
// TODO: This value should be used to set a duration field on the Track object
// instantiated below, however we've found examples where the value is 0. Revisit whether we
// instantiated below, however we've found examples where the value is 0. Revisit whether we
// should set it anyway (and just have it be wrong for bad media streams).
// should set it anyway (and just have it be wrong for bad media streams).
// long duration = header.second;
// long duration = header.second;
long
timescale
=
parseMdhd
(
mdia
.
getLeafAtomOfType
(
Atom
.
TYPE_mdhd
).
getData
()
);
long
timescale
=
parseMdhd
(
mdia
.
getLeafAtomOfType
(
Atom
.
TYPE_mdhd
).
data
);
ContainerAtom
stbl
=
mdia
.
getContainerAtomOfType
(
Atom
.
TYPE_minf
)
ContainerAtom
stbl
=
mdia
.
getContainerAtomOfType
(
Atom
.
TYPE_minf
)
.
getContainerAtomOfType
(
Atom
.
TYPE_stbl
);
.
getContainerAtomOfType
(
Atom
.
TYPE_stbl
);
Pair
<
MediaFormat
,
TrackEncryptionBox
[]>
sampleDescriptions
=
Pair
<
MediaFormat
,
TrackEncryptionBox
[]>
sampleDescriptions
=
parseStsd
(
stbl
.
getLeafAtomOfType
(
Atom
.
TYPE_stsd
).
getData
()
);
parseStsd
(
stbl
.
getLeafAtomOfType
(
Atom
.
TYPE_stsd
).
data
);
return
new
Track
(
id
,
trackType
,
timescale
,
sampleDescriptions
.
first
,
sampleDescriptions
.
second
);
return
new
Track
(
id
,
trackType
,
timescale
,
sampleDescriptions
.
first
,
sampleDescriptions
.
second
);
}
}
...
@@ -667,7 +668,7 @@ public final class FragmentedMp4Extractor {
...
@@ -667,7 +668,7 @@ public final class FragmentedMp4Extractor {
int
length
=
atom
.
readUnsignedShort
();
int
length
=
atom
.
readUnsignedShort
();
int
offset
=
atom
.
getPosition
();
int
offset
=
atom
.
getPosition
();
atom
.
skip
(
length
);
atom
.
skip
(
length
);
return
CodecSpecificDataUtil
.
buildNalUnit
(
atom
.
getData
()
,
offset
,
length
);
return
CodecSpecificDataUtil
.
buildNalUnit
(
atom
.
data
,
offset
,
length
);
}
}
private
static
TrackEncryptionBox
parseSinfFromParent
(
ParsableByteArray
parent
,
int
position
,
private
static
TrackEncryptionBox
parseSinfFromParent
(
ParsableByteArray
parent
,
int
position
,
...
@@ -759,55 +760,41 @@ public final class FragmentedMp4Extractor {
...
@@ -759,55 +760,41 @@ public final class FragmentedMp4Extractor {
}
}
private
static
void
parseMoof
(
Track
track
,
DefaultSampleValues
extendsDefaults
,
private
static
void
parseMoof
(
Track
track
,
DefaultSampleValues
extendsDefaults
,
ContainerAtom
moof
,
TrackFragment
out
,
int
workaroundFlags
)
{
ContainerAtom
moof
,
TrackFragment
out
,
int
workaroundFlags
,
byte
[]
extendedTypeScratch
)
{
// TODO: Consider checking that the sequence number returned by parseMfhd is as expected.
parseMfhd
(
moof
.
getLeafAtomOfType
(
Atom
.
TYPE_mfhd
).
getData
());
parseTraf
(
track
,
extendsDefaults
,
moof
.
getContainerAtomOfType
(
Atom
.
TYPE_traf
),
parseTraf
(
track
,
extendsDefaults
,
moof
.
getContainerAtomOfType
(
Atom
.
TYPE_traf
),
out
,
workaroundFlags
);
out
,
workaroundFlags
,
extendedTypeScratch
);
}
/**
* Parses an mfhd atom (defined in 14496-12).
*
* @param mfhd The mfhd atom to parse.
* @return The sequence number of the fragment.
*/
private
static
int
parseMfhd
(
ParsableByteArray
mfhd
)
{
mfhd
.
setPosition
(
FULL_ATOM_HEADER_SIZE
);
return
mfhd
.
readUnsignedIntToInt
();
}
}
/**
/**
* Parses a traf atom (defined in 14496-12).
* Parses a traf atom (defined in 14496-12).
*/
*/
private
static
void
parseTraf
(
Track
track
,
DefaultSampleValues
extendsDefaults
,
private
static
void
parseTraf
(
Track
track
,
DefaultSampleValues
extendsDefaults
,
ContainerAtom
traf
,
TrackFragment
out
,
int
workaroundFlags
)
{
ContainerAtom
traf
,
TrackFragment
out
,
int
workaroundFlags
,
byte
[]
extendedTypeScratch
)
{
LeafAtom
tfdtAtom
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_tfdt
);
LeafAtom
tfdtAtom
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_tfdt
);
long
decodeTime
=
tfdtAtom
==
null
?
0
long
decodeTime
=
tfdtAtom
==
null
?
0
:
parseTfdt
(
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_tfdt
).
data
);
:
parseTfdt
(
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_tfdt
).
getData
());
LeafAtom
tfhd
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_tfhd
);
LeafAtom
tfhd
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_tfhd
);
DefaultSampleValues
fragmentHeader
=
parseTfhd
(
extendsDefaults
,
tfhd
.
getData
()
);
DefaultSampleValues
fragmentHeader
=
parseTfhd
(
extendsDefaults
,
tfhd
.
data
);
out
.
s
etSampleDescriptionIndex
(
fragmentHeader
.
sampleDescriptionIndex
)
;
out
.
s
ampleDescriptionIndex
=
fragmentHeader
.
sampleDescriptionIndex
;
LeafAtom
trun
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_trun
);
LeafAtom
trun
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_trun
);
parseTrun
(
track
,
fragmentHeader
,
decodeTime
,
workaroundFlags
,
trun
.
getData
()
,
out
);
parseTrun
(
track
,
fragmentHeader
,
decodeTime
,
workaroundFlags
,
trun
.
data
,
out
);
TrackEncryptionBox
trackEncryptionBox
=
TrackEncryptionBox
trackEncryptionBox
=
track
.
sampleDescriptionEncryptionBoxes
[
fragmentHeader
.
sampleDescriptionIndex
];
track
.
sampleDescriptionEncryptionBoxes
[
fragmentHeader
.
sampleDescriptionIndex
];
LeafAtom
saiz
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_saiz
);
LeafAtom
saiz
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_saiz
);
if
(
saiz
!=
null
)
{
if
(
saiz
!=
null
)
{
parseSaiz
(
trackEncryptionBox
,
saiz
.
getData
()
,
out
);
parseSaiz
(
trackEncryptionBox
,
saiz
.
data
,
out
);
}
}
LeafAtom
senc
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_senc
);
LeafAtom
senc
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_senc
);
if
(
senc
!=
null
)
{
if
(
senc
!=
null
)
{
parseSenc
(
senc
.
getData
()
,
out
);
parseSenc
(
senc
.
data
,
out
);
}
}
LeafAtom
uuid
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_uuid
);
LeafAtom
uuid
=
traf
.
getLeafAtomOfType
(
Atom
.
TYPE_uuid
);
if
(
uuid
!=
null
)
{
if
(
uuid
!=
null
)
{
parseUuid
(
uuid
.
getData
(),
out
);
parseUuid
(
uuid
.
data
,
out
,
extendedTypeScratch
);
}
}
}
}
...
@@ -821,10 +808,15 @@ public final class FragmentedMp4Extractor {
...
@@ -821,10 +808,15 @@ public final class FragmentedMp4Extractor {
saiz
.
skip
(
8
);
saiz
.
skip
(
8
);
}
}
int
defaultSampleInfoSize
=
saiz
.
readUnsignedByte
();
int
defaultSampleInfoSize
=
saiz
.
readUnsignedByte
();
int
sampleCount
=
saiz
.
readUnsignedIntToInt
();
int
sampleCount
=
saiz
.
readUnsignedIntToInt
();
if
(
sampleCount
!=
out
.
length
)
{
throw
new
IllegalStateException
(
"Length mismatch: "
+
sampleCount
+
", "
+
out
.
length
);
}
int
totalSize
=
0
;
int
totalSize
=
0
;
boolean
[]
sampleHasSubsampleEncryptionTable
=
new
boolean
[
sampleCount
];
if
(
defaultSampleInfoSize
==
0
)
{
if
(
defaultSampleInfoSize
==
0
)
{
boolean
[]
sampleHasSubsampleEncryptionTable
=
out
.
sampleHasSubsampleEncryptionTable
;
for
(
int
i
=
0
;
i
<
sampleCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
sampleCount
;
i
++)
{
int
sampleInfoSize
=
saiz
.
readUnsignedByte
();
int
sampleInfoSize
=
saiz
.
readUnsignedByte
();
totalSize
+=
sampleInfoSize
;
totalSize
+=
sampleInfoSize
;
...
@@ -833,10 +825,9 @@ public final class FragmentedMp4Extractor {
...
@@ -833,10 +825,9 @@ public final class FragmentedMp4Extractor {
}
else
{
}
else
{
boolean
subsampleEncryption
=
defaultSampleInfoSize
>
vectorSize
;
boolean
subsampleEncryption
=
defaultSampleInfoSize
>
vectorSize
;
totalSize
+=
defaultSampleInfoSize
*
sampleCount
;
totalSize
+=
defaultSampleInfoSize
*
sampleCount
;
Arrays
.
fill
(
sampleHasSubsampleEncryptionTable
,
subsampleEncryption
);
Arrays
.
fill
(
out
.
sampleHasSubsampleEncryptionTable
,
0
,
sampleCount
,
subsampleEncryption
);
}
}
out
.
setSampleEncryptionData
(
sampleHasSubsampleEncryptionTable
,
out
.
initEncryptionData
(
totalSize
);
new
ParsableByteArray
(
totalSize
),
true
);
}
}
/**
/**
...
@@ -895,10 +886,9 @@ public final class FragmentedMp4Extractor {
...
@@ -895,10 +886,9 @@ public final class FragmentedMp4Extractor {
long
decodeTime
,
int
workaroundFlags
,
ParsableByteArray
trun
,
TrackFragment
out
)
{
long
decodeTime
,
int
workaroundFlags
,
ParsableByteArray
trun
,
TrackFragment
out
)
{
trun
.
setPosition
(
ATOM_HEADER_SIZE
);
trun
.
setPosition
(
ATOM_HEADER_SIZE
);
int
fullAtom
=
trun
.
readInt
();
int
fullAtom
=
trun
.
readInt
();
int
version
=
parseFullAtomVersion
(
fullAtom
);
int
flags
=
parseFullAtomFlags
(
fullAtom
);
int
flags
=
parseFullAtomFlags
(
fullAtom
);
int
numberOfEntries
=
trun
.
readUnsignedIntToInt
();
int
sampleCount
=
trun
.
readUnsignedIntToInt
();
if
((
flags
&
0x01
/* data_offset_present */
)
!=
0
)
{
if
((
flags
&
0x01
/* data_offset_present */
)
!=
0
)
{
trun
.
skip
(
4
);
trun
.
skip
(
4
);
}
}
...
@@ -915,17 +905,18 @@ public final class FragmentedMp4Extractor {
...
@@ -915,17 +905,18 @@ public final class FragmentedMp4Extractor {
boolean
sampleCompositionTimeOffsetsPresent
=
boolean
sampleCompositionTimeOffsetsPresent
=
(
flags
&
0x800
/* sample_composition_time_offsets_present */
)
!=
0
;
(
flags
&
0x800
/* sample_composition_time_offsets_present */
)
!=
0
;
int
[]
sampleSizeTable
=
new
int
[
numberOfEntries
];
out
.
initTables
(
sampleCount
);
int
[]
sampleDecodingTimeTable
=
new
int
[
numberOfEntries
];
int
[]
sampleSizeTable
=
out
.
sampleSizeTable
;
int
[]
sampleCompositionTimeOffsetTable
=
new
int
[
numberOfEntries
];
int
[]
sampleDecodingTimeTable
=
out
.
sampleDecodingTimeTable
;
boolean
[]
sampleIsSyncFrameTable
=
new
boolean
[
numberOfEntries
];
int
[]
sampleCompositionTimeOffsetTable
=
out
.
sampleCompositionTimeOffsetTable
;
boolean
[]
sampleIsSyncFrameTable
=
out
.
sampleIsSyncFrameTable
;
long
timescale
=
track
.
timescale
;
long
timescale
=
track
.
timescale
;
long
cumulativeTime
=
decodeTime
;
long
cumulativeTime
=
decodeTime
;
boolean
workaroundEveryVideoFrameIsSyncFrame
=
track
.
type
==
Track
.
TYPE_VIDEO
boolean
workaroundEveryVideoFrameIsSyncFrame
=
track
.
type
==
Track
.
TYPE_VIDEO
&&
((
workaroundFlags
&
WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
)
&&
((
workaroundFlags
&
WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
)
==
WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
);
==
WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
);
for
(
int
i
=
0
;
i
<
numberOfEntries
;
i
++)
{
for
(
int
i
=
0
;
i
<
sampleCount
;
i
++)
{
// Use trun values if present, otherwise tfhd, otherwise trex.
// Use trun values if present, otherwise tfhd, otherwise trex.
int
sampleDuration
=
sampleDurationsPresent
?
trun
.
readUnsignedIntToInt
()
int
sampleDuration
=
sampleDurationsPresent
?
trun
.
readUnsignedIntToInt
()
:
defaultSampleValues
.
duration
;
:
defaultSampleValues
.
duration
;
...
@@ -933,18 +924,15 @@ public final class FragmentedMp4Extractor {
...
@@ -933,18 +924,15 @@ public final class FragmentedMp4Extractor {
int
sampleFlags
=
(
i
==
0
&&
firstSampleFlagsPresent
)
?
firstSampleFlags
int
sampleFlags
=
(
i
==
0
&&
firstSampleFlagsPresent
)
?
firstSampleFlags
:
sampleFlagsPresent
?
trun
.
readInt
()
:
defaultSampleValues
.
flags
;
:
sampleFlagsPresent
?
trun
.
readInt
()
:
defaultSampleValues
.
flags
;
if
(
sampleCompositionTimeOffsetsPresent
)
{
if
(
sampleCompositionTimeOffsetsPresent
)
{
int
sampleOffset
;
// The BMFF spec (ISO 14496-12) states that sample offsets should be unsigned integers in
if
(
version
==
0
)
{
// version 0 trun boxes, however a significant number of streams violate the spec and use
// The BMFF spec (ISO 14496-12) states that sample offsets should be unsigned integers in
// signed integers instead. It's safe to always parse sample offsets as signed integers
// version 0 trun boxes, however a significant number of streams violate the spec and use
// here, because unsigned integers will still be parsed correctly (unless their top bit is
// signed integers instead. It's safe to always parse sample offsets as signed integers
// set, which is never true in practice because sample offsets are always small).
// here, because unsigned integers will still be parsed correctly (unless their top bit is
int
sampleOffset
=
trun
.
readInt
();
// set, which is never true in practice because sample offsets are always small).
sampleOffset
=
trun
.
readInt
();
}
else
{
sampleOffset
=
trun
.
readInt
();
}
sampleCompositionTimeOffsetTable
[
i
]
=
(
int
)
((
sampleOffset
*
1000
)
/
timescale
);
sampleCompositionTimeOffsetTable
[
i
]
=
(
int
)
((
sampleOffset
*
1000
)
/
timescale
);
}
else
{
sampleCompositionTimeOffsetTable
[
i
]
=
0
;
}
}
sampleDecodingTimeTable
[
i
]
=
(
int
)
((
cumulativeTime
*
1000
)
/
timescale
);
sampleDecodingTimeTable
[
i
]
=
(
int
)
((
cumulativeTime
*
1000
)
/
timescale
);
sampleSizeTable
[
i
]
=
sampleSize
;
sampleSizeTable
[
i
]
=
sampleSize
;
...
@@ -952,18 +940,15 @@ public final class FragmentedMp4Extractor {
...
@@ -952,18 +940,15 @@ public final class FragmentedMp4Extractor {
&&
(!
workaroundEveryVideoFrameIsSyncFrame
||
i
==
0
);
&&
(!
workaroundEveryVideoFrameIsSyncFrame
||
i
==
0
);
cumulativeTime
+=
sampleDuration
;
cumulativeTime
+=
sampleDuration
;
}
}
out
.
setSampleTables
(
sampleSizeTable
,
sampleDecodingTimeTable
,
sampleCompositionTimeOffsetTable
,
sampleIsSyncFrameTable
);
}
}
private
static
void
parseUuid
(
ParsableByteArray
uuid
,
TrackFragment
out
)
{
private
static
void
parseUuid
(
ParsableByteArray
uuid
,
TrackFragment
out
,
byte
[]
extendedTypeScratch
)
{
uuid
.
setPosition
(
ATOM_HEADER_SIZE
);
uuid
.
setPosition
(
ATOM_HEADER_SIZE
);
byte
[]
extendedType
=
new
byte
[
16
];
uuid
.
readBytes
(
extendedTypeScratch
,
0
,
16
);
uuid
.
readBytes
(
extendedType
,
0
,
16
);
// Currently this parser only supports Microsoft's PIFF SampleEncryptionBox.
// Currently this parser only supports Microsoft's PIFF SampleEncryptionBox.
if
(!
Arrays
.
equals
(
extendedType
,
PIFF_SAMPLE_ENCRYPTION_BOX_EXTENDED_TYPE
))
{
if
(!
Arrays
.
equals
(
extendedType
Scratch
,
PIFF_SAMPLE_ENCRYPTION_BOX_EXTENDED_TYPE
))
{
return
;
return
;
}
}
...
@@ -993,14 +978,9 @@ public final class FragmentedMp4Extractor {
...
@@ -993,14 +978,9 @@ public final class FragmentedMp4Extractor {
throw
new
IllegalStateException
(
"Length mismatch: "
+
sampleCount
+
", "
+
out
.
length
);
throw
new
IllegalStateException
(
"Length mismatch: "
+
sampleCount
+
", "
+
out
.
length
);
}
}
boolean
[]
sampleHasSubsampleEncryptionTable
=
new
boolean
[
sampleCount
];
Arrays
.
fill
(
out
.
sampleHasSubsampleEncryptionTable
,
0
,
sampleCount
,
subsampleEncryption
);
Arrays
.
fill
(
sampleHasSubsampleEncryptionTable
,
subsampleEncryption
);
out
.
initEncryptionData
(
senc
.
length
()
-
senc
.
getPosition
());
out
.
fillEncryptionData
(
senc
);
int
sampleEncryptionDataLength
=
senc
.
length
()
-
senc
.
getPosition
();
ParsableByteArray
sampleEncryptionData
=
new
ParsableByteArray
(
sampleEncryptionDataLength
);
senc
.
readBytes
(
sampleEncryptionData
.
getData
(),
0
,
sampleEncryptionDataLength
);
out
.
setSampleEncryptionData
(
sampleHasSubsampleEncryptionTable
,
sampleEncryptionData
,
false
);
}
}
/**
/**
...
@@ -1060,13 +1040,10 @@ public final class FragmentedMp4Extractor {
...
@@ -1060,13 +1040,10 @@ public final class FragmentedMp4Extractor {
}
}
private
int
readEncryptionData
(
NonBlockingInputStream
inputStream
)
{
private
int
readEncryptionData
(
NonBlockingInputStream
inputStream
)
{
ParsableByteArray
sampleEncryptionData
=
fragmentRun
.
sampleEncryptionData
;
boolean
success
=
fragmentRun
.
fillEncryptionData
(
inputStream
);
int
sampleEncryptionDataLength
=
sampleEncryptionData
.
length
();
if
(!
success
)
{
if
(
inputStream
.
getAvailableByteCount
()
<
sampleEncryptionDataLength
)
{
return
RESULT_NEED_MORE_DATA
;
return
RESULT_NEED_MORE_DATA
;
}
}
inputStream
.
read
(
sampleEncryptionData
.
getData
(),
0
,
sampleEncryptionDataLength
);
fragmentRun
.
sampleEncryptionDataNeedsFill
=
false
;
enterState
(
STATE_READING_SAMPLE
);
enterState
(
STATE_READING_SAMPLE
);
return
0
;
return
0
;
}
}
...
@@ -1105,8 +1082,8 @@ public final class FragmentedMp4Extractor {
...
@@ -1105,8 +1082,8 @@ public final class FragmentedMp4Extractor {
}
}
private
int
skipSample
(
NonBlockingInputStream
inputStream
,
int
sampleSize
)
{
private
int
skipSample
(
NonBlockingInputStream
inputStream
,
int
sampleSize
)
{
ParsableByteArray
sampleEncryptionData
=
fragmentRun
.
sampleEncryptionData
;
if
(
fragmentRun
.
definesEncryptionData
)
{
if
(
sampleEncryptionData
!=
null
)
{
ParsableByteArray
sampleEncryptionData
=
fragmentRun
.
sampleEncryptionData
;
TrackEncryptionBox
encryptionBox
=
TrackEncryptionBox
encryptionBox
=
track
.
sampleDescriptionEncryptionBoxes
[
fragmentRun
.
sampleDescriptionIndex
];
track
.
sampleDescriptionEncryptionBoxes
[
fragmentRun
.
sampleDescriptionIndex
];
int
vectorSize
=
encryptionBox
.
initializationVectorSize
;
int
vectorSize
=
encryptionBox
.
initializationVectorSize
;
...
@@ -1141,9 +1118,8 @@ public final class FragmentedMp4Extractor {
...
@@ -1141,9 +1118,8 @@ public final class FragmentedMp4Extractor {
outputData
=
ByteBuffer
.
allocate
(
sampleSize
);
outputData
=
ByteBuffer
.
allocate
(
sampleSize
);
out
.
data
=
outputData
;
out
.
data
=
outputData
;
}
}
ParsableByteArray
sampleEncryptionData
=
fragmentRun
.
sampleEncryptionData
;
if
(
fragmentRun
.
definesEncryptionData
)
{
if
(
sampleEncryptionData
!=
null
)
{
readSampleEncryptionData
(
fragmentRun
.
sampleEncryptionData
,
out
);
readSampleEncryptionData
(
sampleEncryptionData
,
out
);
}
}
if
(
outputData
==
null
)
{
if
(
outputData
==
null
)
{
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/ParsableByteArray.java
View file @
4a745b1c
...
@@ -23,17 +23,14 @@ import java.nio.ByteBuffer;
...
@@ -23,17 +23,14 @@ import java.nio.ByteBuffer;
*/
*/
/* package */
final
class
ParsableByteArray
{
/* package */
final
class
ParsableByteArray
{
private
final
byte
[]
data
;
public
byte
[]
data
;
private
int
position
;
private
int
position
;
public
ParsableByteArray
(
int
length
)
{
public
ParsableByteArray
(
int
length
)
{
this
.
data
=
new
byte
[
length
];
this
.
data
=
new
byte
[
length
];
}
}
public
byte
[]
getData
()
{
return
data
;
}
public
int
length
()
{
public
int
length
()
{
return
data
.
length
;
return
data
.
length
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/TrackEncryptionBox.java
View file @
4a745b1c
...
@@ -18,7 +18,7 @@ package com.google.android.exoplayer.parser.mp4;
...
@@ -18,7 +18,7 @@ package com.google.android.exoplayer.parser.mp4;
/**
/**
* Encapsulates information parsed from a track encryption (tenc) box in an MP4 stream.
* Encapsulates information parsed from a track encryption (tenc) box in an MP4 stream.
*/
*/
public
class
TrackEncryptionBox
{
public
final
class
TrackEncryptionBox
{
/**
/**
* Indicates the encryption state of the samples in the sample group.
* Indicates the encryption state of the samples in the sample group.
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/TrackFragment.java
View file @
4a745b1c
...
@@ -15,41 +15,136 @@
...
@@ -15,41 +15,136 @@
*/
*/
package
com
.
google
.
android
.
exoplayer
.
parser
.
mp4
;
package
com
.
google
.
android
.
exoplayer
.
parser
.
mp4
;
import
com.google.android.exoplayer.upstream.NonBlockingInputStream
;
/**
/**
* A holder for information corresponding to a single fragment of an mp4 file.
* A holder for information corresponding to a single fragment of an mp4 file.
*/
*/
/* package */
class
TrackFragment
{
/* package */
final
class
TrackFragment
{
public
int
sampleDescriptionIndex
;
public
int
sampleDescriptionIndex
;
/**
* The number of samples contained by the fragment.
*/
public
int
length
;
public
int
length
;
/**
* The size of each sample in the run.
*/
public
int
[]
sampleSizeTable
;
public
int
[]
sampleSizeTable
;
/**
* The decoding time of each sample in the run.
*/
public
int
[]
sampleDecodingTimeTable
;
public
int
[]
sampleDecodingTimeTable
;
/**
* The composition time offset of each sample in the run.
*/
public
int
[]
sampleCompositionTimeOffsetTable
;
public
int
[]
sampleCompositionTimeOffsetTable
;
/**
* Indicates which samples are sync frames.
*/
public
boolean
[]
sampleIsSyncFrameTable
;
public
boolean
[]
sampleIsSyncFrameTable
;
/**
* True if the fragment defines encryption data. False otherwise.
*/
public
boolean
definesEncryptionData
;
/**
* If {@link #definesEncryptionData} is true, indicates which samples use sub-sample encryption.
* Undefined otherwise.
*/
public
boolean
[]
sampleHasSubsampleEncryptionTable
;
public
boolean
[]
sampleHasSubsampleEncryptionTable
;
/**
* If {@link #definesEncryptionData} is true, indicates the length of the sample encryption data.
* Undefined otherwise.
*/
public
int
sampleEncryptionDataLength
;
/**
* If {@link #definesEncryptionData} is true, contains binary sample encryption data. Undefined
* otherwise.
*/
public
ParsableByteArray
sampleEncryptionData
;
public
ParsableByteArray
sampleEncryptionData
;
/**
* Whether {@link #sampleEncryptionData} needs populating with the actual encryption data.
*/
public
boolean
sampleEncryptionDataNeedsFill
;
public
boolean
sampleEncryptionDataNeedsFill
;
public
void
setSampleDescriptionIndex
(
int
sampleDescriptionIndex
)
{
/**
this
.
sampleDescriptionIndex
=
sampleDescriptionIndex
;
* Resets the fragment.
* <p>
* The {@link #length} is set to 0, and both {@link #definesEncryptionData} and
* {@link #sampleEncryptionDataNeedsFill} is set to false.
*/
public
void
reset
()
{
length
=
0
;
definesEncryptionData
=
false
;
sampleEncryptionDataNeedsFill
=
false
;
}
/**
* Configures the fragment for the specified number of samples.
* <p>
* The {@link #length} of the fragment is set to the specified sample count, and the contained
* tables are resized if necessary such that they are at least this length.
*
* @param sampleCount The number of samples in the new run.
*/
public
void
initTables
(
int
sampleCount
)
{
length
=
sampleCount
;
if
(
sampleSizeTable
==
null
||
sampleSizeTable
.
length
<
length
)
{
// Size the tables 25% larger than needed, so as to make future resize operations less
// likely. The choice of 25% is relatively arbitrary.
int
tableSize
=
(
sampleCount
*
125
)
/
100
;
sampleSizeTable
=
new
int
[
tableSize
];
sampleDecodingTimeTable
=
new
int
[
tableSize
];
sampleCompositionTimeOffsetTable
=
new
int
[
tableSize
];
sampleIsSyncFrameTable
=
new
boolean
[
tableSize
];
sampleHasSubsampleEncryptionTable
=
new
boolean
[
tableSize
];
}
}
/**
* Configures the fragment to be one that defines encryption data of the specified length.
* <p>
* {@link #definesEncryptionData} is set to true, {@link #sampleEncryptionDataLength} is set to
* the specified length, and {@link #sampleEncryptionData} is resized if necessary such that it
* is at least this length.
*
* @param length The length in bytes of the encryption data.
*/
public
void
initEncryptionData
(
int
length
)
{
if
(
sampleEncryptionData
==
null
||
sampleEncryptionData
.
length
()
<
length
)
{
sampleEncryptionData
=
new
ParsableByteArray
(
length
);
}
sampleEncryptionDataLength
=
length
;
definesEncryptionData
=
true
;
sampleEncryptionDataNeedsFill
=
true
;
}
}
public
void
setSampleTables
(
int
[]
sampleSizeTable
,
int
[]
sampleDecodingTimeTable
,
/**
int
[]
sampleCompositionTimeOffsetTable
,
boolean
[]
sampleIsSyncFrameTable
)
{
* Fills {@link #sampleEncryptionData} from the provided source.
this
.
sampleSizeTable
=
sampleSizeTable
;
*
this
.
sampleDecodingTimeTable
=
sampleDecodingTimeTable
;
* @param source A source from which to read the encryption data.
this
.
sampleCompositionTimeOffsetTable
=
sampleCompositionTimeOffsetTable
;
*/
this
.
sampleIsSyncFrameTable
=
sampleIsSyncFrameTable
;
public
void
fillEncryptionData
(
ParsableByteArray
source
)
{
this
.
length
=
sampleSizeTable
.
length
;
source
.
readBytes
(
sampleEncryptionData
.
data
,
0
,
sampleEncryptionDataLength
);
sampleEncryptionData
.
setPosition
(
0
);
sampleEncryptionDataNeedsFill
=
false
;
}
}
public
void
setSampleEncryptionData
(
boolean
[]
sampleHasSubsampleEncryptionTable
,
/**
ParsableByteArray
sampleEncryptionData
,
boolean
sampleEncryptionDataNeedsFill
)
{
* Fills {@link #sampleEncryptionData} for the current run from the provided source.
this
.
sampleHasSubsampleEncryptionTable
=
sampleHasSubsampleEncryptionTable
;
*
this
.
sampleEncryptionData
=
sampleEncryptionData
;
* @param source A source from which to read the encryption data.
this
.
sampleEncryptionDataNeedsFill
=
sampleEncryptionDataNeedsFill
;
* @return True if the encryption data was filled. False if the source had insufficient data.
*/
public
boolean
fillEncryptionData
(
NonBlockingInputStream
source
)
{
if
(
source
.
getAvailableByteCount
()
<
sampleEncryptionDataLength
)
{
return
false
;
}
source
.
read
(
sampleEncryptionData
.
data
,
0
,
sampleEncryptionDataLength
);
sampleEncryptionData
.
setPosition
(
0
);
sampleEncryptionDataNeedsFill
=
false
;
return
true
;
}
}
public
int
getSamplePresentationTime
(
int
index
)
{
public
int
getSamplePresentationTime
(
int
index
)
{
...
...
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