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
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
121 additions
and
37 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 {
/**
* @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
* {@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
* {@link Integer#MAX_VALUE}.
* @param format See {@link #format}.
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
View file @
4a745b1c
...
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer
.
parser
.
mp4
;
import
java.util.ArrayList
;
import
java.util.List
;
/* package */
abstract
class
Atom
{
...
...
@@ -24,7 +23,6 @@ import java.util.List;
public
static
final
int
TYPE_avc3
=
0x61766333
;
public
static
final
int
TYPE_esds
=
0x65736473
;
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_tfdt
=
0x74666474
;
public
static
final
int
TYPE_tfhd
=
0x74666864
;
...
...
@@ -64,17 +62,13 @@ import java.util.List;
public
final
static
class
LeafAtom
extends
Atom
{
p
rivate
final
ParsableByteArray
data
;
p
ublic
final
ParsableByteArray
data
;
public
LeafAtom
(
int
type
,
ParsableByteArray
data
)
{
super
(
type
);
this
.
data
=
data
;
}
public
ParsableByteArray
getData
()
{
return
data
;
}
}
public
final
static
class
ContainerAtom
extends
Atom
{
...
...
@@ -91,7 +85,8 @@ import java.util.List;
}
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
);
if
(
atom
.
type
==
type
)
{
return
(
LeafAtom
)
atom
;
...
...
@@ -101,7 +96,8 @@ import java.util.List;
}
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
);
if
(
atom
.
type
==
type
)
{
return
(
ContainerAtom
)
atom
;
...
...
@@ -110,10 +106,6 @@ import java.util.List;
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;
/**
* 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
};
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
View file @
4a745b1c
This diff is collapsed.
Click to expand it.
library/src/main/java/com/google/android/exoplayer/parser/mp4/ParsableByteArray.java
View file @
4a745b1c
...
...
@@ -23,17 +23,14 @@ import java.nio.ByteBuffer;
*/
/* package */
final
class
ParsableByteArray
{
private
final
byte
[]
data
;
public
byte
[]
data
;
private
int
position
;
public
ParsableByteArray
(
int
length
)
{
this
.
data
=
new
byte
[
length
];
}
public
byte
[]
getData
()
{
return
data
;
}
public
int
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;
/**
* 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.
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/TrackFragment.java
View file @
4a745b1c
...
...
@@ -15,41 +15,136 @@
*/
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.
*/
/* package */
class
TrackFragment
{
/* package */
final
class
TrackFragment
{
public
int
sampleDescriptionIndex
;
/**
* The number of samples contained by the fragment.
*/
public
int
length
;
/**
* The size of each sample in the run.
*/
public
int
[]
sampleSizeTable
;
/**
* The decoding time of each sample in the run.
*/
public
int
[]
sampleDecodingTimeTable
;
/**
* The composition time offset of each sample in the run.
*/
public
int
[]
sampleCompositionTimeOffsetTable
;
/**
* Indicates which samples are sync frames.
*/
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
;
/**
* 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
;
/**
* Whether {@link #sampleEncryptionData} needs populating with the actual encryption data.
*/
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
)
{
this
.
sampleSizeTable
=
sampleSizeTable
;
this
.
sampleDecodingTimeTable
=
sampleDecodingTimeTable
;
this
.
sampleCompositionTimeOffsetTable
=
sampleCompositionTimeOffsetTable
;
this
.
sampleIsSyncFrameTable
=
sampleIsSyncFrameTable
;
this
.
length
=
sampleSizeTable
.
length
;
/**
* Fills {@link #sampleEncryptionData} from the provided source.
*
* @param source A source from which to read the encryption data.
*/
public
void
fillEncryptionData
(
ParsableByteArray
source
)
{
source
.
readBytes
(
sampleEncryptionData
.
data
,
0
,
sampleEncryptionDataLength
);
sampleEncryptionData
.
setPosition
(
0
);
sampleEncryptionDataNeedsFill
=
false
;
}
public
void
setSampleEncryptionData
(
boolean
[]
sampleHasSubsampleEncryptionTable
,
ParsableByteArray
sampleEncryptionData
,
boolean
sampleEncryptionDataNeedsFill
)
{
this
.
sampleHasSubsampleEncryptionTable
=
sampleHasSubsampleEncryptionTable
;
this
.
sampleEncryptionData
=
sampleEncryptionData
;
this
.
sampleEncryptionDataNeedsFill
=
sampleEncryptionDataNeedsFill
;
/**
* Fills {@link #sampleEncryptionData} for the current run from the provided source.
*
* @param source A source from which to read the encryption data.
* @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
)
{
...
...
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