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
e2722dee
authored
Sep 07, 2016
by
Sergio Moreno Mozota
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
TsExtractor support for language code in the audio tracks.
parent
c54169c1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
103 additions
and
31 deletions
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java
View file @
e2722dee
...
...
@@ -33,6 +33,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
static
final
int
HEADER_SIZE
=
8
;
private
String
language
;
private
final
ParsableBitArray
headerScratchBits
;
private
final
ParsableByteArray
headerScratchBytes
;
...
...
@@ -57,10 +59,21 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
* @param output Track output for extracted samples.
*/
public
Ac3Reader
(
TrackOutput
output
)
{
this
(
output
,
null
);
}
/**
* Constructs a new reader for (E-)AC-3 elementary streams.
*
* @param output Track output for extracted samples.
* @param language Track language.
*/
public
Ac3Reader
(
TrackOutput
output
,
String
language
)
{
super
(
output
);
headerScratchBits
=
new
ParsableBitArray
(
new
byte
[
HEADER_SIZE
]);
headerScratchBytes
=
new
ParsableByteArray
(
headerScratchBits
.
data
);
state
=
STATE_FINDING_SYNC
;
this
.
language
=
language
;
}
@Override
...
...
@@ -163,8 +176,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
headerScratchBits
.
skipBits
(
40
);
isEac3
=
headerScratchBits
.
readBits
(
5
)
==
16
;
headerScratchBits
.
setPosition
(
headerScratchBits
.
getPosition
()
-
45
);
format
=
isEac3
?
Ac3Util
.
parseEac3SyncframeFormat
(
headerScratchBits
,
null
,
null
,
null
)
:
Ac3Util
.
parseAc3SyncframeFormat
(
headerScratchBits
,
null
,
null
,
null
);
format
=
isEac3
?
Ac3Util
.
parseEac3SyncframeFormat
(
headerScratchBits
,
null
,
language
,
null
)
:
Ac3Util
.
parseAc3SyncframeFormat
(
headerScratchBits
,
null
,
language
,
null
);
output
.
format
(
format
);
}
sampleSize
=
isEac3
?
Ac3Util
.
parseEAc3SyncframeSize
(
headerScratchBits
.
data
)
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java
View file @
e2722dee
...
...
@@ -42,6 +42,8 @@ import java.util.Collections;
private
static
final
int
HEADER_SIZE
=
5
;
private
static
final
int
CRC_SIZE
=
2
;
private
String
language
;
// Match states used while looking for the next sample
private
static
final
int
MATCH_STATE_VALUE_SHIFT
=
8
;
private
static
final
int
MATCH_STATE_START
=
1
<<
MATCH_STATE_VALUE_SHIFT
;
...
...
@@ -80,6 +82,15 @@ import java.util.Collections;
* @param id3Output A {@link TrackOutput} to which ID3 samples should be written.
*/
public
AdtsReader
(
TrackOutput
output
,
TrackOutput
id3Output
)
{
this
(
output
,
id3Output
,
null
);
}
/**
* @param output A {@link TrackOutput} to which AAC samples should be written.
* @param id3Output A {@link TrackOutput} to which ID3 samples should be written.
* @param language Track language.
*/
public
AdtsReader
(
TrackOutput
output
,
TrackOutput
id3Output
,
String
language
)
{
super
(
output
);
this
.
id3Output
=
id3Output
;
id3Output
.
format
(
Format
.
createSampleFormat
(
null
,
MimeTypes
.
APPLICATION_ID3
,
null
,
...
...
@@ -87,6 +98,7 @@ import java.util.Collections;
adtsScratch
=
new
ParsableBitArray
(
new
byte
[
HEADER_SIZE
+
CRC_SIZE
]);
id3HeaderBuffer
=
new
ParsableByteArray
(
Arrays
.
copyOf
(
ID3_IDENTIFIER
,
ID3_HEADER_SIZE
));
setFindingSampleState
();
this
.
language
=
language
;
}
@Override
...
...
@@ -278,7 +290,7 @@ import java.util.Collections;
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
);
Collections
.
singletonList
(
audioSpecificConfig
),
null
,
0
,
language
);
// 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/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java
View file @
e2722dee
...
...
@@ -34,6 +34,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
static
final
int
SYNC_VALUE
=
0x7FFE8001
;
private
static
final
int
SYNC_VALUE_SIZE
=
4
;
private
String
language
;
private
final
ParsableByteArray
headerScratchBytes
;
private
int
state
;
...
...
@@ -56,6 +58,16 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
* @param output Track output for extracted samples.
*/
public
DtsReader
(
TrackOutput
output
)
{
this
(
output
,
null
);
}
/**
* Constructs a new reader for DTS elementary streams.
*
* @param output Track output for extracted samples.
* @param language Track language.
*/
public
DtsReader
(
TrackOutput
output
,
String
language
)
{
super
(
output
);
headerScratchBytes
=
new
ParsableByteArray
(
new
byte
[
HEADER_SIZE
]);
headerScratchBytes
.
data
[
0
]
=
(
byte
)
((
SYNC_VALUE
>>
24
)
&
0xFF
);
...
...
@@ -63,6 +75,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
headerScratchBytes
.
data
[
2
]
=
(
byte
)
((
SYNC_VALUE
>>
8
)
&
0xFF
);
headerScratchBytes
.
data
[
3
]
=
(
byte
)
(
SYNC_VALUE
&
0xFF
);
state
=
STATE_FINDING_SYNC
;
this
.
language
=
language
;
}
@Override
...
...
@@ -155,7 +168,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
void
parseHeader
()
{
byte
[]
frameData
=
headerScratchBytes
.
data
;
if
(
format
==
null
)
{
format
=
DtsUtil
.
parseDtsFormat
(
frameData
,
null
,
null
,
null
);
format
=
DtsUtil
.
parseDtsFormat
(
frameData
,
null
,
language
,
null
);
output
.
format
(
format
);
}
sampleSize
=
DtsUtil
.
getDtsFrameSize
(
frameData
);
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java
View file @
e2722dee
...
...
@@ -32,6 +32,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
static
final
int
HEADER_SIZE
=
4
;
private
String
language
;
private
final
ParsableByteArray
headerScratch
;
private
final
MpegAudioHeader
header
;
...
...
@@ -50,12 +52,17 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
long
timeUs
;
public
MpegAudioReader
(
TrackOutput
output
)
{
this
(
output
,
null
);
}
public
MpegAudioReader
(
TrackOutput
output
,
String
language
)
{
super
(
output
);
state
=
STATE_FINDING_HEADER
;
// The first byte of an MPEG Audio frame header is always 0xFF.
headerScratch
=
new
ParsableByteArray
(
4
);
headerScratch
.
data
[
0
]
=
(
byte
)
0xFF
;
header
=
new
MpegAudioHeader
();
this
.
language
=
language
;
}
@Override
...
...
@@ -164,7 +171,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
frameDurationUs
=
(
C
.
MICROS_PER_SECOND
*
header
.
samplesPerFrame
)
/
header
.
sampleRate
;
Format
format
=
Format
.
createAudioSampleFormat
(
null
,
header
.
mimeType
,
null
,
Format
.
NO_VALUE
,
MpegAudioHeader
.
MAX_FRAME_SIZE_BYTES
,
header
.
channels
,
header
.
sampleRate
,
null
,
null
,
0
,
null
);
language
);
output
.
format
(
format
);
hasOutputFormat
=
true
;
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
View file @
e2722dee
...
...
@@ -334,6 +334,32 @@ public final class TsExtractor implements Extractor {
private
int
sectionBytesRead
;
private
int
crc
;
private
static
final
int
TS_PMT_DESC_REGISTRATION
=
0x05
;
private
static
final
int
TS_PMT_DESC_ISO639_LANG
=
0x0A
;
private
static
final
int
TS_PMT_DESC_VBI_DATA
=
0x45
;
private
static
final
int
TS_PMT_DESC_VBI_TELETEXT
=
0x46
;
private
static
final
int
TS_PMT_DESC_TELETEXT
=
0x56
;
private
static
final
int
TS_PMT_DESC_SUBTITLING
=
0x59
;
private
static
final
int
TS_PMT_DESC_AC3
=
0x6A
;
private
static
final
int
TS_PMT_DESC_EAC3
=
0x7A
;
private
static
final
int
TS_PMT_DESC_DTS
=
0x7B
;
private
static
final
int
TS_PMT_DESC_AAC
=
0x7C
;
class
EsInfo
{
int
streamType
;
String
streamLanguage
;
int
audioType
;
public
EsInfo
()
{
// REGISTRATION
streamType
=
-
1
;
// ISO639LANG
streamLanguage
=
null
;
audioType
=
-
1
;
}
}
public
PmtReader
()
{
pmtScratch
=
new
ParsableBitArray
(
new
byte
[
5
]);
sectionData
=
new
ParsableByteArray
();
...
...
@@ -404,11 +430,9 @@ public final class TsExtractor implements Extractor {
int
elementaryPid
=
pmtScratch
.
readBits
(
13
);
pmtScratch
.
skipBits
(
4
);
// reserved
int
esInfoLength
=
pmtScratch
.
readBits
(
12
);
// ES_info_length
EsInfo
esInfo
=
readEsInfo
(
sectionData
,
esInfoLength
);
if
(
streamType
==
0x06
)
{
// Read descriptors in PES packets containing private data.
streamType
=
readPrivateDataStreamType
(
sectionData
,
esInfoLength
);
}
else
{
sectionData
.
skipBytes
(
esInfoLength
);
streamType
=
esInfo
.
streamType
;
}
remainingEntriesLength
-=
esInfoLength
+
5
;
int
trackId
=
(
workaroundFlags
&
WORKAROUND_MAP_BY_TYPE
)
!=
0
?
streamType
:
elementaryPid
;
...
...
@@ -418,22 +442,22 @@ public final class TsExtractor implements Extractor {
ElementaryStreamReader
pesPayloadReader
;
switch
(
streamType
)
{
case
TS_STREAM_TYPE_MPA:
pesPayloadReader
=
new
MpegAudioReader
(
output
.
track
(
trackId
));
pesPayloadReader
=
new
MpegAudioReader
(
output
.
track
(
trackId
)
,
esInfo
.
streamLanguage
);
break
;
case
TS_STREAM_TYPE_MPA_LSF:
pesPayloadReader
=
new
MpegAudioReader
(
output
.
track
(
trackId
));
pesPayloadReader
=
new
MpegAudioReader
(
output
.
track
(
trackId
)
,
esInfo
.
streamLanguage
);
break
;
case
TS_STREAM_TYPE_AAC:
pesPayloadReader
=
(
workaroundFlags
&
WORKAROUND_IGNORE_AAC_STREAM
)
!=
0
?
null
:
new
AdtsReader
(
output
.
track
(
trackId
),
new
DummyTrackOutput
());
:
new
AdtsReader
(
output
.
track
(
trackId
),
new
DummyTrackOutput
()
,
esInfo
.
streamLanguage
);
break
;
case
TS_STREAM_TYPE_AC3:
case
TS_STREAM_TYPE_E_AC3:
pesPayloadReader
=
new
Ac3Reader
(
output
.
track
(
trackId
));
pesPayloadReader
=
new
Ac3Reader
(
output
.
track
(
trackId
)
,
esInfo
.
streamLanguage
);
break
;
case
TS_STREAM_TYPE_DTS:
case
TS_STREAM_TYPE_HDMV_DTS:
pesPayloadReader
=
new
DtsReader
(
output
.
track
(
trackId
));
pesPayloadReader
=
new
DtsReader
(
output
.
track
(
trackId
)
,
esInfo
.
streamLanguage
);
break
;
case
TS_STREAM_TYPE_H262:
pesPayloadReader
=
new
H262Reader
(
output
.
track
(
trackId
));
...
...
@@ -472,42 +496,45 @@ public final class TsExtractor implements Extractor {
}
/**
* Returns the stream
type read from a registration descriptor in private data
, or -1 if no
*
stream type is
present. Sets {@code data}'s position to the end of the descriptors.
* Returns the stream
info read from the available descriptors
, or -1 if no
*
descriptors are
present. Sets {@code data}'s position to the end of the descriptors.
*
* @param data A buffer with its position set to the start of the first descriptor.
* @param length The length of descriptors to read from the current position in {@code data}.
* @return The stream
type read from a registration descriptor in private data
, or -1 if no
*
stream type is
present.
* @return The stream
info read from the available descriptors
, or -1 if no
*
descriptors are
present.
*/
private
int
readPrivateDataStreamType
(
ParsableByteArray
data
,
int
length
)
{
int
streamType
=
-
1
;
private
EsInfo
readEsInfo
(
ParsableByteArray
data
,
int
length
)
{
EsInfo
esInfo
=
new
EsInfo
()
;
int
descriptorsEndPosition
=
data
.
getPosition
()
+
length
;
while
(
data
.
getPosition
()
<
descriptorsEndPosition
)
{
int
descriptorTag
=
data
.
readUnsignedByte
();
int
descriptorLength
=
data
.
readUnsignedByte
();
if
(
descriptorTag
==
0x05
)
{
// registration_descriptor
if
(
descriptorTag
==
TS_PMT_DESC_REGISTRATION
)
{
// registration_descriptor
long
formatIdentifier
=
data
.
readUnsignedInt
();
if
(
formatIdentifier
==
AC3_FORMAT_IDENTIFIER
)
{
streamType
=
TS_STREAM_TYPE_AC3
;
esInfo
.
streamType
=
TS_STREAM_TYPE_AC3
;
}
else
if
(
formatIdentifier
==
E_AC3_FORMAT_IDENTIFIER
)
{
streamType
=
TS_STREAM_TYPE_E_AC3
;
esInfo
.
streamType
=
TS_STREAM_TYPE_E_AC3
;
}
else
if
(
formatIdentifier
==
HEVC_FORMAT_IDENTIFIER
)
{
streamType
=
TS_STREAM_TYPE_H265
;
esInfo
.
streamType
=
TS_STREAM_TYPE_H265
;
}
break
;
}
else
if
(
descriptorTag
==
0x6A
)
{
// AC-3_descriptor in DVB (ETSI EN 300 468)
streamType
=
TS_STREAM_TYPE_AC3
;
}
else
if
(
descriptorTag
==
0x7A
)
{
// enhanced_AC-3_descriptor
streamType
=
TS_STREAM_TYPE_E_AC3
;
}
else
if
(
descriptorTag
==
0x7B
)
{
// DTS_descriptor
streamType
=
TS_STREAM_TYPE_DTS
;
}
else
if
(
descriptorTag
==
TS_PMT_DESC_AC3
)
{
// AC-3_descriptor in DVB (ETSI EN 300 468)
esInfo
.
streamType
=
TS_STREAM_TYPE_AC3
;
}
else
if
(
descriptorTag
==
TS_PMT_DESC_EAC3
)
{
// enhanced_AC-3_descriptor
esInfo
.
streamType
=
TS_STREAM_TYPE_E_AC3
;
}
else
if
(
descriptorTag
==
TS_PMT_DESC_DTS
)
{
// DTS_descriptor
esInfo
.
streamType
=
TS_STREAM_TYPE_DTS
;
}
else
if
(
descriptorTag
==
TS_PMT_DESC_ISO639_LANG
)
{
esInfo
.
streamLanguage
=
new
String
(
data
.
data
,
data
.
getPosition
(),
3
).
trim
();
esInfo
.
audioType
=
data
.
data
[
data
.
getPosition
()
+
3
];
}
data
.
skipBytes
(
descriptorLength
);
}
data
.
setPosition
(
descriptorsEndPosition
);
return
streamType
;
return
esInfo
;
}
}
...
...
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