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
24726372
authored
Nov 18, 2014
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add support for extracting Vorbis audio in WebM Extractor.
parent
6a544da2
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
178 additions
and
40 deletions
library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
library/src/main/java/com/google/android/exoplayer/parser/webm/DefaultEbmlReader.java
library/src/main/java/com/google/android/exoplayer/parser/webm/EbmlEventHandler.java
library/src/main/java/com/google/android/exoplayer/parser/webm/EbmlReader.java
library/src/main/java/com/google/android/exoplayer/parser/webm/WebmExtractor.java
library/src/main/java/com/google/android/exoplayer/util/MimeTypes.java
library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
View file @
24726372
...
@@ -87,7 +87,7 @@ public class DashChunkSource implements ChunkSource {
...
@@ -87,7 +87,7 @@ public class DashChunkSource implements ChunkSource {
formats
[
i
]
=
representations
[
i
].
format
;
formats
[
i
]
=
representations
[
i
].
format
;
maxWidth
=
Math
.
max
(
formats
[
i
].
width
,
maxWidth
);
maxWidth
=
Math
.
max
(
formats
[
i
].
width
,
maxWidth
);
maxHeight
=
Math
.
max
(
formats
[
i
].
height
,
maxHeight
);
maxHeight
=
Math
.
max
(
formats
[
i
].
height
,
maxHeight
);
Extractor
extractor
=
formats
[
i
].
mimeType
.
startsWith
(
MimeTypes
.
VIDEO_WEBM
)
Extractor
extractor
=
mimeTypeIsWebm
(
formats
[
i
].
mimeType
)
?
new
WebmExtractor
()
:
new
FragmentedMp4Extractor
();
?
new
WebmExtractor
()
:
new
FragmentedMp4Extractor
();
extractors
.
put
(
formats
[
i
].
id
,
extractor
);
extractors
.
put
(
formats
[
i
].
id
,
extractor
);
this
.
representations
.
put
(
formats
[
i
].
id
,
representations
[
i
]);
this
.
representations
.
put
(
formats
[
i
].
id
,
representations
[
i
]);
...
@@ -197,6 +197,10 @@ public class DashChunkSource implements ChunkSource {
...
@@ -197,6 +197,10 @@ public class DashChunkSource implements ChunkSource {
// Do nothing.
// Do nothing.
}
}
private
boolean
mimeTypeIsWebm
(
String
mimeType
)
{
return
mimeType
.
startsWith
(
MimeTypes
.
VIDEO_WEBM
)
||
mimeType
.
startsWith
(
MimeTypes
.
AUDIO_WEBM
);
}
private
Chunk
newInitializationChunk
(
RangedUri
initializationUri
,
RangedUri
indexUri
,
private
Chunk
newInitializationChunk
(
RangedUri
initializationUri
,
RangedUri
indexUri
,
Representation
representation
,
Extractor
extractor
,
DataSource
dataSource
,
Representation
representation
,
Extractor
extractor
,
DataSource
dataSource
,
int
trigger
)
{
int
trigger
)
{
...
...
library/src/main/java/com/google/android/exoplayer/parser/webm/DefaultEbmlReader.java
View file @
24726372
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer
.
parser
.
webm
;
package
com
.
google
.
android
.
exoplayer
.
parser
.
webm
;
import
com.google.android.exoplayer.C
;
import
com.google.android.exoplayer.C
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.upstream.NonBlockingInputStream
;
import
com.google.android.exoplayer.upstream.NonBlockingInputStream
;
import
com.google.android.exoplayer.util.Assertions
;
import
com.google.android.exoplayer.util.Assertions
;
...
@@ -134,7 +135,7 @@ import java.util.Stack;
...
@@ -134,7 +135,7 @@ import java.util.Stack;
}
}
@Override
@Override
public
int
read
(
NonBlockingInputStream
inputStream
)
{
public
int
read
(
NonBlockingInputStream
inputStream
)
throws
ParserException
{
Assertions
.
checkState
(
eventHandler
!=
null
);
Assertions
.
checkState
(
eventHandler
!=
null
);
while
(
true
)
{
while
(
true
)
{
while
(!
masterElementsStack
.
isEmpty
()
while
(!
masterElementsStack
.
isEmpty
()
...
...
library/src/main/java/com/google/android/exoplayer/parser/webm/EbmlEventHandler.java
View file @
24726372
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
*/
*/
package
com
.
google
.
android
.
exoplayer
.
parser
.
webm
;
package
com
.
google
.
android
.
exoplayer
.
parser
.
webm
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.upstream.NonBlockingInputStream
;
import
com.google.android.exoplayer.upstream.NonBlockingInputStream
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
...
@@ -46,41 +47,47 @@ import java.nio.ByteBuffer;
...
@@ -46,41 +47,47 @@ import java.nio.ByteBuffer;
* @param elementOffsetBytes The byte offset where this element starts
* @param elementOffsetBytes The byte offset where this element starts
* @param headerSizeBytes The byte length of this element's ID and size header
* @param headerSizeBytes The byte length of this element's ID and size header
* @param contentsSizeBytes The byte length of this element's children
* @param contentsSizeBytes The byte length of this element's children
* @throws ParserException If a parsing error occurs.
*/
*/
public
void
onMasterElementStart
(
public
void
onMasterElementStart
(
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
long
contentsSizeBytes
);
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
long
contentsSizeBytes
)
throws
ParserException
;
/**
/**
* Called when a master element has finished reading in all of its children from the
* Called when a master element has finished reading in all of its children from the
* {@link NonBlockingInputStream}.
* {@link NonBlockingInputStream}.
*
*
* @param id The integer ID of this element
* @param id The integer ID of this element
* @throws ParserException If a parsing error occurs.
*/
*/
public
void
onMasterElementEnd
(
int
id
);
public
void
onMasterElementEnd
(
int
id
)
throws
ParserException
;
/**
/**
* Called when an integer element is encountered in the {@link NonBlockingInputStream}.
* Called when an integer element is encountered in the {@link NonBlockingInputStream}.
*
*
* @param id The integer ID of this element
* @param id The integer ID of this element
* @param value The integer value this element contains
* @param value The integer value this element contains
* @throws ParserException If a parsing error occurs.
*/
*/
public
void
onIntegerElement
(
int
id
,
long
value
);
public
void
onIntegerElement
(
int
id
,
long
value
)
throws
ParserException
;
/**
/**
* Called when a float element is encountered in the {@link NonBlockingInputStream}.
* Called when a float element is encountered in the {@link NonBlockingInputStream}.
*
*
* @param id The integer ID of this element
* @param id The integer ID of this element
* @param value The float value this element contains
* @param value The float value this element contains
* @throws ParserException If a parsing error occurs.
*/
*/
public
void
onFloatElement
(
int
id
,
double
value
);
public
void
onFloatElement
(
int
id
,
double
value
)
throws
ParserException
;
/**
/**
* Called when a string element is encountered in the {@link NonBlockingInputStream}.
* Called when a string element is encountered in the {@link NonBlockingInputStream}.
*
*
* @param id The integer ID of this element
* @param id The integer ID of this element
* @param value The string value this element contains
* @param value The string value this element contains
* @throws ParserException If a parsing error occurs.
*/
*/
public
void
onStringElement
(
int
id
,
String
value
);
public
void
onStringElement
(
int
id
,
String
value
)
throws
ParserException
;
/**
/**
* Called when a binary element is encountered in the {@link NonBlockingInputStream}.
* Called when a binary element is encountered in the {@link NonBlockingInputStream}.
...
@@ -109,9 +116,10 @@ import java.nio.ByteBuffer;
...
@@ -109,9 +116,10 @@ import java.nio.ByteBuffer;
* @param inputStream The {@link NonBlockingInputStream} from which this
* @param inputStream The {@link NonBlockingInputStream} from which this
* element's contents should be read
* element's contents should be read
* @return True if the element was read. False otherwise.
* @return True if the element was read. False otherwise.
* @throws ParserException If a parsing error occurs.
*/
*/
public
boolean
onBinaryElement
(
public
boolean
onBinaryElement
(
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
int
contentsSizeBytes
,
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
int
contentsSizeBytes
,
NonBlockingInputStream
inputStream
);
NonBlockingInputStream
inputStream
)
throws
ParserException
;
}
}
library/src/main/java/com/google/android/exoplayer/parser/webm/EbmlReader.java
View file @
24726372
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
*/
*/
package
com
.
google
.
android
.
exoplayer
.
parser
.
webm
;
package
com
.
google
.
android
.
exoplayer
.
parser
.
webm
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.upstream.NonBlockingInputStream
;
import
com.google.android.exoplayer.upstream.NonBlockingInputStream
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
...
@@ -53,8 +54,9 @@ import java.nio.ByteBuffer;
...
@@ -53,8 +54,9 @@ import java.nio.ByteBuffer;
*
*
* @param inputStream The input stream from which data should be read
* @param inputStream The input stream from which data should be read
* @return One of the {@code RESULT_*} flags defined in this interface
* @return One of the {@code RESULT_*} flags defined in this interface
* @throws ParserException If parsing fails.
*/
*/
public
int
read
(
NonBlockingInputStream
inputStream
);
public
int
read
(
NonBlockingInputStream
inputStream
)
throws
ParserException
;
/**
/**
* The total number of bytes consumed by the reader since first created or last {@link #reset()}.
* The total number of bytes consumed by the reader since first created or last {@link #reset()}.
...
...
library/src/main/java/com/google/android/exoplayer/parser/webm/WebmExtractor.java
View file @
24726372
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer
.
parser
.
webm
;
package
com
.
google
.
android
.
exoplayer
.
parser
.
webm
;
import
com.google.android.exoplayer.MediaFormat
;
import
com.google.android.exoplayer.MediaFormat
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.SampleHolder
;
import
com.google.android.exoplayer.SampleHolder
;
import
com.google.android.exoplayer.parser.Extractor
;
import
com.google.android.exoplayer.parser.Extractor
;
import
com.google.android.exoplayer.parser.SegmentIndex
;
import
com.google.android.exoplayer.parser.SegmentIndex
;
...
@@ -27,6 +28,7 @@ import android.annotation.TargetApi;
...
@@ -27,6 +28,7 @@ import android.annotation.TargetApi;
import
android.media.MediaExtractor
;
import
android.media.MediaExtractor
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.UUID
;
import
java.util.UUID
;
...
@@ -44,6 +46,8 @@ public final class WebmExtractor implements Extractor {
...
@@ -44,6 +46,8 @@ public final class WebmExtractor implements Extractor {
private
static
final
String
DOC_TYPE_WEBM
=
"webm"
;
private
static
final
String
DOC_TYPE_WEBM
=
"webm"
;
private
static
final
String
CODEC_ID_VP9
=
"V_VP9"
;
private
static
final
String
CODEC_ID_VP9
=
"V_VP9"
;
private
static
final
String
CODEC_ID_VORBIS
=
"A_VORBIS"
;
private
static
final
int
VORBIS_MAX_INPUT_SIZE
=
8192
;
private
static
final
int
UNKNOWN
=
-
1
;
private
static
final
int
UNKNOWN
=
-
1
;
// Element IDs
// Element IDs
...
@@ -65,9 +69,13 @@ public final class WebmExtractor implements Extractor {
...
@@ -65,9 +69,13 @@ public final class WebmExtractor implements Extractor {
private
static
final
int
ID_TRACKS
=
0x1654AE6B
;
private
static
final
int
ID_TRACKS
=
0x1654AE6B
;
private
static
final
int
ID_TRACK_ENTRY
=
0xAE
;
private
static
final
int
ID_TRACK_ENTRY
=
0xAE
;
private
static
final
int
ID_CODEC_ID
=
0x86
;
private
static
final
int
ID_CODEC_ID
=
0x86
;
private
static
final
int
ID_CODEC_PRIVATE
=
0x63A2
;
private
static
final
int
ID_VIDEO
=
0xE0
;
private
static
final
int
ID_VIDEO
=
0xE0
;
private
static
final
int
ID_PIXEL_WIDTH
=
0xB0
;
private
static
final
int
ID_PIXEL_WIDTH
=
0xB0
;
private
static
final
int
ID_PIXEL_HEIGHT
=
0xBA
;
private
static
final
int
ID_PIXEL_HEIGHT
=
0xBA
;
private
static
final
int
ID_AUDIO
=
0xE1
;
private
static
final
int
ID_CHANNELS
=
0x9F
;
private
static
final
int
ID_SAMPLING_FREQUENCY
=
0xB5
;
private
static
final
int
ID_CUES
=
0x1C53BB6B
;
private
static
final
int
ID_CUES
=
0x1C53BB6B
;
private
static
final
int
ID_CUE_POINT
=
0xBB
;
private
static
final
int
ID_CUE_POINT
=
0xBB
;
...
@@ -96,6 +104,10 @@ public final class WebmExtractor implements Extractor {
...
@@ -96,6 +104,10 @@ public final class WebmExtractor implements Extractor {
private
long
durationUs
=
UNKNOWN
;
private
long
durationUs
=
UNKNOWN
;
private
int
pixelWidth
=
UNKNOWN
;
private
int
pixelWidth
=
UNKNOWN
;
private
int
pixelHeight
=
UNKNOWN
;
private
int
pixelHeight
=
UNKNOWN
;
private
int
channelCount
=
UNKNOWN
;
private
int
sampleRate
=
UNKNOWN
;
private
byte
[]
codecPrivate
;
private
boolean
seenAudioTrack
;
private
long
cuesSizeBytes
=
UNKNOWN
;
private
long
cuesSizeBytes
=
UNKNOWN
;
private
long
clusterTimecodeUs
=
UNKNOWN
;
private
long
clusterTimecodeUs
=
UNKNOWN
;
private
long
simpleBlockTimecodeUs
=
UNKNOWN
;
private
long
simpleBlockTimecodeUs
=
UNKNOWN
;
...
@@ -114,7 +126,8 @@ public final class WebmExtractor implements Extractor {
...
@@ -114,7 +126,8 @@ public final class WebmExtractor implements Extractor {
}
}
@Override
@Override
public
int
read
(
NonBlockingInputStream
inputStream
,
SampleHolder
sampleHolder
)
{
public
int
read
(
NonBlockingInputStream
inputStream
,
SampleHolder
sampleHolder
)
throws
ParserException
{
this
.
sampleHolder
=
sampleHolder
;
this
.
sampleHolder
=
sampleHolder
;
this
.
readResults
=
0
;
this
.
readResults
=
0
;
while
((
readResults
&
READ_TERMINATING_RESULTS
)
==
0
)
{
while
((
readResults
&
READ_TERMINATING_RESULTS
)
==
0
)
{
...
@@ -176,6 +189,7 @@ public final class WebmExtractor implements Extractor {
...
@@ -176,6 +189,7 @@ public final class WebmExtractor implements Extractor {
case
ID_CLUSTER:
case
ID_CLUSTER:
case
ID_TRACKS:
case
ID_TRACKS:
case
ID_TRACK_ENTRY:
case
ID_TRACK_ENTRY:
case
ID_AUDIO:
case
ID_VIDEO:
case
ID_VIDEO:
case
ID_CUES:
case
ID_CUES:
case
ID_CUE_POINT:
case
ID_CUE_POINT:
...
@@ -187,6 +201,7 @@ public final class WebmExtractor implements Extractor {
...
@@ -187,6 +201,7 @@ public final class WebmExtractor implements Extractor {
case
ID_TIME_CODE:
case
ID_TIME_CODE:
case
ID_PIXEL_WIDTH:
case
ID_PIXEL_WIDTH:
case
ID_PIXEL_HEIGHT:
case
ID_PIXEL_HEIGHT:
case
ID_CHANNELS:
case
ID_CUE_TIME:
case
ID_CUE_TIME:
case
ID_CUE_CLUSTER_POSITION:
case
ID_CUE_CLUSTER_POSITION:
return
EbmlReader
.
TYPE_UNSIGNED_INT
;
return
EbmlReader
.
TYPE_UNSIGNED_INT
;
...
@@ -194,8 +209,10 @@ public final class WebmExtractor implements Extractor {
...
@@ -194,8 +209,10 @@ public final class WebmExtractor implements Extractor {
case
ID_CODEC_ID:
case
ID_CODEC_ID:
return
EbmlReader
.
TYPE_STRING
;
return
EbmlReader
.
TYPE_STRING
;
case
ID_SIMPLE_BLOCK:
case
ID_SIMPLE_BLOCK:
case
ID_CODEC_PRIVATE:
return
EbmlReader
.
TYPE_BINARY
;
return
EbmlReader
.
TYPE_BINARY
;
case
ID_DURATION:
case
ID_DURATION:
case
ID_SAMPLING_FREQUENCY:
return
EbmlReader
.
TYPE_FLOAT
;
return
EbmlReader
.
TYPE_FLOAT
;
default
:
default
:
return
EbmlReader
.
TYPE_UNKNOWN
;
return
EbmlReader
.
TYPE_UNKNOWN
;
...
@@ -203,11 +220,12 @@ public final class WebmExtractor implements Extractor {
...
@@ -203,11 +220,12 @@ public final class WebmExtractor implements Extractor {
}
}
/* package */
boolean
onMasterElementStart
(
/* package */
boolean
onMasterElementStart
(
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
long
contentsSizeBytes
)
{
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
long
contentsSizeBytes
)
throws
ParserException
{
switch
(
id
)
{
switch
(
id
)
{
case
ID_SEGMENT:
case
ID_SEGMENT:
if
(
segmentStartOffsetBytes
!=
UNKNOWN
||
segmentEndOffsetBytes
!=
UNKNOWN
)
{
if
(
segmentStartOffsetBytes
!=
UNKNOWN
||
segmentEndOffsetBytes
!=
UNKNOWN
)
{
throw
new
IllegalState
Exception
(
"Multiple Segment elements not supported"
);
throw
new
Parser
Exception
(
"Multiple Segment elements not supported"
);
}
}
segmentStartOffsetBytes
=
elementOffsetBytes
+
headerSizeBytes
;
segmentStartOffsetBytes
=
elementOffsetBytes
+
headerSizeBytes
;
segmentEndOffsetBytes
=
elementOffsetBytes
+
headerSizeBytes
+
contentsSizeBytes
;
segmentEndOffsetBytes
=
elementOffsetBytes
+
headerSizeBytes
+
contentsSizeBytes
;
...
@@ -223,31 +241,41 @@ public final class WebmExtractor implements Extractor {
...
@@ -223,31 +241,41 @@ public final class WebmExtractor implements Extractor {
return
true
;
return
true
;
}
}
/* package */
boolean
onMasterElementEnd
(
int
id
)
{
/* package */
boolean
onMasterElementEnd
(
int
id
)
throws
ParserException
{
switch
(
id
)
{
switch
(
id
)
{
case
ID_CUES:
case
ID_CUES:
buildCues
();
buildCues
();
return
false
;
return
false
;
case
ID_VIDEO:
case
ID_VIDEO:
buildFormat
();
buildVideoFormat
();
return
true
;
case
ID_AUDIO:
seenAudioTrack
=
true
;
return
true
;
case
ID_TRACK_ENTRY:
if
(
seenAudioTrack
)
{
// Audio format has to be built here since codec private may not be available at the end
// of ID_AUDIO.
buildAudioFormat
();
}
return
true
;
return
true
;
default
:
default
:
return
true
;
return
true
;
}
}
}
}
/* package */
boolean
onIntegerElement
(
int
id
,
long
value
)
{
/* package */
boolean
onIntegerElement
(
int
id
,
long
value
)
throws
ParserException
{
switch
(
id
)
{
switch
(
id
)
{
case
ID_EBML_READ_VERSION:
case
ID_EBML_READ_VERSION:
// Validate that EBMLReadVersion is supported. This extractor only supports v1.
// Validate that EBMLReadVersion is supported. This extractor only supports v1.
if
(
value
!=
1
)
{
if
(
value
!=
1
)
{
throw
new
IllegalArgument
Exception
(
"EBMLReadVersion "
+
value
+
" not supported"
);
throw
new
Parser
Exception
(
"EBMLReadVersion "
+
value
+
" not supported"
);
}
}
break
;
break
;
case
ID_DOC_TYPE_READ_VERSION:
case
ID_DOC_TYPE_READ_VERSION:
// Validate that DocTypeReadVersion is supported. This extractor only supports up to v2.
// Validate that DocTypeReadVersion is supported. This extractor only supports up to v2.
if
(
value
<
1
||
value
>
2
)
{
if
(
value
<
1
||
value
>
2
)
{
throw
new
IllegalArgument
Exception
(
"DocTypeReadVersion "
+
value
+
" not supported"
);
throw
new
Parser
Exception
(
"DocTypeReadVersion "
+
value
+
" not supported"
);
}
}
break
;
break
;
case
ID_TIMECODE_SCALE:
case
ID_TIMECODE_SCALE:
...
@@ -259,6 +287,9 @@ public final class WebmExtractor implements Extractor {
...
@@ -259,6 +287,9 @@ public final class WebmExtractor implements Extractor {
case
ID_PIXEL_HEIGHT:
case
ID_PIXEL_HEIGHT:
pixelHeight
=
(
int
)
value
;
pixelHeight
=
(
int
)
value
;
break
;
break
;
case
ID_CHANNELS:
channelCount
=
(
int
)
value
;
break
;
case
ID_CUE_TIME:
case
ID_CUE_TIME:
cueTimesUs
.
add
(
scaleTimecodeToUs
(
value
));
cueTimesUs
.
add
(
scaleTimecodeToUs
(
value
));
break
;
break
;
...
@@ -275,24 +306,31 @@ public final class WebmExtractor implements Extractor {
...
@@ -275,24 +306,31 @@ public final class WebmExtractor implements Extractor {
}
}
/* package */
boolean
onFloatElement
(
int
id
,
double
value
)
{
/* package */
boolean
onFloatElement
(
int
id
,
double
value
)
{
if
(
id
==
ID_DURATION
)
{
switch
(
id
)
{
case
ID_DURATION:
durationUs
=
scaleTimecodeToUs
((
long
)
value
);
durationUs
=
scaleTimecodeToUs
((
long
)
value
);
break
;
case
ID_SAMPLING_FREQUENCY:
sampleRate
=
(
int
)
value
;
break
;
default
:
// pass
}
}
return
true
;
return
true
;
}
}
/* package */
boolean
onStringElement
(
int
id
,
String
value
)
{
/* package */
boolean
onStringElement
(
int
id
,
String
value
)
throws
ParserException
{
switch
(
id
)
{
switch
(
id
)
{
case
ID_DOC_TYPE:
case
ID_DOC_TYPE:
// Validate that DocType is supported. This extractor only supports "webm".
// Validate that DocType is supported. This extractor only supports "webm".
if
(!
DOC_TYPE_WEBM
.
equals
(
value
))
{
if
(!
DOC_TYPE_WEBM
.
equals
(
value
))
{
throw
new
IllegalArgument
Exception
(
"DocType "
+
value
+
" not supported"
);
throw
new
Parser
Exception
(
"DocType "
+
value
+
" not supported"
);
}
}
break
;
break
;
case
ID_CODEC_ID:
case
ID_CODEC_ID:
// Validate that CodecID is supported. This extractor only supports "V_VP9".
// Validate that CodecID is supported. This extractor only supports "V_VP9"
and "A_VORBIS"
.
if
(!
CODEC_ID_VP9
.
equals
(
value
))
{
if
(!
CODEC_ID_VP9
.
equals
(
value
)
&&
!
CODEC_ID_VORBIS
.
equals
(
value
)
)
{
throw
new
IllegalArgument
Exception
(
"CodecID "
+
value
+
" not supported"
);
throw
new
Parser
Exception
(
"CodecID "
+
value
+
" not supported"
);
}
}
break
;
break
;
default
:
default
:
...
@@ -303,8 +341,9 @@ public final class WebmExtractor implements Extractor {
...
@@ -303,8 +341,9 @@ public final class WebmExtractor implements Extractor {
/* package */
boolean
onBinaryElement
(
/* package */
boolean
onBinaryElement
(
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
int
contentsSizeBytes
,
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
int
contentsSizeBytes
,
NonBlockingInputStream
inputStream
)
{
NonBlockingInputStream
inputStream
)
throws
ParserException
{
if
(
id
==
ID_SIMPLE_BLOCK
)
{
switch
(
id
)
{
case
ID_SIMPLE_BLOCK:
// Please refer to http://www.matroska.org/technical/specs/index.html#simpleblock_structure
// Please refer to http://www.matroska.org/technical/specs/index.html#simpleblock_structure
// for info about how data is organized in a SimpleBlock element.
// for info about how data is organized in a SimpleBlock element.
...
@@ -344,7 +383,7 @@ public final class WebmExtractor implements Extractor {
...
@@ -344,7 +383,7 @@ public final class WebmExtractor implements Extractor {
case
LACING_FIXED:
case
LACING_FIXED:
case
LACING_XIPH:
case
LACING_XIPH:
default
:
default
:
throw
new
IllegalState
Exception
(
"Lacing mode "
+
lacing
+
" not supported"
);
throw
new
Parser
Exception
(
"Lacing mode "
+
lacing
+
" not supported"
);
}
}
if
(
sampleHolder
.
data
==
null
||
sampleHolder
.
data
.
capacity
()
<
sampleHolder
.
size
)
{
if
(
sampleHolder
.
data
==
null
||
sampleHolder
.
data
.
capacity
()
<
sampleHolder
.
size
)
{
...
@@ -359,6 +398,13 @@ public final class WebmExtractor implements Extractor {
...
@@ -359,6 +398,13 @@ public final class WebmExtractor implements Extractor {
reader
.
readBytes
(
inputStream
,
outputData
,
sampleHolder
.
size
);
reader
.
readBytes
(
inputStream
,
outputData
,
sampleHolder
.
size
);
}
}
readResults
|=
RESULT_READ_SAMPLE
;
readResults
|=
RESULT_READ_SAMPLE
;
break
;
case
ID_CODEC_PRIVATE:
codecPrivate
=
new
byte
[
contentsSizeBytes
];
reader
.
readBytes
(
inputStream
,
codecPrivate
,
contentsSizeBytes
);
break
;
default
:
// pass
}
}
return
true
;
return
true
;
}
}
...
@@ -372,16 +418,38 @@ public final class WebmExtractor implements Extractor {
...
@@ -372,16 +418,38 @@ public final class WebmExtractor implements Extractor {
*
*
* <p>Replaces the previous {@link #format} only if video width/height have changed.
* <p>Replaces the previous {@link #format} only if video width/height have changed.
* {@link #format} is guaranteed to not be null after calling this method. In
* {@link #format} is guaranteed to not be null after calling this method. In
* the event that it can't be built, an {@link
IllegalState
Exception} will be thrown.
* the event that it can't be built, an {@link
Parser
Exception} will be thrown.
*/
*/
private
void
build
Format
()
{
private
void
build
VideoFormat
()
throws
ParserException
{
if
(
pixelWidth
!=
UNKNOWN
&&
pixelHeight
!=
UNKNOWN
if
(
pixelWidth
!=
UNKNOWN
&&
pixelHeight
!=
UNKNOWN
&&
(
format
==
null
||
format
.
width
!=
pixelWidth
||
format
.
height
!=
pixelHeight
))
{
&&
(
format
==
null
||
format
.
width
!=
pixelWidth
||
format
.
height
!=
pixelHeight
))
{
format
=
MediaFormat
.
createVideoFormat
(
format
=
MediaFormat
.
createVideoFormat
(
MimeTypes
.
VIDEO_VP9
,
MediaFormat
.
NO_VALUE
,
pixelWidth
,
pixelHeight
,
null
);
MimeTypes
.
VIDEO_VP9
,
MediaFormat
.
NO_VALUE
,
pixelWidth
,
pixelHeight
,
null
);
readResults
|=
RESULT_READ_INIT
;
readResults
|=
RESULT_READ_INIT
;
}
else
if
(
format
==
null
)
{
}
else
if
(
format
==
null
)
{
throw
new
IllegalStateException
(
"Unable to build format"
);
throw
new
ParserException
(
"Unable to build format"
);
}
}
/**
* Build an audio {@link MediaFormat} containing recently gathered Audio information, if needed.
*
* <p>Replaces the previous {@link #format} only if audio channel count/sample rate have changed.
* {@link #format} is guaranteed to not be null after calling this method.
*
* @throws ParserException If an error occurs when parsing codec's private data or if the format
* can't be built.
*/
private
void
buildAudioFormat
()
throws
ParserException
{
if
(
channelCount
!=
UNKNOWN
&&
sampleRate
!=
UNKNOWN
&&
(
format
==
null
||
format
.
channelCount
!=
channelCount
||
format
.
sampleRate
!=
sampleRate
))
{
format
=
MediaFormat
.
createAudioFormat
(
MimeTypes
.
AUDIO_VORBIS
,
VORBIS_MAX_INPUT_SIZE
,
sampleRate
,
channelCount
,
parseVorbisCodecPrivate
());
readResults
|=
RESULT_READ_INIT
;
}
else
if
(
format
==
null
)
{
throw
new
ParserException
(
"Unable to build format"
);
}
}
}
}
...
@@ -389,18 +457,18 @@ public final class WebmExtractor implements Extractor {
...
@@ -389,18 +457,18 @@ public final class WebmExtractor implements Extractor {
* Build a {@link SegmentIndex} containing recently gathered Cues information.
* Build a {@link SegmentIndex} containing recently gathered Cues information.
*
*
* <p>{@link #cues} is guaranteed to not be null after calling this method. In
* <p>{@link #cues} is guaranteed to not be null after calling this method. In
* the event that it can't be built, an {@link
IllegalState
Exception} will be thrown.
* the event that it can't be built, an {@link
Parser
Exception} will be thrown.
*/
*/
private
void
buildCues
()
{
private
void
buildCues
()
throws
ParserException
{
if
(
segmentStartOffsetBytes
==
UNKNOWN
)
{
if
(
segmentStartOffsetBytes
==
UNKNOWN
)
{
throw
new
IllegalState
Exception
(
"Segment start/end offsets unknown"
);
throw
new
Parser
Exception
(
"Segment start/end offsets unknown"
);
}
else
if
(
durationUs
==
UNKNOWN
)
{
}
else
if
(
durationUs
==
UNKNOWN
)
{
throw
new
IllegalState
Exception
(
"Duration unknown"
);
throw
new
Parser
Exception
(
"Duration unknown"
);
}
else
if
(
cuesSizeBytes
==
UNKNOWN
)
{
}
else
if
(
cuesSizeBytes
==
UNKNOWN
)
{
throw
new
IllegalState
Exception
(
"Cues size unknown"
);
throw
new
Parser
Exception
(
"Cues size unknown"
);
}
else
if
(
cueTimesUs
==
null
||
cueClusterPositions
==
null
}
else
if
(
cueTimesUs
==
null
||
cueClusterPositions
==
null
||
cueTimesUs
.
size
()
==
0
||
cueTimesUs
.
size
()
!=
cueClusterPositions
.
size
())
{
||
cueTimesUs
.
size
()
==
0
||
cueTimesUs
.
size
()
!=
cueClusterPositions
.
size
())
{
throw
new
IllegalState
Exception
(
"Invalid/missing cue points"
);
throw
new
Parser
Exception
(
"Invalid/missing cue points"
);
}
}
int
cuePointsSize
=
cueTimesUs
.
size
();
int
cuePointsSize
=
cueTimesUs
.
size
();
int
[]
sizes
=
new
int
[
cuePointsSize
];
int
[]
sizes
=
new
int
[
cuePointsSize
];
...
@@ -424,6 +492,58 @@ public final class WebmExtractor implements Extractor {
...
@@ -424,6 +492,58 @@ public final class WebmExtractor implements Extractor {
}
}
/**
/**
* Parses Vorbis Codec Private data and adds it as initialization data to the {@link #format}.
* WebM Vorbis Codec Private data specification can be found
* <a href="http://matroska.org/technical/specs/codecid/index.html">here</a>.
*
* @return ArrayList of byte arrays containing the initialization data on success.
* @throws ParserException If parsing codec private data fails.
*/
private
ArrayList
<
byte
[]>
parseVorbisCodecPrivate
()
throws
ParserException
{
try
{
if
(
codecPrivate
[
0
]
!=
0x02
)
{
throw
new
ParserException
(
"Error parsing vorbis codec private"
);
}
int
offset
=
1
;
int
vorbisInfoLength
=
0
;
while
(
codecPrivate
[
offset
]
==
(
byte
)
0xFF
)
{
vorbisInfoLength
+=
0xFF
;
offset
++;
}
vorbisInfoLength
+=
codecPrivate
[
offset
++];
int
vorbisSkipLength
=
0
;
while
(
codecPrivate
[
offset
]
==
(
byte
)
0xFF
)
{
vorbisSkipLength
+=
0xFF
;
offset
++;
}
vorbisSkipLength
+=
codecPrivate
[
offset
++];
if
(
codecPrivate
[
offset
]
!=
0x01
)
{
throw
new
ParserException
(
"Error parsing vorbis codec private"
);
}
byte
[]
vorbisInfo
=
new
byte
[
vorbisInfoLength
];
System
.
arraycopy
(
codecPrivate
,
offset
,
vorbisInfo
,
0
,
vorbisInfoLength
);
offset
+=
vorbisInfoLength
;
if
(
codecPrivate
[
offset
]
!=
0x03
)
{
throw
new
ParserException
(
"Error parsing vorbis codec private"
);
}
offset
+=
vorbisSkipLength
;
if
(
codecPrivate
[
offset
]
!=
0x05
)
{
throw
new
ParserException
(
"Error parsing vorbis codec private"
);
}
byte
[]
vorbisBooks
=
new
byte
[
codecPrivate
.
length
-
offset
];
System
.
arraycopy
(
codecPrivate
,
offset
,
vorbisBooks
,
0
,
codecPrivate
.
length
-
offset
);
ArrayList
<
byte
[]>
initializationData
=
new
ArrayList
<
byte
[]>(
2
);
initializationData
.
add
(
vorbisInfo
);
initializationData
.
add
(
vorbisBooks
);
return
initializationData
;
}
catch
(
ArrayIndexOutOfBoundsException
e
)
{
throw
new
ParserException
(
"Error parsing vorbis codec private"
);
}
}
/**
* Passes events through to {@link WebmExtractor} as
* Passes events through to {@link WebmExtractor} as
* callbacks from {@link EbmlReader} are received.
* callbacks from {@link EbmlReader} are received.
*/
*/
...
@@ -436,18 +556,19 @@ public final class WebmExtractor implements Extractor {
...
@@ -436,18 +556,19 @@ public final class WebmExtractor implements Extractor {
@Override
@Override
public
void
onMasterElementStart
(
public
void
onMasterElementStart
(
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
long
contentsSizeBytes
)
{
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
long
contentsSizeBytes
)
throws
ParserException
{
WebmExtractor
.
this
.
onMasterElementStart
(
WebmExtractor
.
this
.
onMasterElementStart
(
id
,
elementOffsetBytes
,
headerSizeBytes
,
contentsSizeBytes
);
id
,
elementOffsetBytes
,
headerSizeBytes
,
contentsSizeBytes
);
}
}
@Override
@Override
public
void
onMasterElementEnd
(
int
id
)
{
public
void
onMasterElementEnd
(
int
id
)
throws
ParserException
{
WebmExtractor
.
this
.
onMasterElementEnd
(
id
);
WebmExtractor
.
this
.
onMasterElementEnd
(
id
);
}
}
@Override
@Override
public
void
onIntegerElement
(
int
id
,
long
value
)
{
public
void
onIntegerElement
(
int
id
,
long
value
)
throws
ParserException
{
WebmExtractor
.
this
.
onIntegerElement
(
id
,
value
);
WebmExtractor
.
this
.
onIntegerElement
(
id
,
value
);
}
}
...
@@ -457,14 +578,14 @@ public final class WebmExtractor implements Extractor {
...
@@ -457,14 +578,14 @@ public final class WebmExtractor implements Extractor {
}
}
@Override
@Override
public
void
onStringElement
(
int
id
,
String
value
)
{
public
void
onStringElement
(
int
id
,
String
value
)
throws
ParserException
{
WebmExtractor
.
this
.
onStringElement
(
id
,
value
);
WebmExtractor
.
this
.
onStringElement
(
id
,
value
);
}
}
@Override
@Override
public
boolean
onBinaryElement
(
public
boolean
onBinaryElement
(
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
int
contentsSizeBytes
,
int
id
,
long
elementOffsetBytes
,
int
headerSizeBytes
,
int
contentsSizeBytes
,
NonBlockingInputStream
inputStream
)
{
NonBlockingInputStream
inputStream
)
throws
ParserException
{
return
WebmExtractor
.
this
.
onBinaryElement
(
return
WebmExtractor
.
this
.
onBinaryElement
(
id
,
elementOffsetBytes
,
headerSizeBytes
,
contentsSizeBytes
,
inputStream
);
id
,
elementOffsetBytes
,
headerSizeBytes
,
contentsSizeBytes
,
inputStream
);
}
}
...
...
library/src/main/java/com/google/android/exoplayer/util/MimeTypes.java
View file @
24726372
...
@@ -34,6 +34,8 @@ public class MimeTypes {
...
@@ -34,6 +34,8 @@ public class MimeTypes {
public
static
final
String
AUDIO_AAC
=
BASE_TYPE_AUDIO
+
"/mp4a-latm"
;
public
static
final
String
AUDIO_AAC
=
BASE_TYPE_AUDIO
+
"/mp4a-latm"
;
public
static
final
String
AUDIO_AC3
=
BASE_TYPE_AUDIO
+
"/ac3"
;
public
static
final
String
AUDIO_AC3
=
BASE_TYPE_AUDIO
+
"/ac3"
;
public
static
final
String
AUDIO_EC3
=
BASE_TYPE_AUDIO
+
"/eac3"
;
public
static
final
String
AUDIO_EC3
=
BASE_TYPE_AUDIO
+
"/eac3"
;
public
static
final
String
AUDIO_WEBM
=
BASE_TYPE_AUDIO
+
"/webm"
;
public
static
final
String
AUDIO_VORBIS
=
BASE_TYPE_AUDIO
+
"/vorbis"
;
public
static
final
String
TEXT_VTT
=
BASE_TYPE_TEXT
+
"/vtt"
;
public
static
final
String
TEXT_VTT
=
BASE_TYPE_TEXT
+
"/vtt"
;
...
...
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