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
ad7237b5
authored
Nov 25, 2015
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Handle E-AC-3 audio in HLS.
parent
9fd575e1
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
41 additions
and
23 deletions
library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java
library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/Ac3Reader.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/AdtsReader.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/TsExtractor.java
library/src/main/java/com/google/android/exoplayer/util/Ac3Util.java
library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java
View file @
ad7237b5
...
@@ -941,9 +941,9 @@ public final class AudioTrack {
...
@@ -941,9 +941,9 @@ public final class AudioTrack {
|
((
buffer
.
get
(
buffer
.
position
()
+
5
)
&
0xFC
)
>>
2
);
|
((
buffer
.
get
(
buffer
.
position
()
+
5
)
&
0xFC
)
>>
2
);
return
(
nblks
+
1
)
*
32
;
return
(
nblks
+
1
)
*
32
;
}
else
if
(
encoding
==
C
.
ENCODING_AC3
)
{
}
else
if
(
encoding
==
C
.
ENCODING_AC3
)
{
return
Ac3Util
.
getAc3S
amplesPerSyncframe
();
return
Ac3Util
.
getAc3S
yncframeAudioSampleCount
();
}
else
if
(
encoding
==
C
.
ENCODING_E_AC3
)
{
}
else
if
(
encoding
==
C
.
ENCODING_E_AC3
)
{
return
Ac3Util
.
parseE
ac3SamplesPerSyncframe
(
buffer
);
return
Ac3Util
.
parseE
Ac3SyncframeAudioSampleCount
(
buffer
);
}
else
{
}
else
{
throw
new
IllegalStateException
(
"Unexpected audio encoding: "
+
encoding
);
throw
new
IllegalStateException
(
"Unexpected audio encoding: "
+
encoding
);
}
}
...
...
library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java
View file @
ad7237b5
...
@@ -774,12 +774,12 @@ import java.util.List;
...
@@ -774,12 +774,12 @@ import java.util.List;
// TODO: Choose the right AC-3 track based on the contents of dac3/dec3.
// TODO: Choose the right AC-3 track based on the contents of dac3/dec3.
// TODO: Add support for encryption (by setting out.trackEncryptionBoxes).
// TODO: Add support for encryption (by setting out.trackEncryptionBoxes).
parent
.
setPosition
(
Atom
.
HEADER_SIZE
+
childAtomPosition
);
parent
.
setPosition
(
Atom
.
HEADER_SIZE
+
childAtomPosition
);
out
.
mediaFormat
=
Ac3Util
.
parseA
nnexFAc3
Format
(
parent
,
Integer
.
toString
(
trackId
),
out
.
mediaFormat
=
Ac3Util
.
parseA
c3AnnexF
Format
(
parent
,
Integer
.
toString
(
trackId
),
durationUs
,
language
);
durationUs
,
language
);
return
;
return
;
}
else
if
(
atomType
==
Atom
.
TYPE_ec_3
&&
childAtomType
==
Atom
.
TYPE_dec3
)
{
}
else
if
(
atomType
==
Atom
.
TYPE_ec_3
&&
childAtomType
==
Atom
.
TYPE_dec3
)
{
parent
.
setPosition
(
Atom
.
HEADER_SIZE
+
childAtomPosition
);
parent
.
setPosition
(
Atom
.
HEADER_SIZE
+
childAtomPosition
);
out
.
mediaFormat
=
Ac3Util
.
parse
AnnexFEAc3
Format
(
parent
,
Integer
.
toString
(
trackId
),
out
.
mediaFormat
=
Ac3Util
.
parse
EAc3AnnexF
Format
(
parent
,
Integer
.
toString
(
trackId
),
durationUs
,
language
);
durationUs
,
language
);
return
;
return
;
}
else
if
((
atomType
==
Atom
.
TYPE_dtsc
||
atomType
==
Atom
.
TYPE_dtse
}
else
if
((
atomType
==
Atom
.
TYPE_dtsc
||
atomType
==
Atom
.
TYPE_dtse
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/Ac3Reader.java
View file @
ad7237b5
...
@@ -23,7 +23,7 @@ import com.google.android.exoplayer.util.ParsableBitArray;
...
@@ -23,7 +23,7 @@ import com.google.android.exoplayer.util.ParsableBitArray;
import
com.google.android.exoplayer.util.ParsableByteArray
;
import
com.google.android.exoplayer.util.ParsableByteArray
;
/**
/**
* Parses a continuous AC-3 byte stream and extracts individual samples.
* Parses a continuous
(E-)
AC-3 byte stream and extracts individual samples.
*/
*/
/* package */
final
class
Ac3Reader
extends
ElementaryStreamReader
{
/* package */
final
class
Ac3Reader
extends
ElementaryStreamReader
{
...
@@ -33,6 +33,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
...
@@ -33,6 +33,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
private
static
final
int
HEADER_SIZE
=
8
;
private
static
final
int
HEADER_SIZE
=
8
;
private
final
boolean
isEac3
;
private
final
ParsableBitArray
headerScratchBits
;
private
final
ParsableBitArray
headerScratchBits
;
private
final
ParsableByteArray
headerScratchBytes
;
private
final
ParsableByteArray
headerScratchBytes
;
...
@@ -43,16 +44,23 @@ import com.google.android.exoplayer.util.ParsableByteArray;
...
@@ -43,16 +44,23 @@ import com.google.android.exoplayer.util.ParsableByteArray;
private
boolean
lastByteWas0B
;
private
boolean
lastByteWas0B
;
// Used when parsing the header.
// Used when parsing the header.
private
long
fram
eDurationUs
;
private
long
sampl
eDurationUs
;
private
MediaFormat
mediaFormat
;
private
MediaFormat
mediaFormat
;
private
int
sampleSize
;
private
int
sampleSize
;
private
int
bitrate
;
// Used when reading the samples.
// Used when reading the samples.
private
long
timeUs
;
private
long
timeUs
;
public
Ac3Reader
(
TrackOutput
output
)
{
/**
* Constructs a new reader for (E-)AC-3 elementary streams.
*
* @param output Track output for extracted samples.
* @param isEac3 Whether the stream is E-AC-3 (ETSI TS 102 366 Annex E). Specify {@code false} to
* parse sample headers as AC-3.
*/
public
Ac3Reader
(
TrackOutput
output
,
boolean
isEac3
)
{
super
(
output
);
super
(
output
);
this
.
isEac3
=
isEac3
;
headerScratchBits
=
new
ParsableBitArray
(
new
byte
[
HEADER_SIZE
]);
headerScratchBits
=
new
ParsableBitArray
(
new
byte
[
HEADER_SIZE
]);
headerScratchBytes
=
new
ParsableByteArray
(
headerScratchBits
.
data
);
headerScratchBytes
=
new
ParsableByteArray
(
headerScratchBits
.
data
);
state
=
STATE_FINDING_SYNC
;
state
=
STATE_FINDING_SYNC
;
...
@@ -94,7 +102,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
...
@@ -94,7 +102,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
bytesRead
+=
bytesToRead
;
bytesRead
+=
bytesToRead
;
if
(
bytesRead
==
sampleSize
)
{
if
(
bytesRead
==
sampleSize
)
{
output
.
sampleMetadata
(
timeUs
,
C
.
SAMPLE_FLAG_SYNC
,
sampleSize
,
0
,
null
);
output
.
sampleMetadata
(
timeUs
,
C
.
SAMPLE_FLAG_SYNC
,
sampleSize
,
0
,
null
);
timeUs
+=
fram
eDurationUs
;
timeUs
+=
sampl
eDurationUs
;
state
=
STATE_FINDING_SYNC
;
state
=
STATE_FINDING_SYNC
;
}
}
break
;
break
;
...
@@ -124,11 +132,11 @@ import com.google.android.exoplayer.util.ParsableByteArray;
...
@@ -124,11 +132,11 @@ import com.google.android.exoplayer.util.ParsableByteArray;
}
}
/**
/**
* Locates the next sync
word, advancing the position to the byte that immediately follows it.
* Locates the next sync
word, advancing the position to the byte that immediately follows it. If a
*
If a sync
word was not located, the position is advanced to the limit.
*
sync
word was not located, the position is advanced to the limit.
*
*
* @param pesBuffer The buffer whose position should be advanced.
* @param pesBuffer The buffer whose position should be advanced.
* @return True if a sync
word position was found. False otherwise.
* @return True if a syncword position was found. False otherwise.
*/
*/
private
boolean
skipToNextSync
(
ParsableByteArray
pesBuffer
)
{
private
boolean
skipToNextSync
(
ParsableByteArray
pesBuffer
)
{
while
(
pesBuffer
.
bytesLeft
()
>
0
)
{
while
(
pesBuffer
.
bytesLeft
()
>
0
)
{
...
@@ -151,15 +159,21 @@ import com.google.android.exoplayer.util.ParsableByteArray;
...
@@ -151,15 +159,21 @@ import com.google.android.exoplayer.util.ParsableByteArray;
* Parses the sample header.
* Parses the sample header.
*/
*/
private
void
parseHeader
()
{
private
void
parseHeader
()
{
headerScratchBits
.
setPosition
(
0
);
sampleSize
=
Ac3Util
.
parseFrameSize
(
headerScratchBits
);
if
(
mediaFormat
==
null
)
{
if
(
mediaFormat
==
null
)
{
headerScratchBits
.
setPosition
(
0
);
mediaFormat
=
isEac3
mediaFormat
=
Ac3Util
.
parseFrameAc3Format
(
headerScratchBits
,
null
,
C
.
UNKNOWN_TIME_US
,
null
);
?
Ac3Util
.
parseEac3SyncframeFormat
(
headerScratchBits
,
null
,
C
.
UNKNOWN_TIME_US
,
null
)
:
Ac3Util
.
parseAc3SyncframeFormat
(
headerScratchBits
,
null
,
C
.
UNKNOWN_TIME_US
,
null
);
output
.
format
(
mediaFormat
);
output
.
format
(
mediaFormat
);
bitrate
=
Ac3Util
.
getBitrate
(
sampleSize
,
mediaFormat
.
sampleRate
);
}
}
frameDurationUs
=
(
int
)
(
1000L
*
8
*
sampleSize
/
bitrate
);
sampleSize
=
isEac3
?
Ac3Util
.
parseEAc3SyncframeSize
(
headerScratchBits
.
data
)
:
Ac3Util
.
parseAc3SyncframeSize
(
headerScratchBits
.
data
);
int
audioSamplesPerSyncframe
=
isEac3
?
Ac3Util
.
parseEAc3SyncframeAudioSampleCount
(
headerScratchBits
.
data
)
:
Ac3Util
.
getAc3SyncframeAudioSampleCount
();
// In this class a sample is an access unit (syncframe in AC-3), but the MediaFormat sample rate
// specifies the number of PCM audio samples per second.
sampleDurationUs
=
(
int
)
(
C
.
MICROS_PER_SECOND
*
audioSamplesPerSyncframe
/
mediaFormat
.
sampleRate
);
}
}
}
}
library/src/main/java/com/google/android/exoplayer/extractor/ts/AdtsReader.java
View file @
ad7237b5
...
@@ -50,7 +50,7 @@ import java.util.Collections;
...
@@ -50,7 +50,7 @@ import java.util.Collections;
// Used when parsing the header.
// Used when parsing the header.
private
boolean
hasOutputFormat
;
private
boolean
hasOutputFormat
;
private
long
fram
eDurationUs
;
private
long
sampl
eDurationUs
;
private
int
sampleSize
;
private
int
sampleSize
;
// Used when reading the samples.
// Used when reading the samples.
...
@@ -96,7 +96,7 @@ import java.util.Collections;
...
@@ -96,7 +96,7 @@ import java.util.Collections;
bytesRead
+=
bytesToRead
;
bytesRead
+=
bytesToRead
;
if
(
bytesRead
==
sampleSize
)
{
if
(
bytesRead
==
sampleSize
)
{
output
.
sampleMetadata
(
timeUs
,
C
.
SAMPLE_FLAG_SYNC
,
sampleSize
,
0
,
null
);
output
.
sampleMetadata
(
timeUs
,
C
.
SAMPLE_FLAG_SYNC
,
sampleSize
,
0
,
null
);
timeUs
+=
fram
eDurationUs
;
timeUs
+=
sampl
eDurationUs
;
bytesRead
=
0
;
bytesRead
=
0
;
state
=
STATE_FINDING_SYNC
;
state
=
STATE_FINDING_SYNC
;
}
}
...
@@ -173,7 +173,9 @@ import java.util.Collections;
...
@@ -173,7 +173,9 @@ import java.util.Collections;
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
null
,
MimeTypes
.
AUDIO_AAC
,
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
null
,
MimeTypes
.
AUDIO_AAC
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
audioParams
.
second
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
audioParams
.
second
,
audioParams
.
first
,
Collections
.
singletonList
(
audioSpecificConfig
),
null
);
audioParams
.
first
,
Collections
.
singletonList
(
audioSpecificConfig
),
null
);
frameDurationUs
=
(
C
.
MICROS_PER_SECOND
*
1024L
)
/
mediaFormat
.
sampleRate
;
// 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
)
/
mediaFormat
.
sampleRate
;
output
.
format
(
mediaFormat
);
output
.
format
(
mediaFormat
);
hasOutputFormat
=
true
;
hasOutputFormat
=
true
;
}
else
{
}
else
{
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/TsExtractor.java
View file @
ad7237b5
...
@@ -310,9 +310,11 @@ public final class TsExtractor implements Extractor {
...
@@ -310,9 +310,11 @@ public final class TsExtractor implements Extractor {
case
TS_STREAM_TYPE_AAC:
case
TS_STREAM_TYPE_AAC:
pesPayloadReader
=
new
AdtsReader
(
output
.
track
(
TS_STREAM_TYPE_AAC
));
pesPayloadReader
=
new
AdtsReader
(
output
.
track
(
TS_STREAM_TYPE_AAC
));
break
;
break
;
case
TS_STREAM_TYPE_E_AC3:
case
TS_STREAM_TYPE_AC3:
case
TS_STREAM_TYPE_AC3:
pesPayloadReader
=
new
Ac3Reader
(
output
.
track
(
streamType
));
pesPayloadReader
=
new
Ac3Reader
(
output
.
track
(
TS_STREAM_TYPE_AC3
),
false
);
break
;
case
TS_STREAM_TYPE_E_AC3:
pesPayloadReader
=
new
Ac3Reader
(
output
.
track
(
TS_STREAM_TYPE_E_AC3
),
true
);
break
;
break
;
case
TS_STREAM_TYPE_H262:
case
TS_STREAM_TYPE_H262:
pesPayloadReader
=
new
H262Reader
(
output
.
track
(
TS_STREAM_TYPE_H262
));
pesPayloadReader
=
new
H262Reader
(
output
.
track
(
TS_STREAM_TYPE_H262
));
...
...
library/src/main/java/com/google/android/exoplayer/util/Ac3Util.java
View file @
ad7237b5
This diff is collapsed.
Click to expand it.
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