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
a4ff13d7
authored
Jun 26, 2015
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Set a MIME type based on the esds ObjectTypeIndication.
Issue: #576
parent
a626a5e5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
79 additions
and
32 deletions
library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java
library/src/main/java/com/google/android/exoplayer/extractor/mp4/Mp4Extractor.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/AdtsReader.java
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
library/src/main/java/com/google/android/exoplayer/util/CodecSpecificDataUtil.java
library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java
View file @
a4ff13d7
...
...
@@ -64,8 +64,9 @@ import java.util.List;
long
mediaTimescale
=
parseMdhd
(
mdia
.
getLeafAtomOfType
(
Atom
.
TYPE_mdhd
).
data
);
StsdDataHolder
stsdData
=
parseStsd
(
stbl
.
getLeafAtomOfType
(
Atom
.
TYPE_stsd
).
data
,
durationUs
);
return
new
Track
(
id
,
trackType
,
mediaTimescale
,
durationUs
,
stsdData
.
mediaFormat
,
stsdData
.
trackEncryptionBoxes
,
stsdData
.
nalUnitLengthFieldLength
);
return
stsdData
.
mediaFormat
==
null
?
null
:
new
Track
(
id
,
trackType
,
mediaTimescale
,
durationUs
,
stsdData
.
mediaFormat
,
stsdData
.
trackEncryptionBoxes
,
stsdData
.
nalUnitLengthFieldLength
);
}
/**
...
...
@@ -388,9 +389,10 @@ import java.util.List;
out
.
nalUnitLengthFieldLength
=
hvcCData
.
second
;
}
else
if
(
childAtomType
==
Atom
.
TYPE_esds
)
{
Assertions
.
checkState
(
mimeType
==
null
);
mimeType
=
MimeTypes
.
VIDEO_MP4V
;
initializationData
=
Collections
.
singletonList
(
parseEsdsFromParent
(
parent
,
childStartPosition
));
Pair
<
String
,
byte
[]>
mimeTypeAndInitializationData
=
parseEsdsFromParent
(
parent
,
childStartPosition
);
mimeType
=
mimeTypeAndInitializationData
.
first
;
initializationData
=
Collections
.
singletonList
(
mimeTypeAndInitializationData
.
second
);
}
else
if
(
childAtomType
==
Atom
.
TYPE_sinf
)
{
out
.
trackEncryptionBoxes
[
entryIndex
]
=
parseSinfFromParent
(
parent
,
childStartPosition
,
childAtomSize
);
...
...
@@ -399,6 +401,12 @@ import java.util.List;
}
childPosition
+=
childAtomSize
;
}
// If the media type was not recognized, ignore the track.
if
(
mimeType
==
null
)
{
return
;
}
out
.
mediaFormat
=
MediaFormat
.
createVideoFormat
(
mimeType
,
MediaFormat
.
NO_VALUE
,
durationUs
,
width
,
height
,
pixelWidthHeightRatio
,
initializationData
);
}
...
...
@@ -529,6 +537,14 @@ import java.util.List;
parent
.
skipBytes
(
4
);
int
sampleRate
=
parent
.
readUnsignedFixedPoint1616
();
// If the atom type determines a MIME type, set it immediately.
String
mimeType
=
null
;
if
(
atomType
==
Atom
.
TYPE_ac_3
)
{
mimeType
=
MimeTypes
.
AUDIO_AC3
;
}
else
if
(
atomType
==
Atom
.
TYPE_ec_3
)
{
mimeType
=
MimeTypes
.
AUDIO_EC3
;
}
byte
[]
initializationData
=
null
;
int
childPosition
=
parent
.
getPosition
();
while
(
childPosition
-
position
<
size
)
{
...
...
@@ -539,13 +555,18 @@ import java.util.List;
int
childAtomType
=
parent
.
readInt
();
if
(
atomType
==
Atom
.
TYPE_mp4a
||
atomType
==
Atom
.
TYPE_enca
)
{
if
(
childAtomType
==
Atom
.
TYPE_esds
)
{
initializationData
=
parseEsdsFromParent
(
parent
,
childStartPosition
);
// TODO: Do we really need to do this? See [Internal: b/10903778]
// Update sampleRate and channelCount from the AudioSpecificConfig initialization data.
Pair
<
Integer
,
Integer
>
audioSpecificConfig
=
CodecSpecificDataUtil
.
parseAudioSpecificConfig
(
initializationData
);
sampleRate
=
audioSpecificConfig
.
first
;
channelCount
=
audioSpecificConfig
.
second
;
Pair
<
String
,
byte
[]>
mimeTypeAndInitializationData
=
parseEsdsFromParent
(
parent
,
childStartPosition
);
mimeType
=
mimeTypeAndInitializationData
.
first
;
initializationData
=
mimeTypeAndInitializationData
.
second
;
if
(
MimeTypes
.
AUDIO_AAC
.
equals
(
mimeType
))
{
// TODO: Do we really need to do this? See [Internal: b/10903778]
// Update sampleRate and channelCount from the AudioSpecificConfig initialization data.
Pair
<
Integer
,
Integer
>
audioSpecificConfig
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
initializationData
);
sampleRate
=
audioSpecificConfig
.
first
;
channelCount
=
audioSpecificConfig
.
second
;
}
}
else
if
(
childAtomType
==
Atom
.
TYPE_sinf
)
{
out
.
trackEncryptionBoxes
[
entryIndex
]
=
parseSinfFromParent
(
parent
,
childStartPosition
,
childAtomSize
);
...
...
@@ -564,14 +585,9 @@ import java.util.List;
childPosition
+=
childAtomSize
;
}
// Set the MIME type for ac-3/ec-3 atoms even if the dac3/dec3 child atom is missing.
String
mimeType
;
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
;
// If the media type was not recognized, ignore the track.
if
(
mimeType
==
null
)
{
return
;
}
out
.
mediaFormat
=
MediaFormat
.
createAudioFormat
(
mimeType
,
sampleSize
,
durationUs
,
channelCount
,
...
...
@@ -580,7 +596,7 @@ import java.util.List;
}
/** Returns codec-specific initialization data contained in an esds box. */
private
static
byte
[]
parseEsdsFromParent
(
ParsableByteArray
parent
,
int
position
)
{
private
static
Pair
<
String
,
byte
[]>
parseEsdsFromParent
(
ParsableByteArray
parent
,
int
position
)
{
parent
.
setPosition
(
position
+
Atom
.
HEADER_SIZE
+
4
);
// Start of the ES_Descriptor (defined in 14496-1)
parent
.
skipBytes
(
1
);
// ES_Descriptor tag
...
...
@@ -607,9 +623,40 @@ import java.util.List;
while
(
varIntByte
>
127
)
{
varIntByte
=
parent
.
readUnsignedByte
();
}
parent
.
skipBytes
(
13
);
// Start of AudioSpecificConfig (defined in 14496-3)
// Set the MIME type based on the object type indication (14496-1 table 5).
int
objectTypeIndication
=
parent
.
readUnsignedByte
();
String
mimeType
;
switch
(
objectTypeIndication
)
{
case
0x20
:
mimeType
=
MimeTypes
.
VIDEO_MP4V
;
break
;
case
0x21
:
mimeType
=
MimeTypes
.
VIDEO_H264
;
break
;
case
0x23
:
mimeType
=
MimeTypes
.
VIDEO_H265
;
break
;
case
0x40
:
mimeType
=
MimeTypes
.
AUDIO_AAC
;
break
;
case
0x6B
:
mimeType
=
MimeTypes
.
AUDIO_MPEG
;
break
;
case
0xA5
:
mimeType
=
MimeTypes
.
AUDIO_AC3
;
break
;
case
0xA6
:
mimeType
=
MimeTypes
.
AUDIO_EC3
;
break
;
default
:
mimeType
=
null
;
break
;
}
parent
.
skipBytes
(
12
);
// Start of the AudioSpecificConfig.
parent
.
skipBytes
(
1
);
// AudioSpecificConfig tag
varIntByte
=
parent
.
readUnsignedByte
();
int
varInt
=
varIntByte
&
0x7F
;
...
...
@@ -620,7 +667,7 @@ import java.util.List;
}
byte
[]
initializationData
=
new
byte
[
varInt
];
parent
.
readBytes
(
initializationData
,
0
,
varInt
);
return
initializationData
;
return
Pair
.
create
(
mimeType
,
initializationData
)
;
}
private
AtomParsers
()
{
...
...
library/src/main/java/com/google/android/exoplayer/extractor/mp4/Mp4Extractor.java
View file @
a4ff13d7
...
...
@@ -225,8 +225,8 @@ public final class Mp4Extractor implements Extractor, SeekMap {
}
Track
track
=
AtomParsers
.
parseTrak
(
atom
,
moov
.
getLeafAtomOfType
(
Atom
.
TYPE_mvhd
));
if
(
track
==
null
||
track
.
mediaFormat
==
null
||
(
track
.
type
!=
Track
.
TYPE_AUDI
O
&&
track
.
type
!=
Track
.
TYPE_
VIDEO
&&
track
.
type
!=
Track
.
TYPE_
TEXT
))
{
if
(
track
==
null
||
(
track
.
type
!=
Track
.
TYPE_AUDIO
&&
track
.
type
!=
Track
.
TYPE_VIDE
O
&&
track
.
type
!=
Track
.
TYPE_TEXT
))
{
continue
;
}
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/AdtsReader.java
View file @
a4ff13d7
...
...
@@ -165,9 +165,9 @@ import java.util.Collections;
adtsScratch
.
skipBits
(
1
);
int
channelConfig
=
adtsScratch
.
readBits
(
3
);
byte
[]
audioSpecificConfig
=
CodecSpecificDataUtil
.
buildAudioSpecificConfig
(
byte
[]
audioSpecificConfig
=
CodecSpecificDataUtil
.
buildA
acA
udioSpecificConfig
(
audioObjectType
,
sampleRateIndex
,
channelConfig
);
Pair
<
Integer
,
Integer
>
audioParams
=
CodecSpecificDataUtil
.
parseAudioSpecificConfig
(
Pair
<
Integer
,
Integer
>
audioParams
=
CodecSpecificDataUtil
.
parseA
acA
udioSpecificConfig
(
audioSpecificConfig
);
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
MimeTypes
.
AUDIO_AAC
,
...
...
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
View file @
a4ff13d7
...
...
@@ -388,7 +388,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
if
(
trackElement
.
csd
!=
null
)
{
csd
=
Arrays
.
asList
(
trackElement
.
csd
);
}
else
{
csd
=
Collections
.
singletonList
(
CodecSpecificDataUtil
.
buildAudioSpecificConfig
(
csd
=
Collections
.
singletonList
(
CodecSpecificDataUtil
.
buildA
acA
udioSpecificConfig
(
trackFormat
.
audioSamplingRate
,
trackFormat
.
numChannels
));
}
MediaFormat
format
=
MediaFormat
.
createAudioFormat
(
mimeType
,
MediaFormat
.
NO_VALUE
,
...
...
library/src/main/java/com/google/android/exoplayer/util/CodecSpecificDataUtil.java
View file @
a4ff13d7
...
...
@@ -47,7 +47,7 @@ public final class CodecSpecificDataUtil {
* @param audioSpecificConfig The AudioSpecificConfig to parse.
* @return A pair consisting of the sample rate in Hz and the channel count.
*/
public
static
Pair
<
Integer
,
Integer
>
parseAudioSpecificConfig
(
byte
[]
audioSpecificConfig
)
{
public
static
Pair
<
Integer
,
Integer
>
parseA
acA
udioSpecificConfig
(
byte
[]
audioSpecificConfig
)
{
int
audioObjectType
=
(
audioSpecificConfig
[
0
]
>>
3
)
&
0x1F
;
int
byteOffset
=
audioObjectType
==
5
||
audioObjectType
==
29
?
1
:
0
;
int
frequencyIndex
=
(
audioSpecificConfig
[
byteOffset
]
&
0x7
)
<<
1
...
...
@@ -66,7 +66,7 @@ public final class CodecSpecificDataUtil {
* @param channelConfig The channel configuration.
* @return The AudioSpecificConfig.
*/
public
static
byte
[]
buildAudioSpecificConfig
(
int
audioObjectType
,
int
sampleRateIndex
,
public
static
byte
[]
buildA
acA
udioSpecificConfig
(
int
audioObjectType
,
int
sampleRateIndex
,
int
channelConfig
)
{
byte
[]
audioSpecificConfig
=
new
byte
[
2
];
audioSpecificConfig
[
0
]
=
(
byte
)
((
audioObjectType
<<
3
)
&
0xF8
|
(
sampleRateIndex
>>
1
)
&
0x07
);
...
...
@@ -81,7 +81,7 @@ public final class CodecSpecificDataUtil {
* @param numChannels The number of channels.
* @return The AudioSpecificConfig.
*/
public
static
byte
[]
buildAudioSpecificConfig
(
int
sampleRate
,
int
numChannels
)
{
public
static
byte
[]
buildA
acA
udioSpecificConfig
(
int
sampleRate
,
int
numChannels
)
{
int
sampleRateIndex
=
-
1
;
for
(
int
i
=
0
;
i
<
AUDIO_SPECIFIC_CONFIG_SAMPLING_RATE_TABLE
.
length
;
++
i
)
{
if
(
sampleRate
==
AUDIO_SPECIFIC_CONFIG_SAMPLING_RATE_TABLE
[
i
])
{
...
...
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