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
d14e11c5
authored
Nov 13, 2014
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Additional extraction for AC3
parent
456d53e1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
117 additions
and
20 deletions
library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
View file @
d14e11c5
...
@@ -24,6 +24,10 @@ import java.util.ArrayList;
...
@@ -24,6 +24,10 @@ import java.util.ArrayList;
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_mp4a
=
0x6D703461
;
public
static
final
int
TYPE_mp4a
=
0x6D703461
;
public
static
final
int
TYPE_ac_3
=
0x61632D33
;
// ac-3
public
static
final
int
TYPE_dac3
=
0x64616333
;
public
static
final
int
TYPE_ec_3
=
0x65632D33
;
// ec-3
public
static
final
int
TYPE_dec3
=
0x64656333
;
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
;
public
static
final
int
TYPE_trex
=
0x74726578
;
public
static
final
int
TYPE_trex
=
0x74726578
;
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
View file @
d14e11c5
...
@@ -65,6 +65,11 @@ public final class FragmentedMp4Extractor implements Extractor {
...
@@ -65,6 +65,11 @@ public final class FragmentedMp4Extractor implements Extractor {
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
};
private
static
final
byte
[]
PIFF_SAMPLE_ENCRYPTION_BOX_EXTENDED_TYPE
=
private
static
final
byte
[]
PIFF_SAMPLE_ENCRYPTION_BOX_EXTENDED_TYPE
=
new
byte
[]
{-
94
,
57
,
79
,
82
,
90
,
-
101
,
79
,
20
,
-
94
,
68
,
108
,
66
,
124
,
100
,
-
115
,
-
12
};
new
byte
[]
{-
94
,
57
,
79
,
82
,
90
,
-
101
,
79
,
20
,
-
94
,
68
,
108
,
66
,
124
,
100
,
-
115
,
-
12
};
/** Channel counts for AC-3 audio, indexed by acmod. (See ETSI TS 102 366.) */
private
static
final
int
[]
AC3_CHANNEL_COUNTS
=
new
int
[]
{
2
,
1
,
2
,
3
,
3
,
4
,
4
,
5
};
/** Nominal bit-rates for AC-3 audio in kbps, indexed by bit_rate_code. (See ETSI TS 102 366.) */
private
static
final
int
[]
AC3_BIT_RATES
=
new
int
[]
{
32
,
40
,
48
,
56
,
64
,
80
,
96
,
112
,
128
,
160
,
192
,
224
,
256
,
320
,
384
,
448
,
512
,
576
,
640
};
// Parser states
// Parser states
private
static
final
int
STATE_READING_ATOM_HEADER
=
0
;
private
static
final
int
STATE_READING_ATOM_HEADER
=
0
;
...
@@ -512,11 +517,12 @@ public final class FragmentedMp4Extractor implements Extractor {
...
@@ -512,11 +517,12 @@ public final class FragmentedMp4Extractor implements Extractor {
parseAvcFromParent
(
stsd
,
childStartPosition
,
childAtomSize
);
parseAvcFromParent
(
stsd
,
childStartPosition
,
childAtomSize
);
mediaFormat
=
avc
.
first
;
mediaFormat
=
avc
.
first
;
trackEncryptionBoxes
[
i
]
=
avc
.
second
;
trackEncryptionBoxes
[
i
]
=
avc
.
second
;
}
else
if
(
childAtomType
==
Atom
.
TYPE_mp4a
||
childAtomType
==
Atom
.
TYPE_enca
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_mp4a
||
childAtomType
==
Atom
.
TYPE_enca
Pair
<
MediaFormat
,
TrackEncryptionBox
>
mp4a
=
||
childAtomType
==
Atom
.
TYPE_ac_3
)
{
parseMp4aFromParent
(
stsd
,
childStartPosition
,
childAtomSize
);
Pair
<
MediaFormat
,
TrackEncryptionBox
>
audioSampleEntry
=
mediaFormat
=
mp4a
.
first
;
parseAudioSampleEntry
(
stsd
,
childAtomType
,
childStartPosition
,
childAtomSize
);
trackEncryptionBoxes
[
i
]
=
mp4a
.
second
;
mediaFormat
=
audioSampleEntry
.
first
;
trackEncryptionBoxes
[
i
]
=
audioSampleEntry
.
second
;
}
}
stsd
.
setPosition
(
childStartPosition
+
childAtomSize
);
stsd
.
setPosition
(
childStartPosition
+
childAtomSize
);
}
}
...
@@ -556,15 +562,15 @@ public final class FragmentedMp4Extractor implements Extractor {
...
@@ -556,15 +562,15 @@ public final class FragmentedMp4Extractor implements Extractor {
return
Pair
.
create
(
format
,
trackEncryptionBox
);
return
Pair
.
create
(
format
,
trackEncryptionBox
);
}
}
private
static
Pair
<
MediaFormat
,
TrackEncryptionBox
>
parse
Mp4aFromParent
(
ParsableByteArray
parent
,
private
static
Pair
<
MediaFormat
,
TrackEncryptionBox
>
parse
AudioSampleEntry
(
int
position
,
int
size
)
{
ParsableByteArray
parent
,
int
atomType
,
int
position
,
int
size
)
{
parent
.
setPosition
(
position
+
ATOM_HEADER_SIZE
);
parent
.
setPosition
(
position
+
ATOM_HEADER_SIZE
);
// Start of the mp4a atom (defined in 14496-14)
parent
.
skip
(
16
);
parent
.
skip
(
16
);
int
channelCount
=
parent
.
readUnsignedShort
();
int
channelCount
=
parent
.
readUnsignedShort
();
int
sampleSize
=
parent
.
readUnsignedShort
();
int
sampleSize
=
parent
.
readUnsignedShort
();
parent
.
skip
(
4
);
parent
.
skip
(
4
);
int
sampleRate
=
parent
.
readUnsignedFixedPoint1616
();
int
sampleRate
=
parent
.
readUnsignedFixedPoint1616
();
int
bitrate
=
MediaFormat
.
NO_VALUE
;
byte
[]
initializationData
=
null
;
byte
[]
initializationData
=
null
;
TrackEncryptionBox
trackEncryptionBox
=
null
;
TrackEncryptionBox
trackEncryptionBox
=
null
;
...
@@ -574,25 +580,97 @@ public final class FragmentedMp4Extractor implements Extractor {
...
@@ -574,25 +580,97 @@ public final class FragmentedMp4Extractor implements Extractor {
int
childStartPosition
=
parent
.
getPosition
();
int
childStartPosition
=
parent
.
getPosition
();
int
childAtomSize
=
parent
.
readInt
();
int
childAtomSize
=
parent
.
readInt
();
int
childAtomType
=
parent
.
readInt
();
int
childAtomType
=
parent
.
readInt
();
if
(
childAtomType
==
Atom
.
TYPE_esds
)
{
if
(
atomType
==
Atom
.
TYPE_mp4a
||
atomType
==
Atom
.
TYPE_enca
)
{
initializationData
=
parseEsdsFromParent
(
parent
,
childStartPosition
);
if
(
childAtomType
==
Atom
.
TYPE_esds
)
{
// TODO: Do we really need to do this? See [redacted]
initializationData
=
parseEsdsFromParent
(
parent
,
childStartPosition
);
// Update sampleRate and channelCount from the AudioSpecificConfig initialization data.
// TODO: Do we really need to do this? See [redacted]
Pair
<
Integer
,
Integer
>
audioSpecificConfig
=
// Update sampleRate and channelCount from the AudioSpecificConfig initialization data.
CodecSpecificDataUtil
.
parseAudioSpecificConfig
(
initializationData
);
Pair
<
Integer
,
Integer
>
audioSpecificConfig
=
sampleRate
=
audioSpecificConfig
.
first
;
CodecSpecificDataUtil
.
parseAudioSpecificConfig
(
initializationData
);
channelCount
=
audioSpecificConfig
.
second
;
sampleRate
=
audioSpecificConfig
.
first
;
}
else
if
(
childAtomType
==
Atom
.
TYPE_sinf
)
{
channelCount
=
audioSpecificConfig
.
second
;
trackEncryptionBox
=
parseSinfFromParent
(
parent
,
childStartPosition
,
childAtomSize
);
}
else
if
(
childAtomType
==
Atom
.
TYPE_sinf
)
{
trackEncryptionBox
=
parseSinfFromParent
(
parent
,
childStartPosition
,
childAtomSize
);
}
}
else
if
(
atomType
==
Atom
.
TYPE_ac_3
&&
childAtomType
==
Atom
.
TYPE_dac3
)
{
// TODO: Choose the right AC-3 track based on the contents of dac3/dec3.
Ac3Format
ac3Format
=
parseAc3SpecificBoxFromParent
(
parent
,
childStartPosition
);
if
(
ac3Format
!=
null
)
{
sampleRate
=
ac3Format
.
sampleRate
;
channelCount
=
ac3Format
.
channelCount
;
bitrate
=
ac3Format
.
bitrate
;
}
// TODO: Add support for encrypted AC-3.
trackEncryptionBox
=
null
;
}
else
if
(
atomType
==
Atom
.
TYPE_ec_3
&&
childAtomType
==
Atom
.
TYPE_dec3
)
{
sampleRate
=
parseEc3SpecificBoxFromParent
(
parent
,
childStartPosition
);
trackEncryptionBox
=
null
;
}
}
childPosition
+=
childAtomSize
;
childPosition
+=
childAtomSize
;
}
}
MediaFormat
format
=
MediaFormat
.
createAudioFormat
(
"audio/mp4a-latm"
,
sampleSize
,
channelCount
,
String
mimeType
;
sampleRate
,
Collections
.
singletonList
(
initializationData
));
if
(
atomType
==
Atom
.
TYPE_ac_3
)
{
mimeType
=
MimeTypes
.
AUDIO_AC3
;
}
else
if
(
atomType
==
Atom
.
TYPE_ec_3
)
{
mimeType
=
MimeTypes
.
AUDIO_EC3
;
}
else
{
mimeType
=
MimeTypes
.
AUDIO_AAC
;
}
MediaFormat
format
=
MediaFormat
.
createAudioFormat
(
mimeType
,
sampleSize
,
channelCount
,
sampleRate
,
bitrate
,
initializationData
==
null
?
null
:
Collections
.
singletonList
(
initializationData
));
return
Pair
.
create
(
format
,
trackEncryptionBox
);
return
Pair
.
create
(
format
,
trackEncryptionBox
);
}
}
private
static
Ac3Format
parseAc3SpecificBoxFromParent
(
ParsableByteArray
parent
,
int
position
)
{
// Start of the dac3 atom (defined in ETSI TS 102 366)
parent
.
setPosition
(
position
+
ATOM_HEADER_SIZE
);
// fscod (sample rate code)
int
fscod
=
(
parent
.
readUnsignedByte
()
&
0xC0
)
>>
6
;
int
sampleRate
;
switch
(
fscod
)
{
case
0
:
sampleRate
=
48000
;
break
;
case
1
:
sampleRate
=
44100
;
break
;
case
2
:
sampleRate
=
32000
;
break
;
default
:
// TODO: The decoder should not use this stream.
return
null
;
}
int
nextByte
=
parent
.
readUnsignedByte
();
// Map acmod (audio coding mode) onto a channel count.
int
channelCount
=
AC3_CHANNEL_COUNTS
[(
nextByte
&
0x38
)
>>
3
];
// lfeon (low frequency effects on)
if
((
nextByte
&
0x04
)
!=
0
)
{
channelCount
++;
}
// Map bit_rate_code onto a bit-rate in kbit/s.
int
bitrate
=
AC3_BIT_RATES
[((
nextByte
&
0x03
)
<<
3
)
+
(
parent
.
readUnsignedByte
()
>>
5
)];
return
new
Ac3Format
(
channelCount
,
sampleRate
,
bitrate
);
}
private
static
int
parseEc3SpecificBoxFromParent
(
ParsableByteArray
parent
,
int
position
)
{
// Start of the dec3 atom (defined in ETSI TS 102 366)
parent
.
setPosition
(
position
+
ATOM_HEADER_SIZE
);
// TODO: Implement parsing for enhanced AC-3 with multiple sub-streams.
return
0
;
}
private
static
List
<
byte
[]>
parseAvcCFromParent
(
ParsableByteArray
parent
,
int
position
)
{
private
static
List
<
byte
[]>
parseAvcCFromParent
(
ParsableByteArray
parent
,
int
position
)
{
parent
.
setPosition
(
position
+
ATOM_HEADER_SIZE
+
4
);
parent
.
setPosition
(
position
+
ATOM_HEADER_SIZE
+
4
);
// Start of the AVCDecoderConfigurationRecord (defined in 14496-15)
// Start of the AVCDecoderConfigurationRecord (defined in 14496-15)
...
@@ -1182,4 +1260,19 @@ public final class FragmentedMp4Extractor implements Extractor {
...
@@ -1182,4 +1260,19 @@ public final class FragmentedMp4Extractor implements Extractor {
return
result
;
return
result
;
}
}
/** Represents the format for AC-3 audio. */
private
static
final
class
Ac3Format
{
public
final
int
channelCount
;
public
final
int
sampleRate
;
public
final
int
bitrate
;
public
Ac3Format
(
int
channelCount
,
int
sampleRate
,
int
bitrate
)
{
this
.
channelCount
=
channelCount
;
this
.
sampleRate
=
sampleRate
;
this
.
bitrate
=
bitrate
;
}
}
}
}
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