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
bd8ee155
authored
Feb 27, 2020
by
andrewlewis
Committed by
kim-vde
Feb 27, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Construct codecs string for AAC in MP4/TS/FLV
PiperOrigin-RevId: 297578984
parent
c6a6e0d6
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
87 additions
and
40 deletions
library/common/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java
library/common/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java
View file @
bd8ee155
...
...
@@ -23,11 +23,26 @@ import java.util.ArrayList;
import
java.util.Collections
;
import
java.util.List
;
/**
* Provides static utility methods for manipulating various types of codec specific data.
*/
/** Provides utilities for handling various types of codec-specific data. */
public
final
class
CodecSpecificDataUtil
{
/** Holds sample format information for AAC audio. */
public
static
final
class
AacConfig
{
/** The sample rate in Hertz. */
public
final
int
sampleRateHz
;
/** The number of channels. */
public
final
int
channelCount
;
/** The RFC 6381 codecs string. */
public
final
String
codecs
;
private
AacConfig
(
int
sampleRateHz
,
int
channelCount
,
String
codecs
)
{
this
.
sampleRateHz
=
sampleRateHz
;
this
.
channelCount
=
channelCount
;
this
.
codecs
=
codecs
;
}
}
private
static
final
byte
[]
NAL_START_CODE
=
new
byte
[]
{
0
,
0
,
0
,
1
};
private
static
final
int
AUDIO_SPECIFIC_CONFIG_FREQUENCY_INDEX_ARBITRARY
=
0xF
;
...
...
@@ -70,14 +85,20 @@ public final class CodecSpecificDataUtil {
AUDIO_SPECIFIC_CONFIG_CHANNEL_CONFIGURATION_INVALID
};
/**
* Prefix for the RFC 6381 codecs string for AAC formats. To form a full codecs string, suffix the
* decimal AudioObjectType.
*/
private
static
final
String
AAC_CODECS_STRING_PREFIX
=
"mp4a.40."
;
// Advanced Audio Coding Low-Complexity profile.
private
static
final
int
AUDIO_OBJECT_TYPE_AAC_LC
=
2
;
// Spectral Band Replication.
private
static
final
int
AUDIO_OBJECT_TYPE_SBR
=
5
;
private
static
final
int
AUDIO_OBJECT_TYPE_
AAC_
SBR
=
5
;
// Error Resilient Bit-Sliced Arithmetic Coding.
private
static
final
int
AUDIO_OBJECT_TYPE_ER_BSAC
=
22
;
private
static
final
int
AUDIO_OBJECT_TYPE_
AAC_
ER_BSAC
=
22
;
// Parametric Stereo.
private
static
final
int
AUDIO_OBJECT_TYPE_PS
=
29
;
private
static
final
int
AUDIO_OBJECT_TYPE_
AAC_
PS
=
29
;
// Escape code for extended audio object types.
private
static
final
int
AUDIO_OBJECT_TYPE_ESCAPE
=
31
;
...
...
@@ -87,12 +108,13 @@ public final class CodecSpecificDataUtil {
* Parses an AAC AudioSpecificConfig, as defined in ISO 14496-3 1.6.2.1
*
* @param audioSpecificConfig A byte array containing the AudioSpecificConfig to parse.
* @return
A pair consisting of the sample rate in Hz and the channel count
.
* @return
The parsed configuration
.
* @throws ParserException If the AudioSpecificConfig cannot be parsed as it's not supported.
*/
public
static
Pair
<
Integer
,
Integer
>
parseAacAudioSpecificConfig
(
byte
[]
audioSpecificConfig
)
public
static
AacConfig
parseAacAudioSpecificConfig
(
byte
[]
audioSpecificConfig
)
throws
ParserException
{
return
parseAacAudioSpecificConfig
(
new
ParsableBitArray
(
audioSpecificConfig
),
false
);
return
parseAacAudioSpecificConfig
(
new
ParsableBitArray
(
audioSpecificConfig
),
/* forceReadToEnd= */
false
);
}
/**
...
...
@@ -102,23 +124,25 @@ public final class CodecSpecificDataUtil {
* position is advanced to the end of the AudioSpecificConfig.
* @param forceReadToEnd Whether the entire AudioSpecificConfig should be read. Required for
* knowing the length of the configuration payload.
* @return
A pair consisting of the sample rate in Hz and the channel count
.
* @return
The parsed configuration
.
* @throws ParserException If the AudioSpecificConfig cannot be parsed as it's not supported.
*/
public
static
Pair
<
Integer
,
Integer
>
parseAacAudioSpecificConfig
(
public
static
AacConfig
parseAacAudioSpecificConfig
(
ParsableBitArray
bitArray
,
boolean
forceReadToEnd
)
throws
ParserException
{
int
audioObjectType
=
getAacAudioObjectType
(
bitArray
);
int
sampleRate
=
getAacSamplingFrequency
(
bitArray
);
int
sampleRate
Hz
=
getAacSamplingFrequency
(
bitArray
);
int
channelConfiguration
=
bitArray
.
readBits
(
4
);
if
(
audioObjectType
==
AUDIO_OBJECT_TYPE_SBR
||
audioObjectType
==
AUDIO_OBJECT_TYPE_PS
)
{
String
codecs
=
AAC_CODECS_STRING_PREFIX
+
audioObjectType
;
if
(
audioObjectType
==
AUDIO_OBJECT_TYPE_AAC_SBR
||
audioObjectType
==
AUDIO_OBJECT_TYPE_AAC_PS
)
{
// For an AAC bitstream using spectral band replication (SBR) or parametric stereo (PS) with
// explicit signaling, we return the extension sampling frequency as the sample rate of the
// content; this is identical to the sample rate of the decoded output but may differ from
// the sample rate set above.
// Use the extensionSamplingFrequencyIndex.
sampleRate
=
getAacSamplingFrequency
(
bitArray
);
sampleRate
Hz
=
getAacSamplingFrequency
(
bitArray
);
audioObjectType
=
getAacAudioObjectType
(
bitArray
);
if
(
audioObjectType
==
AUDIO_OBJECT_TYPE_ER_BSAC
)
{
if
(
audioObjectType
==
AUDIO_OBJECT_TYPE_
AAC_
ER_BSAC
)
{
// Use the extensionChannelConfiguration.
channelConfiguration
=
bitArray
.
readBits
(
4
);
}
...
...
@@ -160,7 +184,7 @@ public final class CodecSpecificDataUtil {
// For supported containers, bits_to_decode() is always 0.
int
channelCount
=
AUDIO_SPECIFIC_CONFIG_CHANNEL_COUNT_TABLE
[
channelConfiguration
];
Assertions
.
checkArgument
(
channelCount
!=
AUDIO_SPECIFIC_CONFIG_CHANNEL_CONFIGURATION_INVALID
);
return
Pair
.
create
(
sampleRate
,
channelCount
);
return
new
AacConfig
(
sampleRateHz
,
channelCount
,
codecs
);
}
/**
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java
View file @
bd8ee155
...
...
@@ -15,12 +15,12 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
flv
;
import
android.util.Pair
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.ParserException
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil.AacConfig
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
java.util.Collections
;
...
...
@@ -109,11 +109,16 @@ import java.util.Collections;
// Parse the sequence header.
byte
[]
audioSpecificConfig
=
new
byte
[
data
.
bytesLeft
()];
data
.
readBytes
(
audioSpecificConfig
,
0
,
audioSpecificConfig
.
length
);
Pair
<
Integer
,
Integer
>
audioParams
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
audioSpecificConfig
);
Format
format
=
Format
.
createAudioSampleFormat
(
null
,
MimeTypes
.
AUDIO_AAC
,
null
,
Format
.
NO_VALUE
,
Format
.
NO_VALUE
,
audioParams
.
second
,
audioParams
.
first
,
Collections
.
singletonList
(
audioSpecificConfig
),
null
,
0
,
null
);
AacConfig
aacConfig
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
audioSpecificConfig
);
Format
format
=
new
Format
.
Builder
()
.
setSampleMimeType
(
MimeTypes
.
AUDIO_AAC
)
.
setCodecs
(
aacConfig
.
codecs
)
.
setChannelCount
(
aacConfig
.
channelCount
)
.
setSampleRate
(
aacConfig
.
sampleRateHz
)
.
setInitializationData
(
Collections
.
singletonList
(
audioSpecificConfig
))
.
build
();
output
.
format
(
format
);
hasOutputFormat
=
true
;
return
false
;
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
View file @
bd8ee155
...
...
@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.extractor.GaplessInfoHolder;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil.AacConfig
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
...
...
@@ -1086,6 +1087,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
int
channelCount
;
int
sampleRate
;
@C
.
PcmEncoding
int
pcmEncoding
=
Format
.
NO_VALUE
;
@Nullable
String
codecs
=
null
;
if
(
quickTimeSoundDescriptionVersion
==
0
||
quickTimeSoundDescriptionVersion
==
1
)
{
channelCount
=
parent
.
readUnsignedShort
();
...
...
@@ -1182,10 +1184,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
if
(
MimeTypes
.
AUDIO_AAC
.
equals
(
mimeType
)
&&
initializationData
!=
null
)
{
// Update sampleRate and channelCount from the AudioSpecificConfig initialization data,
// which is more reliable. See [Internal: b/10903778].
Pair
<
Integer
,
Integer
>
audioSpecifi
cConfig
=
AacConfig
aa
cConfig
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
initializationData
);
sampleRate
=
audioSpecificConfig
.
first
;
channelCount
=
audioSpecificConfig
.
second
;
sampleRate
=
aacConfig
.
sampleRateHz
;
channelCount
=
aacConfig
.
channelCount
;
codecs
=
aacConfig
.
codecs
;
}
}
}
else
if
(
childAtomType
==
Atom
.
TYPE_dac3
)
{
...
...
@@ -1237,10 +1240,19 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
if
(
out
.
format
==
null
&&
mimeType
!=
null
)
{
out
.
format
=
Format
.
createAudioSampleFormat
(
Integer
.
toString
(
trackId
),
mimeType
,
null
,
Format
.
NO_VALUE
,
Format
.
NO_VALUE
,
channelCount
,
sampleRate
,
pcmEncoding
,
initializationData
==
null
?
null
:
Collections
.
singletonList
(
initializationData
),
drmInitData
,
0
,
language
);
out
.
format
=
new
Format
.
Builder
()
.
setId
(
Integer
.
toString
(
trackId
))
.
setSampleMimeType
(
mimeType
)
.
setCodecs
(
codecs
)
.
setChannelCount
(
channelCount
)
.
setSampleRate
(
sampleRate
)
.
setPcmEncoding
(
pcmEncoding
)
.
setInitializationData
(
initializationData
==
null
?
null
:
Collections
.
singletonList
(
initializationData
))
.
setDrmInitData
(
drmInitData
)
.
setLanguage
(
language
)
.
build
();
}
}
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java
View file @
bd8ee155
...
...
@@ -15,7 +15,6 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
import
android.util.Pair
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
...
...
@@ -26,6 +25,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput;
import
com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil.AacConfig
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.ParsableBitArray
;
...
...
@@ -469,12 +469,17 @@ public final class AdtsReader implements ElementaryStreamReader {
byte
[]
audioSpecificConfig
=
CodecSpecificDataUtil
.
buildAacAudioSpecificConfig
(
audioObjectType
,
firstFrameSampleRateIndex
,
channelConfig
);
Pair
<
Integer
,
Integer
>
audioParams
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
audioSpecificConfig
);
Format
format
=
Format
.
createAudioSampleFormat
(
formatId
,
MimeTypes
.
AUDIO_AAC
,
null
,
Format
.
NO_VALUE
,
Format
.
NO_VALUE
,
audioParams
.
second
,
audioParams
.
first
,
Collections
.
singletonList
(
audioSpecificConfig
),
null
,
0
,
language
);
AacConfig
aacConfig
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
audioSpecificConfig
);
Format
format
=
new
Format
.
Builder
()
.
setId
(
formatId
)
.
setSampleMimeType
(
MimeTypes
.
AUDIO_AAC
)
.
setCodecs
(
aacConfig
.
codecs
)
.
setChannelCount
(
aacConfig
.
channelCount
)
.
setSampleRate
(
aacConfig
.
sampleRateHz
)
.
setInitializationData
(
Collections
.
singletonList
(
audioSpecificConfig
))
.
setLanguage
(
language
)
.
build
();
// In this class a sample is an access unit, but the MediaFormat sample rate specifies the
// number of PCM audio samples per second.
sampleDurationUs
=
(
C
.
MICROS_PER_SECOND
*
1024
)
/
format
.
sampleRate
;
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java
View file @
bd8ee155
...
...
@@ -15,7 +15,6 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
import
android.util.Pair
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
...
...
@@ -25,6 +24,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput;
import
com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil.AacConfig
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.ParsableBitArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
...
...
@@ -273,9 +273,10 @@ public final class LatmReader implements ElementaryStreamReader {
private
int
parseAudioSpecificConfig
(
ParsableBitArray
data
)
throws
ParserException
{
int
bitsLeft
=
data
.
bitsLeft
();
Pair
<
Integer
,
Integer
>
config
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
data
,
true
);
sampleRateHz
=
config
.
first
;
channelCount
=
config
.
second
;
AacConfig
config
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
data
,
/* forceReadToEnd= */
true
);
sampleRateHz
=
config
.
sampleRateHz
;
channelCount
=
config
.
channelCount
;
return
bitsLeft
-
data
.
bitsLeft
();
}
...
...
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