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
e252ddde
authored
Oct 27, 2015
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge branch 'RikHeijdens-mediaformat-id-dash' into dev
parents
f16ba3ba
f4b07ab1
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
57 additions
and
57 deletions
demo/src/main/java/com/google/android/exoplayer/demo/PlayerActivity.java
library/src/androidTest/java/com/google/android/exoplayer/MediaFormatTest.java
library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java
library/src/main/java/com/google/android/exoplayer/MediaFormat.java
library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
library/src/main/java/com/google/android/exoplayer/extractor/flv/AudioTagPayloadReader.java
library/src/main/java/com/google/android/exoplayer/extractor/flv/VideoTagPayloadReader.java
library/src/main/java/com/google/android/exoplayer/extractor/mp3/Mp3Extractor.java
library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/AdtsReader.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/H264Reader.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/H265Reader.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/Id3Reader.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/MpegAudioReader.java
library/src/main/java/com/google/android/exoplayer/extractor/ts/SeiReader.java
library/src/main/java/com/google/android/exoplayer/extractor/webm/WebmExtractor.java
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
library/src/main/java/com/google/android/exoplayer/util/Ac3Util.java
demo/src/main/java/com/google/android/exoplayer/demo/PlayerActivity.java
View file @
e252ddde
...
@@ -508,8 +508,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
...
@@ -508,8 +508,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
}
}
private
static
String
buildTrackIdString
(
MediaFormat
format
)
{
private
static
String
buildTrackIdString
(
MediaFormat
format
)
{
return
format
.
trackId
==
MediaFormat
.
NO_VALUE
?
""
return
format
.
trackId
==
null
?
""
:
" ("
+
format
.
trackId
+
")"
;
:
String
.
format
(
Locale
.
US
,
" (%d)"
,
format
.
trackId
);
}
}
private
boolean
onTrackItemClick
(
MenuItem
item
,
int
type
)
{
private
boolean
onTrackItemClick
(
MenuItem
item
,
int
type
)
{
...
...
library/src/androidTest/java/com/google/android/exoplayer/MediaFormatTest.java
View file @
e252ddde
...
@@ -15,11 +15,11 @@
...
@@ -15,11 +15,11 @@
*/
*/
package
com
.
google
.
android
.
exoplayer
;
package
com
.
google
.
android
.
exoplayer
;
import
com.google.android.exoplayer.util.Util
;
import
android.annotation.SuppressLint
;
import
android.annotation.SuppressLint
;
import
android.annotation.TargetApi
;
import
android.annotation.TargetApi
;
import
com.google.android.exoplayer.util.Util
;
import
junit.framework.TestCase
;
import
junit.framework.TestCase
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
...
@@ -45,20 +45,20 @@ public final class MediaFormatTest extends TestCase {
...
@@ -45,20 +45,20 @@ public final class MediaFormatTest extends TestCase {
initData
.
add
(
initData2
);
initData
.
add
(
initData2
);
testConversionToFrameworkFormatV16
(
MediaFormat
.
createVideoFormat
(
testConversionToFrameworkFormatV16
(
MediaFormat
.
createVideoFormat
(
MediaFormat
.
NO_VALUE
,
"video/xyz"
,
5000
,
102400
,
1000L
,
1280
,
720
,
initData
));
null
,
"video/xyz"
,
5000
,
102400
,
1000L
,
1280
,
720
,
initData
));
testConversionToFrameworkFormatV16
(
MediaFormat
.
createVideoFormat
(
testConversionToFrameworkFormatV16
(
MediaFormat
.
createVideoFormat
(
MediaFormat
.
NO_VALUE
,
"video/xyz"
,
5000
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
1280
,
720
,
null
,
"video/xyz"
,
5000
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
1280
,
720
,
null
));
null
));
testConversionToFrameworkFormatV16
(
MediaFormat
.
createAudioFormat
(
testConversionToFrameworkFormatV16
(
MediaFormat
.
createAudioFormat
(
MediaFormat
.
NO_VALUE
,
"audio/xyz"
,
500
,
128
,
1000L
,
5
,
44100
,
initData
,
null
));
null
,
"audio/xyz"
,
500
,
128
,
1000L
,
5
,
44100
,
initData
,
null
));
testConversionToFrameworkFormatV16
(
MediaFormat
.
createAudioFormat
(
testConversionToFrameworkFormatV16
(
MediaFormat
.
createAudioFormat
(
MediaFormat
.
NO_VALUE
,
"audio/xyz"
,
500
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
5
,
44100
,
null
,
"audio/xyz"
,
500
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
5
,
44100
,
null
,
null
));
null
,
null
));
testConversionToFrameworkFormatV16
(
testConversionToFrameworkFormatV16
(
MediaFormat
.
createTextFormat
(
MediaFormat
.
NO_VALUE
,
"text/xyz"
,
MediaFormat
.
NO_VALUE
,
1000L
,
MediaFormat
.
createTextFormat
(
null
,
"text/xyz"
,
MediaFormat
.
NO_VALUE
,
1000L
,
"eng"
));
"eng"
));
testConversionToFrameworkFormatV16
(
testConversionToFrameworkFormatV16
(
MediaFormat
.
createTextFormat
(
MediaFormat
.
NO_VALUE
,
"text/xyz"
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
createTextFormat
(
null
,
"text/xyz"
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
null
));
C
.
UNKNOWN_TIME_US
,
null
));
}
}
...
...
library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java
View file @
e252ddde
...
@@ -315,7 +315,7 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe
...
@@ -315,7 +315,7 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe
}
}
long
durationUs
=
format
.
containsKey
(
android
.
media
.
MediaFormat
.
KEY_DURATION
)
long
durationUs
=
format
.
containsKey
(
android
.
media
.
MediaFormat
.
KEY_DURATION
)
?
format
.
getLong
(
android
.
media
.
MediaFormat
.
KEY_DURATION
)
:
C
.
UNKNOWN_TIME_US
;
?
format
.
getLong
(
android
.
media
.
MediaFormat
.
KEY_DURATION
)
:
C
.
UNKNOWN_TIME_US
;
MediaFormat
mediaFormat
=
new
MediaFormat
(
MediaFormat
.
NO_VALUE
,
mimeType
,
MediaFormat
.
NO_VALUE
,
MediaFormat
mediaFormat
=
new
MediaFormat
(
null
,
mimeType
,
MediaFormat
.
NO_VALUE
,
maxInputSize
,
durationUs
,
width
,
height
,
rotationDegrees
,
MediaFormat
.
NO_VALUE
,
maxInputSize
,
durationUs
,
width
,
height
,
rotationDegrees
,
MediaFormat
.
NO_VALUE
,
channelCount
,
sampleRate
,
language
,
MediaFormat
.
OFFSET_SAMPLE_RELATIVE
,
initializationData
,
channelCount
,
sampleRate
,
language
,
MediaFormat
.
OFFSET_SAMPLE_RELATIVE
,
initializationData
,
false
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
);
false
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
);
...
...
library/src/main/java/com/google/android/exoplayer/MediaFormat.java
View file @
e252ddde
...
@@ -15,12 +15,12 @@
...
@@ -15,12 +15,12 @@
*/
*/
package
com
.
google
.
android
.
exoplayer
;
package
com
.
google
.
android
.
exoplayer
;
import
com.google.android.exoplayer.util.Assertions
;
import
com.google.android.exoplayer.util.Util
;
import
android.annotation.SuppressLint
;
import
android.annotation.SuppressLint
;
import
android.annotation.TargetApi
;
import
android.annotation.TargetApi
;
import
com.google.android.exoplayer.util.Assertions
;
import
com.google.android.exoplayer.util.Util
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Collections
;
...
@@ -40,10 +40,10 @@ public final class MediaFormat {
...
@@ -40,10 +40,10 @@ public final class MediaFormat {
public
static
final
long
OFFSET_SAMPLE_RELATIVE
=
Long
.
MAX_VALUE
;
public
static
final
long
OFFSET_SAMPLE_RELATIVE
=
Long
.
MAX_VALUE
;
/**
/**
* The identifier for the track represented by the format, or
{@link #NO_VALUE}
if unknown or not
* The identifier for the track represented by the format, or
null
if unknown or not
* applicable.
* applicable.
*/
*/
public
final
int
trackId
;
public
final
String
trackId
;
/**
/**
* The mime type of the format.
* The mime type of the format.
*/
*/
...
@@ -139,13 +139,13 @@ public final class MediaFormat {
...
@@ -139,13 +139,13 @@ public final class MediaFormat {
private
int
hashCode
;
private
int
hashCode
;
private
android
.
media
.
MediaFormat
frameworkMediaFormat
;
private
android
.
media
.
MediaFormat
frameworkMediaFormat
;
public
static
MediaFormat
createVideoFormat
(
int
trackId
,
String
mimeType
,
int
bitrate
,
public
static
MediaFormat
createVideoFormat
(
String
trackId
,
String
mimeType
,
int
bitrate
,
int
maxInputSize
,
long
durationUs
,
int
width
,
int
height
,
List
<
byte
[]>
initializationData
)
{
int
maxInputSize
,
long
durationUs
,
int
width
,
int
height
,
List
<
byte
[]>
initializationData
)
{
return
createVideoFormat
(
trackId
,
mimeType
,
bitrate
,
maxInputSize
,
durationUs
,
width
,
height
,
return
createVideoFormat
(
trackId
,
mimeType
,
bitrate
,
maxInputSize
,
durationUs
,
width
,
height
,
initializationData
,
NO_VALUE
,
NO_VALUE
);
initializationData
,
NO_VALUE
,
NO_VALUE
);
}
}
public
static
MediaFormat
createVideoFormat
(
int
trackId
,
String
mimeType
,
int
bitrate
,
public
static
MediaFormat
createVideoFormat
(
String
trackId
,
String
mimeType
,
int
bitrate
,
int
maxInputSize
,
long
durationUs
,
int
width
,
int
height
,
List
<
byte
[]>
initializationData
,
int
maxInputSize
,
long
durationUs
,
int
width
,
int
height
,
List
<
byte
[]>
initializationData
,
int
rotationDegrees
,
float
pixelWidthHeightRatio
)
{
int
rotationDegrees
,
float
pixelWidthHeightRatio
)
{
return
new
MediaFormat
(
trackId
,
mimeType
,
bitrate
,
maxInputSize
,
durationUs
,
width
,
height
,
return
new
MediaFormat
(
trackId
,
mimeType
,
bitrate
,
maxInputSize
,
durationUs
,
width
,
height
,
...
@@ -153,7 +153,7 @@ public final class MediaFormat {
...
@@ -153,7 +153,7 @@ public final class MediaFormat {
initializationData
,
false
,
NO_VALUE
,
NO_VALUE
);
initializationData
,
false
,
NO_VALUE
,
NO_VALUE
);
}
}
public
static
MediaFormat
createAudioFormat
(
int
trackId
,
String
mimeType
,
int
bitrate
,
public
static
MediaFormat
createAudioFormat
(
String
trackId
,
String
mimeType
,
int
bitrate
,
int
maxInputSize
,
long
durationUs
,
int
channelCount
,
int
sampleRate
,
int
maxInputSize
,
long
durationUs
,
int
channelCount
,
int
sampleRate
,
List
<
byte
[]>
initializationData
,
String
language
)
{
List
<
byte
[]>
initializationData
,
String
language
)
{
return
new
MediaFormat
(
trackId
,
mimeType
,
bitrate
,
maxInputSize
,
durationUs
,
NO_VALUE
,
NO_VALUE
,
return
new
MediaFormat
(
trackId
,
mimeType
,
bitrate
,
maxInputSize
,
durationUs
,
NO_VALUE
,
NO_VALUE
,
...
@@ -161,27 +161,27 @@ public final class MediaFormat {
...
@@ -161,27 +161,27 @@ public final class MediaFormat {
initializationData
,
false
,
NO_VALUE
,
NO_VALUE
);
initializationData
,
false
,
NO_VALUE
,
NO_VALUE
);
}
}
public
static
MediaFormat
createTextFormat
(
int
trackId
,
String
mimeType
,
int
bitrate
,
public
static
MediaFormat
createTextFormat
(
String
trackId
,
String
mimeType
,
int
bitrate
,
long
durationUs
,
String
language
)
{
long
durationUs
,
String
language
)
{
return
createTextFormat
(
trackId
,
mimeType
,
bitrate
,
durationUs
,
language
,
return
createTextFormat
(
trackId
,
mimeType
,
bitrate
,
durationUs
,
language
,
OFFSET_SAMPLE_RELATIVE
);
OFFSET_SAMPLE_RELATIVE
);
}
}
public
static
MediaFormat
createTextFormat
(
int
trackId
,
String
mimeType
,
int
bitrate
,
public
static
MediaFormat
createTextFormat
(
String
trackId
,
String
mimeType
,
int
bitrate
,
long
durationUs
,
String
language
,
long
subsampleOffsetUs
)
{
long
durationUs
,
String
language
,
long
subsampleOffsetUs
)
{
return
new
MediaFormat
(
trackId
,
mimeType
,
bitrate
,
NO_VALUE
,
durationUs
,
NO_VALUE
,
NO_VALUE
,
return
new
MediaFormat
(
trackId
,
mimeType
,
bitrate
,
NO_VALUE
,
durationUs
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
language
,
subsampleOffsetUs
,
null
,
false
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
language
,
subsampleOffsetUs
,
null
,
false
,
NO_VALUE
,
NO_VALUE
);
NO_VALUE
);
}
}
public
static
MediaFormat
createFormatForMimeType
(
int
trackId
,
String
mimeType
,
int
bitrate
,
public
static
MediaFormat
createFormatForMimeType
(
String
trackId
,
String
mimeType
,
int
bitrate
,
long
durationUs
)
{
long
durationUs
)
{
return
new
MediaFormat
(
trackId
,
mimeType
,
bitrate
,
NO_VALUE
,
durationUs
,
NO_VALUE
,
NO_VALUE
,
return
new
MediaFormat
(
trackId
,
mimeType
,
bitrate
,
NO_VALUE
,
durationUs
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
OFFSET_SAMPLE_RELATIVE
,
null
,
false
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
OFFSET_SAMPLE_RELATIVE
,
null
,
false
,
NO_VALUE
,
NO_VALUE
);
NO_VALUE
);
}
}
/* package */
MediaFormat
(
int
trackId
,
String
mimeType
,
int
bitrate
,
int
maxInputSize
,
/* package */
MediaFormat
(
String
trackId
,
String
mimeType
,
int
bitrate
,
int
maxInputSize
,
long
durationUs
,
int
width
,
int
height
,
int
rotationDegrees
,
float
pixelWidthHeightRatio
,
long
durationUs
,
int
width
,
int
height
,
int
rotationDegrees
,
float
pixelWidthHeightRatio
,
int
channelCount
,
int
sampleRate
,
String
language
,
long
subsampleOffsetUs
,
int
channelCount
,
int
sampleRate
,
String
language
,
long
subsampleOffsetUs
,
List
<
byte
[]>
initializationData
,
boolean
adaptive
,
int
maxWidth
,
int
maxHeight
)
{
List
<
byte
[]>
initializationData
,
boolean
adaptive
,
int
maxWidth
,
int
maxHeight
)
{
...
@@ -230,7 +230,7 @@ public final class MediaFormat {
...
@@ -230,7 +230,7 @@ public final class MediaFormat {
}
}
public
MediaFormat
copyAsAdaptive
()
{
public
MediaFormat
copyAsAdaptive
()
{
return
new
MediaFormat
(
trackId
,
mimeType
,
NO_VALUE
,
NO_VALUE
,
durationUs
,
NO_VALUE
,
NO_VALUE
,
return
new
MediaFormat
(
null
,
mimeType
,
NO_VALUE
,
NO_VALUE
,
durationUs
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
OFFSET_SAMPLE_RELATIVE
,
null
,
true
,
maxWidth
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
OFFSET_SAMPLE_RELATIVE
,
null
,
true
,
maxWidth
,
maxHeight
);
maxHeight
);
}
}
...
@@ -288,7 +288,7 @@ public final class MediaFormat {
...
@@ -288,7 +288,7 @@ public final class MediaFormat {
public
int
hashCode
()
{
public
int
hashCode
()
{
if
(
hashCode
==
0
)
{
if
(
hashCode
==
0
)
{
int
result
=
17
;
int
result
=
17
;
result
=
31
*
result
+
trackId
;
result
=
31
*
result
+
(
trackId
==
null
?
0
:
trackId
.
hashCode
())
;
result
=
31
*
result
+
(
mimeType
==
null
?
0
:
mimeType
.
hashCode
());
result
=
31
*
result
+
(
mimeType
==
null
?
0
:
mimeType
.
hashCode
());
result
=
31
*
result
+
bitrate
;
result
=
31
*
result
+
bitrate
;
result
=
31
*
result
+
maxInputSize
;
result
=
31
*
result
+
maxInputSize
;
...
...
library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
View file @
e252ddde
...
@@ -610,14 +610,14 @@ public class DashChunkSource implements ChunkSource, Output {
...
@@ -610,14 +610,14 @@ public class DashChunkSource implements ChunkSource, Output {
String
mediaMimeType
,
long
durationUs
)
{
String
mediaMimeType
,
long
durationUs
)
{
switch
(
adaptationSetType
)
{
switch
(
adaptationSetType
)
{
case
AdaptationSet
.
TYPE_VIDEO
:
case
AdaptationSet
.
TYPE_VIDEO
:
return
MediaFormat
.
createVideoFormat
(
MediaFormat
.
NO_VALUE
,
mediaMimeType
,
format
.
bitrate
,
return
MediaFormat
.
createVideoFormat
(
format
.
id
,
mediaMimeType
,
format
.
bitrate
,
MediaFormat
.
NO_VALUE
,
durationUs
,
format
.
width
,
format
.
height
,
null
);
MediaFormat
.
NO_VALUE
,
durationUs
,
format
.
width
,
format
.
height
,
null
);
case
AdaptationSet
.
TYPE_AUDIO
:
case
AdaptationSet
.
TYPE_AUDIO
:
return
MediaFormat
.
createAudioFormat
(
MediaFormat
.
NO_VALUE
,
mediaMimeType
,
format
.
bitrate
,
return
MediaFormat
.
createAudioFormat
(
format
.
id
,
mediaMimeType
,
format
.
bitrate
,
MediaFormat
.
NO_VALUE
,
durationUs
,
format
.
audioChannels
,
format
.
audioSamplingRate
,
null
,
MediaFormat
.
NO_VALUE
,
durationUs
,
format
.
audioChannels
,
format
.
audioSamplingRate
,
null
,
format
.
language
);
format
.
language
);
case
AdaptationSet
.
TYPE_TEXT
:
case
AdaptationSet
.
TYPE_TEXT
:
return
MediaFormat
.
createTextFormat
(
MediaFormat
.
NO_VALUE
,
mediaMimeType
,
format
.
bitrate
,
return
MediaFormat
.
createTextFormat
(
format
.
id
,
mediaMimeType
,
format
.
bitrate
,
durationUs
,
format
.
language
);
durationUs
,
format
.
language
);
default
:
default
:
return
null
;
return
null
;
...
...
library/src/main/java/com/google/android/exoplayer/extractor/flv/AudioTagPayloadReader.java
View file @
e252ddde
...
@@ -95,10 +95,9 @@ import java.util.Collections;
...
@@ -95,10 +95,9 @@ import java.util.Collections;
Pair
<
Integer
,
Integer
>
audioParams
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
Pair
<
Integer
,
Integer
>
audioParams
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
audioSpecificConfig
);
audioSpecificConfig
);
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
MediaFormat
.
NO_VALUE
,
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
null
,
MimeTypes
.
AUDIO_AAC
,
MimeTypes
.
AUDIO_AAC
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
getDurationUs
(),
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
getDurationUs
(),
audioParams
.
second
,
audioParams
.
second
,
audioParams
.
first
,
Collections
.
singletonList
(
audioSpecificConfig
),
audioParams
.
first
,
Collections
.
singletonList
(
audioSpecificConfig
),
null
);
null
);
output
.
format
(
mediaFormat
);
output
.
format
(
mediaFormat
);
hasOutputFormat
=
true
;
hasOutputFormat
=
true
;
}
else
if
(
packetType
==
AAC_PACKET_TYPE_AAC_RAW
)
{
}
else
if
(
packetType
==
AAC_PACKET_TYPE_AAC_RAW
)
{
...
...
library/src/main/java/com/google/android/exoplayer/extractor/flv/VideoTagPayloadReader.java
View file @
e252ddde
...
@@ -95,9 +95,9 @@ import java.util.List;
...
@@ -95,9 +95,9 @@ import java.util.List;
nalUnitLengthFieldLength
=
avcData
.
nalUnitLengthFieldLength
;
nalUnitLengthFieldLength
=
avcData
.
nalUnitLengthFieldLength
;
// Construct and output the format.
// Construct and output the format.
MediaFormat
mediaFormat
=
MediaFormat
.
createVideoFormat
(
MediaFormat
.
NO_VALUE
,
MediaFormat
mediaFormat
=
MediaFormat
.
createVideoFormat
(
null
,
MimeTypes
.
VIDEO_H264
,
M
imeTypes
.
VIDEO_H264
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
getDurationUs
()
,
M
ediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
getDurationUs
(),
avcData
.
width
,
avcData
.
width
,
avcData
.
height
,
avcData
.
initializationData
,
MediaFormat
.
NO_VALUE
,
avcData
.
height
,
avcData
.
initializationData
,
MediaFormat
.
NO_VALUE
,
avcData
.
pixelWidthAspectRatio
);
avcData
.
pixelWidthAspectRatio
);
output
.
format
(
mediaFormat
);
output
.
format
(
mediaFormat
);
hasOutputFormat
=
true
;
hasOutputFormat
=
true
;
...
...
library/src/main/java/com/google/android/exoplayer/extractor/mp3/Mp3Extractor.java
View file @
e252ddde
...
@@ -332,7 +332,7 @@ public final class Mp3Extractor implements Extractor {
...
@@ -332,7 +332,7 @@ public final class Mp3Extractor implements Extractor {
if
(
seeker
==
null
)
{
if
(
seeker
==
null
)
{
setupSeeker
(
extractorInput
,
headerPosition
);
setupSeeker
(
extractorInput
,
headerPosition
);
extractorOutput
.
seekMap
(
seeker
);
extractorOutput
.
seekMap
(
seeker
);
trackOutput
.
format
(
MediaFormat
.
createAudioFormat
(
MediaFormat
.
NO_VALUE
,
trackOutput
.
format
(
MediaFormat
.
createAudioFormat
(
null
,
synchronizedHeader
.
mimeType
,
MediaFormat
.
NO_VALUE
,
MpegAudioHeader
.
MAX_FRAME_SIZE_BYTES
,
synchronizedHeader
.
mimeType
,
MediaFormat
.
NO_VALUE
,
MpegAudioHeader
.
MAX_FRAME_SIZE_BYTES
,
seeker
.
getDurationUs
(),
synchronizedHeader
.
channels
,
synchronizedHeader
.
sampleRate
,
null
,
seeker
.
getDurationUs
(),
synchronizedHeader
.
channels
,
synchronizedHeader
.
sampleRate
,
null
,
null
));
null
));
...
...
library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java
View file @
e252ddde
...
@@ -454,13 +454,13 @@ import java.util.List;
...
@@ -454,13 +454,13 @@ import java.util.List;
parseAudioSampleEntry
(
stsd
,
childAtomType
,
childStartPosition
,
childAtomSize
,
trackId
,
parseAudioSampleEntry
(
stsd
,
childAtomType
,
childStartPosition
,
childAtomSize
,
trackId
,
durationUs
,
language
,
out
,
i
);
durationUs
,
language
,
out
,
i
);
}
else
if
(
childAtomType
==
Atom
.
TYPE_TTML
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_TTML
)
{
out
.
mediaFormat
=
MediaFormat
.
createTextFormat
(
trackId
,
MimeTypes
.
APPLICATION_TTML
,
out
.
mediaFormat
=
MediaFormat
.
createTextFormat
(
Integer
.
toString
(
trackId
)
,
MimeTypes
.
APPLICATION_TTML
,
MediaFormat
.
NO_VALUE
,
durationUs
,
language
);
MediaFormat
.
NO_VALUE
,
durationUs
,
language
);
}
else
if
(
childAtomType
==
Atom
.
TYPE_tx3g
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_tx3g
)
{
out
.
mediaFormat
=
MediaFormat
.
createTextFormat
(
trackId
,
MimeTypes
.
APPLICATION_TX3G
,
out
.
mediaFormat
=
MediaFormat
.
createTextFormat
(
Integer
.
toString
(
trackId
)
,
MimeTypes
.
APPLICATION_TX3G
,
MediaFormat
.
NO_VALUE
,
durationUs
,
language
);
MediaFormat
.
NO_VALUE
,
durationUs
,
language
);
}
else
if
(
childAtomType
==
Atom
.
TYPE_stpp
)
{
}
else
if
(
childAtomType
==
Atom
.
TYPE_stpp
)
{
out
.
mediaFormat
=
MediaFormat
.
createTextFormat
(
trackId
,
MimeTypes
.
APPLICATION_TTML
,
out
.
mediaFormat
=
MediaFormat
.
createTextFormat
(
Integer
.
toString
(
trackId
)
,
MimeTypes
.
APPLICATION_TTML
,
MediaFormat
.
NO_VALUE
,
durationUs
,
language
,
0
/* subsample timing is absolute */
);
MediaFormat
.
NO_VALUE
,
durationUs
,
language
,
0
/* subsample timing is absolute */
);
}
}
stsd
.
setPosition
(
childStartPosition
+
childAtomSize
);
stsd
.
setPosition
(
childStartPosition
+
childAtomSize
);
...
@@ -531,7 +531,7 @@ import java.util.List;
...
@@ -531,7 +531,7 @@ import java.util.List;
return
;
return
;
}
}
out
.
mediaFormat
=
MediaFormat
.
createVideoFormat
(
trackId
,
mimeType
,
MediaFormat
.
NO_VALUE
,
out
.
mediaFormat
=
MediaFormat
.
createVideoFormat
(
Integer
.
toString
(
trackId
)
,
mimeType
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
durationUs
,
width
,
height
,
initializationData
,
rotationDegrees
,
MediaFormat
.
NO_VALUE
,
durationUs
,
width
,
height
,
initializationData
,
rotationDegrees
,
pixelWidthHeightRatio
);
pixelWidthHeightRatio
);
}
}
...
@@ -753,7 +753,7 @@ import java.util.List;
...
@@ -753,7 +753,7 @@ import java.util.List;
}
else
if
((
atomType
==
Atom
.
TYPE_dtsc
||
atomType
==
Atom
.
TYPE_dtse
}
else
if
((
atomType
==
Atom
.
TYPE_dtsc
||
atomType
==
Atom
.
TYPE_dtse
||
atomType
==
Atom
.
TYPE_dtsh
||
atomType
==
Atom
.
TYPE_dtsl
)
||
atomType
==
Atom
.
TYPE_dtsh
||
atomType
==
Atom
.
TYPE_dtsl
)
&&
childAtomType
==
Atom
.
TYPE_ddts
)
{
&&
childAtomType
==
Atom
.
TYPE_ddts
)
{
out
.
mediaFormat
=
MediaFormat
.
createAudioFormat
(
trackId
,
mimeType
,
MediaFormat
.
NO_VALUE
,
out
.
mediaFormat
=
MediaFormat
.
createAudioFormat
(
Integer
.
toString
(
trackId
)
,
mimeType
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
durationUs
,
channelCount
,
sampleRate
,
null
,
language
);
MediaFormat
.
NO_VALUE
,
durationUs
,
channelCount
,
sampleRate
,
null
,
language
);
return
;
return
;
}
}
...
@@ -765,7 +765,7 @@ import java.util.List;
...
@@ -765,7 +765,7 @@ import java.util.List;
return
;
return
;
}
}
out
.
mediaFormat
=
MediaFormat
.
createAudioFormat
(
trackId
,
mimeType
,
MediaFormat
.
NO_VALUE
,
out
.
mediaFormat
=
MediaFormat
.
createAudioFormat
(
Integer
.
toString
(
trackId
)
,
mimeType
,
MediaFormat
.
NO_VALUE
,
sampleSize
,
durationUs
,
channelCount
,
sampleRate
,
sampleSize
,
durationUs
,
channelCount
,
sampleRate
,
initializationData
==
null
?
null
:
Collections
.
singletonList
(
initializationData
),
initializationData
==
null
?
null
:
Collections
.
singletonList
(
initializationData
),
language
);
language
);
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/AdtsReader.java
View file @
e252ddde
...
@@ -170,7 +170,7 @@ import java.util.Collections;
...
@@ -170,7 +170,7 @@ import java.util.Collections;
Pair
<
Integer
,
Integer
>
audioParams
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
Pair
<
Integer
,
Integer
>
audioParams
=
CodecSpecificDataUtil
.
parseAacAudioSpecificConfig
(
audioSpecificConfig
);
audioSpecificConfig
);
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
MediaFormat
.
NO_VALUE
,
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
null
,
MimeTypes
.
AUDIO_AAC
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
MimeTypes
.
AUDIO_AAC
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
audioParams
.
second
,
audioParams
.
first
,
Collections
.
singletonList
(
audioSpecificConfig
),
audioParams
.
second
,
audioParams
.
first
,
Collections
.
singletonList
(
audioSpecificConfig
),
null
);
null
);
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/H264Reader.java
View file @
e252ddde
...
@@ -210,7 +210,7 @@ import java.util.List;
...
@@ -210,7 +210,7 @@ import java.util.List;
SpsData
parsedSpsData
=
CodecSpecificDataUtil
.
parseSpsNalUnit
(
bitArray
);
SpsData
parsedSpsData
=
CodecSpecificDataUtil
.
parseSpsNalUnit
(
bitArray
);
// Construct and output the format.
// Construct and output the format.
output
.
format
(
MediaFormat
.
createVideoFormat
(
MediaFormat
.
NO_VALUE
,
MimeTypes
.
VIDEO_H264
,
output
.
format
(
MediaFormat
.
createVideoFormat
(
null
,
MimeTypes
.
VIDEO_H264
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
parsedSpsData
.
width
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
parsedSpsData
.
width
,
parsedSpsData
.
height
,
initializationData
,
MediaFormat
.
NO_VALUE
,
parsedSpsData
.
height
,
initializationData
,
MediaFormat
.
NO_VALUE
,
parsedSpsData
.
pixelWidthAspectRatio
));
parsedSpsData
.
pixelWidthAspectRatio
));
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/H265Reader.java
View file @
e252ddde
...
@@ -294,7 +294,7 @@ import java.util.Collections;
...
@@ -294,7 +294,7 @@ import java.util.Collections;
}
}
}
}
output
.
format
(
MediaFormat
.
createVideoFormat
(
MediaFormat
.
NO_VALUE
,
MimeTypes
.
VIDEO_H265
,
output
.
format
(
MediaFormat
.
createVideoFormat
(
null
,
MimeTypes
.
VIDEO_H265
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
picWidthInLumaSamples
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
picWidthInLumaSamples
,
picHeightInLumaSamples
,
Collections
.
singletonList
(
csd
),
MediaFormat
.
NO_VALUE
,
picHeightInLumaSamples
,
Collections
.
singletonList
(
csd
),
MediaFormat
.
NO_VALUE
,
pixelWidthHeightRatio
));
pixelWidthHeightRatio
));
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/Id3Reader.java
View file @
e252ddde
...
@@ -35,7 +35,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
...
@@ -35,7 +35,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
public
Id3Reader
(
TrackOutput
output
)
{
public
Id3Reader
(
TrackOutput
output
)
{
super
(
output
);
super
(
output
);
output
.
format
(
MediaFormat
.
createFormatForMimeType
(
MediaFormat
.
NO_VALUE
,
output
.
format
(
MediaFormat
.
createFormatForMimeType
(
null
,
MimeTypes
.
APPLICATION_ID3
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
));
MimeTypes
.
APPLICATION_ID3
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
));
}
}
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/MpegAudioReader.java
View file @
e252ddde
...
@@ -160,7 +160,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
...
@@ -160,7 +160,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
frameSize
=
header
.
frameSize
;
frameSize
=
header
.
frameSize
;
if
(!
hasOutputFormat
)
{
if
(!
hasOutputFormat
)
{
frameDurationUs
=
(
C
.
MICROS_PER_SECOND
*
header
.
samplesPerFrame
)
/
header
.
sampleRate
;
frameDurationUs
=
(
C
.
MICROS_PER_SECOND
*
header
.
samplesPerFrame
)
/
header
.
sampleRate
;
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
MediaFormat
.
NO_VALUE
,
header
.
mimeType
,
MediaFormat
mediaFormat
=
MediaFormat
.
createAudioFormat
(
null
,
header
.
mimeType
,
MediaFormat
.
NO_VALUE
,
MpegAudioHeader
.
MAX_FRAME_SIZE_BYTES
,
C
.
UNKNOWN_TIME_US
,
MediaFormat
.
NO_VALUE
,
MpegAudioHeader
.
MAX_FRAME_SIZE_BYTES
,
C
.
UNKNOWN_TIME_US
,
header
.
channels
,
header
.
sampleRate
,
null
,
null
);
header
.
channels
,
header
.
sampleRate
,
null
,
null
);
output
.
format
(
mediaFormat
);
output
.
format
(
mediaFormat
);
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ts/SeiReader.java
View file @
e252ddde
...
@@ -32,7 +32,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
...
@@ -32,7 +32,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
public
SeiReader
(
TrackOutput
output
)
{
public
SeiReader
(
TrackOutput
output
)
{
super
(
output
);
super
(
output
);
output
.
format
(
MediaFormat
.
createTextFormat
(
MediaFormat
.
NO_VALUE
,
MimeTypes
.
APPLICATION_EIA608
,
output
.
format
(
MediaFormat
.
createTextFormat
(
null
,
MimeTypes
.
APPLICATION_EIA608
,
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
null
));
MediaFormat
.
NO_VALUE
,
C
.
UNKNOWN_TIME_US
,
null
));
}
}
...
...
library/src/main/java/com/google/android/exoplayer/extractor/webm/WebmExtractor.java
View file @
e252ddde
...
@@ -1227,14 +1227,16 @@ public final class WebmExtractor implements Extractor {
...
@@ -1227,14 +1227,16 @@ public final class WebmExtractor implements Extractor {
}
}
MediaFormat
format
;
MediaFormat
format
;
// TODO: Read the name of the track from the header of the webm container and
// supply this as id instead of trackId?
if
(
MimeTypes
.
isAudio
(
mimeType
))
{
if
(
MimeTypes
.
isAudio
(
mimeType
))
{
format
=
MediaFormat
.
createAudioFormat
(
trackId
,
mimeType
,
MediaFormat
.
NO_VALUE
,
format
=
MediaFormat
.
createAudioFormat
(
Integer
.
toString
(
trackId
)
,
mimeType
,
MediaFormat
.
NO_VALUE
,
maxInputSize
,
durationUs
,
channelCount
,
sampleRate
,
initializationData
,
language
);
maxInputSize
,
durationUs
,
channelCount
,
sampleRate
,
initializationData
,
language
);
}
else
if
(
MimeTypes
.
isVideo
(
mimeType
))
{
}
else
if
(
MimeTypes
.
isVideo
(
mimeType
))
{
format
=
MediaFormat
.
createVideoFormat
(
trackId
,
mimeType
,
MediaFormat
.
NO_VALUE
,
format
=
MediaFormat
.
createVideoFormat
(
Integer
.
toString
(
trackId
)
,
mimeType
,
MediaFormat
.
NO_VALUE
,
maxInputSize
,
durationUs
,
width
,
height
,
initializationData
);
maxInputSize
,
durationUs
,
width
,
height
,
initializationData
);
}
else
if
(
MimeTypes
.
APPLICATION_SUBRIP
.
equals
(
mimeType
))
{
}
else
if
(
MimeTypes
.
APPLICATION_SUBRIP
.
equals
(
mimeType
))
{
format
=
MediaFormat
.
createTextFormat
(
trackId
,
mimeType
,
MediaFormat
.
NO_VALUE
,
durationUs
,
format
=
MediaFormat
.
createTextFormat
(
Integer
.
toString
(
trackId
)
,
mimeType
,
MediaFormat
.
NO_VALUE
,
durationUs
,
language
);
language
);
}
else
{
}
else
{
throw
new
ParserException
(
"Unexpected MIME type."
);
throw
new
ParserException
(
"Unexpected MIME type."
);
...
...
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
View file @
e252ddde
...
@@ -398,7 +398,7 @@ public class SmoothStreamingChunkSource implements ChunkSource,
...
@@ -398,7 +398,7 @@ public class SmoothStreamingChunkSource implements ChunkSource,
int
mp4TrackType
;
int
mp4TrackType
;
switch
(
element
.
type
)
{
switch
(
element
.
type
)
{
case
StreamElement
.
TYPE_VIDEO
:
case
StreamElement
.
TYPE_VIDEO
:
mediaFormat
=
MediaFormat
.
createVideoFormat
(
MediaFormat
.
NO_VALUE
,
format
.
mimeType
,
mediaFormat
=
MediaFormat
.
createVideoFormat
(
format
.
id
,
format
.
mimeType
,
format
.
bitrate
,
MediaFormat
.
NO_VALUE
,
durationUs
,
format
.
width
,
format
.
height
,
format
.
bitrate
,
MediaFormat
.
NO_VALUE
,
durationUs
,
format
.
width
,
format
.
height
,
Arrays
.
asList
(
csdArray
));
Arrays
.
asList
(
csdArray
));
mp4TrackType
=
Track
.
TYPE_vide
;
mp4TrackType
=
Track
.
TYPE_vide
;
...
@@ -411,13 +411,13 @@ public class SmoothStreamingChunkSource implements ChunkSource,
...
@@ -411,13 +411,13 @@ public class SmoothStreamingChunkSource implements ChunkSource,
csd
=
Collections
.
singletonList
(
CodecSpecificDataUtil
.
buildAacAudioSpecificConfig
(
csd
=
Collections
.
singletonList
(
CodecSpecificDataUtil
.
buildAacAudioSpecificConfig
(
format
.
audioSamplingRate
,
format
.
audioChannels
));
format
.
audioSamplingRate
,
format
.
audioChannels
));
}
}
mediaFormat
=
MediaFormat
.
createAudioFormat
(
MediaFormat
.
NO_VALUE
,
format
.
mimeType
,
mediaFormat
=
MediaFormat
.
createAudioFormat
(
format
.
id
,
format
.
mimeType
,
format
.
bitrate
,
MediaFormat
.
NO_VALUE
,
durationUs
,
format
.
audioChannels
,
format
.
bitrate
,
MediaFormat
.
NO_VALUE
,
durationUs
,
format
.
audioChannels
,
format
.
audioSamplingRate
,
csd
,
format
.
language
);
format
.
audioSamplingRate
,
csd
,
format
.
language
);
mp4TrackType
=
Track
.
TYPE_soun
;
mp4TrackType
=
Track
.
TYPE_soun
;
break
;
break
;
case
StreamElement
.
TYPE_TEXT
:
case
StreamElement
.
TYPE_TEXT
:
mediaFormat
=
MediaFormat
.
createTextFormat
(
MediaFormat
.
NO_VALUE
,
format
.
mimeType
,
mediaFormat
=
MediaFormat
.
createTextFormat
(
format
.
id
,
format
.
mimeType
,
format
.
bitrate
,
durationUs
,
format
.
language
);
format
.
bitrate
,
durationUs
,
format
.
language
);
mp4TrackType
=
Track
.
TYPE_text
;
mp4TrackType
=
Track
.
TYPE_text
;
break
;
break
;
...
...
library/src/main/java/com/google/android/exoplayer/util/Ac3Util.java
View file @
e252ddde
...
@@ -55,7 +55,7 @@ public final class Ac3Util {
...
@@ -55,7 +55,7 @@ public final class Ac3Util {
if
((
nextByte
&
0x04
)
!=
0
)
{
if
((
nextByte
&
0x04
)
!=
0
)
{
channelCount
++;
channelCount
++;
}
}
return
MediaFormat
.
createAudioFormat
(
trackId
,
MimeTypes
.
AUDIO_AC3
,
MediaFormat
.
NO_VALUE
,
return
MediaFormat
.
createAudioFormat
(
Integer
.
toString
(
trackId
)
,
MimeTypes
.
AUDIO_AC3
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
durationUs
,
channelCount
,
sampleRate
,
null
,
language
);
MediaFormat
.
NO_VALUE
,
durationUs
,
channelCount
,
sampleRate
,
null
,
language
);
}
}
...
@@ -85,7 +85,7 @@ public final class Ac3Util {
...
@@ -85,7 +85,7 @@ public final class Ac3Util {
if
((
nextByte
&
0x01
)
!=
0
)
{
if
((
nextByte
&
0x01
)
!=
0
)
{
channelCount
++;
channelCount
++;
}
}
return
MediaFormat
.
createAudioFormat
(
trackId
,
MimeTypes
.
AUDIO_EC3
,
MediaFormat
.
NO_VALUE
,
return
MediaFormat
.
createAudioFormat
(
Integer
.
toString
(
trackId
)
,
MimeTypes
.
AUDIO_EC3
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
durationUs
,
channelCount
,
sampleRate
,
null
,
language
);
MediaFormat
.
NO_VALUE
,
durationUs
,
channelCount
,
sampleRate
,
null
,
language
);
}
}
...
@@ -117,7 +117,7 @@ public final class Ac3Util {
...
@@ -117,7 +117,7 @@ public final class Ac3Util {
data
.
skipBits
(
2
);
// dsurmod
data
.
skipBits
(
2
);
// dsurmod
}
}
boolean
lfeon
=
data
.
readBit
();
boolean
lfeon
=
data
.
readBit
();
return
MediaFormat
.
createAudioFormat
(
trackId
,
MimeTypes
.
AUDIO_AC3
,
MediaFormat
.
NO_VALUE
,
return
MediaFormat
.
createAudioFormat
(
Integer
.
toString
(
trackId
)
,
MimeTypes
.
AUDIO_AC3
,
MediaFormat
.
NO_VALUE
,
MediaFormat
.
NO_VALUE
,
durationUs
,
CHANNEL_COUNTS
[
acmod
]
+
(
lfeon
?
1
:
0
),
MediaFormat
.
NO_VALUE
,
durationUs
,
CHANNEL_COUNTS
[
acmod
]
+
(
lfeon
?
1
:
0
),
SAMPLE_RATES
[
fscod
],
null
,
language
);
SAMPLE_RATES
[
fscod
],
null
,
language
);
}
}
...
...
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