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
efff7a9d
authored
May 06, 2020
by
krocard
Committed by
Oliver Woodman
May 06, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Propagate sample rate and format deeper
#exo-offload PiperOrigin-RevId: 310150780
parent
8077fe1b
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
57 additions
and
52 deletions
extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java
extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java
extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/LibopusAudioRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java
library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java
library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java
extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java
View file @
efff7a9d
...
...
@@ -143,12 +143,14 @@ public final class FfmpegAudioRenderer extends DecoderAudioRenderer {
private
boolean
isOutputSupported
(
Format
inputFormat
)
{
return
shouldUseFloatOutput
(
inputFormat
)
||
supportsOutput
(
inputFormat
.
channelCount
,
C
.
ENCODING_PCM_16BIT
);
||
supportsOutput
(
inputFormat
.
channelCount
,
inputFormat
.
sampleRate
,
C
.
ENCODING_PCM_16BIT
);
}
private
boolean
shouldUseFloatOutput
(
Format
inputFormat
)
{
Assertions
.
checkNotNull
(
inputFormat
.
sampleMimeType
);
if
(!
enableFloatOutput
||
!
supportsOutput
(
inputFormat
.
channelCount
,
C
.
ENCODING_PCM_FLOAT
))
{
if
(!
enableFloatOutput
||
!
supportsOutput
(
inputFormat
.
channelCount
,
inputFormat
.
sampleRate
,
C
.
ENCODING_PCM_FLOAT
))
{
return
false
;
}
switch
(
inputFormat
.
sampleMimeType
)
{
...
...
extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java
View file @
efff7a9d
...
...
@@ -100,7 +100,7 @@ public final class LibflacAudioRenderer extends DecoderAudioRenderer {
new
FlacStreamMetadata
(
format
.
initializationData
.
get
(
0
),
streamMetadataOffset
);
pcmEncoding
=
Util
.
getPcmEncoding
(
streamMetadata
.
bitsPerSample
);
}
if
(!
supportsOutput
(
format
.
channelCount
,
pcmEncoding
))
{
if
(!
supportsOutput
(
format
.
channelCount
,
format
.
sampleRate
,
pcmEncoding
))
{
return
FORMAT_UNSUPPORTED_SUBTYPE
;
}
else
if
(
format
.
drmInitData
!=
null
&&
format
.
exoMediaCryptoType
==
null
)
{
return
FORMAT_UNSUPPORTED_DRM
;
...
...
extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/LibopusAudioRenderer.java
View file @
efff7a9d
...
...
@@ -69,7 +69,7 @@ public class LibopusAudioRenderer extends DecoderAudioRenderer {
if
(!
OpusLibrary
.
isAvailable
()
||
!
MimeTypes
.
AUDIO_OPUS
.
equalsIgnoreCase
(
format
.
sampleMimeType
))
{
return
FORMAT_UNSUPPORTED_TYPE
;
}
else
if
(!
supportsOutput
(
format
.
channelCount
,
C
.
ENCODING_PCM_16BIT
))
{
}
else
if
(!
supportsOutput
(
format
.
channelCount
,
format
.
sampleRate
,
C
.
ENCODING_PCM_16BIT
))
{
return
FORMAT_UNSUPPORTED_SUBTYPE
;
}
else
if
(!
drmIsSupported
)
{
return
FORMAT_UNSUPPORTED_DRM
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java
View file @
efff7a9d
...
...
@@ -177,10 +177,11 @@ public interface AudioSink {
* Returns whether the sink supports the audio format.
*
* @param channelCount The number of channels, or {@link Format#NO_VALUE} if not known.
* @param sampleRate The sample rate, or {@link Format#NO_VALUE} if not known.
* @param encoding The audio encoding, or {@link Format#NO_VALUE} if not known.
* @return Whether the sink supports the audio format.
*/
boolean
supportsOutput
(
int
channelCount
,
@C
.
Encoding
int
encoding
);
boolean
supportsOutput
(
int
channelCount
,
int
sampleRate
,
@C
.
Encoding
int
encoding
);
/**
* Returns the playback position in the stream starting at zero, in microseconds, or
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java
View file @
efff7a9d
...
...
@@ -214,10 +214,11 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
/**
* Returns whether the sink supports the audio format.
*
* @see AudioSink#supportsOutput(int, int)
* @see AudioSink#supportsOutput(int, int
, int
)
*/
protected
final
boolean
supportsOutput
(
int
channelCount
,
@C
.
Encoding
int
encoding
)
{
return
audioSink
.
supportsOutput
(
channelCount
,
encoding
);
protected
final
boolean
supportsOutput
(
int
channelCount
,
int
sampleRateHz
,
@C
.
Encoding
int
encoding
)
{
return
audioSink
.
supportsOutput
(
channelCount
,
sampleRateHz
,
encoding
);
}
@Override
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java
View file @
efff7a9d
...
...
@@ -395,7 +395,7 @@ public final class DefaultAudioSink implements AudioSink {
}
@Override
public
boolean
supportsOutput
(
int
channelCount
,
@C
.
Encoding
int
encoding
)
{
public
boolean
supportsOutput
(
int
channelCount
,
int
sampleRateHz
,
@C
.
Encoding
int
encoding
)
{
if
(
Util
.
isEncodingLinearPcm
(
encoding
))
{
// AudioTrack supports 16-bit integer PCM output in all platform API versions, and float
// output from platform API version 21 only. Other integer PCM encodings are resampled by this
...
...
@@ -446,7 +446,7 @@ public final class DefaultAudioSink implements AudioSink {
@C
.
Encoding
int
encoding
=
inputEncoding
;
boolean
useFloatOutput
=
enableFloatOutput
&&
supportsOutput
(
inputChannelCount
,
C
.
ENCODING_PCM_FLOAT
)
&&
supportsOutput
(
inputChannelCount
,
inputSampleRate
,
C
.
ENCODING_PCM_FLOAT
)
&&
Util
.
isEncodingHighResolutionPcm
(
inputEncoding
);
AudioProcessor
[]
availableAudioProcessors
=
useFloatOutput
?
toFloatPcmAvailableAudioProcessors
:
toIntPcmAvailableAudioProcessors
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java
View file @
efff7a9d
...
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
audio
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.PlaybackParameters
;
import
java.nio.ByteBuffer
;
...
...
@@ -34,8 +35,8 @@ public class ForwardingAudioSink implements AudioSink {
}
@Override
public
boolean
supportsOutput
(
int
channelCount
,
int
encoding
)
{
return
sink
.
supportsOutput
(
channelCount
,
encoding
);
public
boolean
supportsOutput
(
int
channelCount
,
int
sampleRate
,
@C
.
Encoding
int
encoding
)
{
return
sink
.
supportsOutput
(
channelCount
,
sampleRate
,
encoding
);
}
@Override
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
View file @
efff7a9d
...
...
@@ -85,7 +85,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
private
boolean
passthroughEnabled
;
private
boolean
codecNeedsDiscardChannelsWorkaround
;
private
boolean
codecNeedsEosBufferTimestampWorkaround
;
private
android
.
media
.
MediaFormat
passthroughMedia
Format
;
@Nullable
private
Format
passthrough
Format
;
@Nullable
private
Format
inputFormat
;
private
long
currentPositionUs
;
private
boolean
allowFirstBufferPositionDiscontinuity
;
...
...
@@ -210,8 +210,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Capabilities
protected
int
supportsFormat
(
MediaCodecSelector
mediaCodecSelector
,
Format
format
)
throws
DecoderQueryException
{
String
mimeType
=
format
.
sampleMimeType
;
if
(!
MimeTypes
.
isAudio
(
mimeType
))
{
if
(!
MimeTypes
.
isAudio
(
format
.
sampleMimeType
))
{
return
RendererCapabilities
.
create
(
FORMAT_UNSUPPORTED_TYPE
);
}
@TunnelingSupport
...
...
@@ -220,13 +219,15 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
// In passthrough mode, if DRM init data is present we need to use a passthrough decoder to
// decrypt the content. For passthrough of clear content we don't need a decoder at all.
if
(
supportsFormatDrm
&&
usePassthrough
(
format
.
channelCount
,
mimeType
)
&&
usePassthrough
(
format
)
&&
(
format
.
drmInitData
==
null
||
MediaCodecUtil
.
getPassthroughDecoderInfo
()
!=
null
))
{
return
RendererCapabilities
.
create
(
FORMAT_HANDLED
,
ADAPTIVE_NOT_SEAMLESS
,
tunnelingSupport
);
}
if
((
MimeTypes
.
AUDIO_RAW
.
equals
(
mimeType
)
&&
!
audioSink
.
supportsOutput
(
format
.
channelCount
,
format
.
pcmEncoding
))
||
!
audioSink
.
supportsOutput
(
format
.
channelCount
,
C
.
ENCODING_PCM_16BIT
))
{
if
((
MimeTypes
.
AUDIO_RAW
.
equals
(
format
.
sampleMimeType
)
&&
!
audioSink
.
supportsOutput
(
format
.
channelCount
,
format
.
sampleRate
,
format
.
pcmEncoding
))
||
!
audioSink
.
supportsOutput
(
format
.
channelCount
,
format
.
sampleRate
,
C
.
ENCODING_PCM_16BIT
))
{
// Assume the decoder outputs 16-bit PCM, unless the input is raw.
return
RendererCapabilities
.
create
(
FORMAT_UNSUPPORTED_SUBTYPE
);
}
...
...
@@ -259,7 +260,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
if
(
mimeType
==
null
)
{
return
Collections
.
emptyList
();
}
if
(
usePassthrough
(
format
.
channelCount
,
mimeType
))
{
if
(
usePassthrough
(
format
))
{
@Nullable
MediaCodecInfo
codecInfo
=
MediaCodecUtil
.
getPassthroughDecoderInfo
();
if
(
codecInfo
!=
null
)
{
return
Collections
.
singletonList
(
codecInfo
);
...
...
@@ -281,8 +282,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
@Override
protected
boolean
usePassthrough
(
int
channelCount
,
String
mimeType
)
{
return
getPassthroughEncoding
(
channelCount
,
mimeType
)
!=
C
.
ENCODING_INVALID
;
protected
boolean
usePassthrough
(
Format
format
)
{
return
getPassthroughEncoding
(
format
)
!=
C
.
ENCODING_INVALID
;
}
@Override
...
...
@@ -301,13 +302,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
MediaFormat
mediaFormat
=
getMediaFormat
(
format
,
codecInfo
.
codecMimeType
,
codecMaxInputSize
,
codecOperatingRate
);
codec
.
configure
(
mediaFormat
,
/* surface= */
null
,
crypto
,
/* flags= */
0
);
if
(
passthroughEnabled
)
{
// Store the input MIME type if we're using the passthrough codec.
passthroughMediaFormat
=
mediaFormat
;
passthroughMediaFormat
.
setString
(
MediaFormat
.
KEY_MIME
,
format
.
sampleMimeType
);
}
else
{
passthroughMediaFormat
=
null
;
}
// Store the input MIME type if we're using the passthrough codec.
passthroughFormat
=
passthroughEnabled
?
format
:
null
;
}
@Override
...
...
@@ -394,23 +390,21 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
protected
void
onOutputMediaFormatChanged
(
MediaCodec
codec
,
MediaFormat
outputMediaFormat
)
throws
ExoPlaybackException
{
@C
.
Encoding
int
encoding
;
MediaFormat
mediaFormat
;
if
(
passthroughMediaFormat
!=
null
)
{
mediaFormat
=
passthroughMediaFormat
;
encoding
=
getPassthroughEncoding
(
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
),
mediaFormat
.
getString
(
MediaFormat
.
KEY_MIME
));
int
channelCount
;
int
sampleRate
;
if
(
passthroughFormat
!=
null
)
{
encoding
=
getPassthroughEncoding
(
passthroughFormat
);
channelCount
=
passthroughFormat
.
channelCount
;
sampleRate
=
passthroughFormat
.
sampleRate
;
}
else
{
mediaFormat
=
outputMediaFormat
;
if
(
outputMediaFormat
.
containsKey
(
VIVO_BITS_PER_SAMPLE_KEY
))
{
encoding
=
Util
.
getPcmEncoding
(
outputMediaFormat
.
getInteger
(
VIVO_BITS_PER_SAMPLE_KEY
));
}
else
{
encoding
=
getPcmEncoding
(
inputFormat
);
}
channelCount
=
outputMediaFormat
.
getInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
);
sampleRate
=
outputMediaFormat
.
getInteger
(
MediaFormat
.
KEY_SAMPLE_RATE
);
}
int
channelCount
=
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
);
int
sampleRate
=
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_SAMPLE_RATE
);
@Nullable
int
[]
channelMap
=
null
;
if
(
codecNeedsDiscardChannelsWorkaround
&&
channelCount
==
6
&&
inputFormat
.
channelCount
<
6
)
{
channelMap
=
new
int
[
inputFormat
.
channelCount
];
...
...
@@ -435,8 +429,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override
protected
void
onOutputPassthroughFormatChanged
(
Format
outputFormat
)
throws
ExoPlaybackException
{
@C
.
Encoding
int
encoding
=
getPassthroughEncoding
(
outputFormat
.
channelCount
,
outputFormat
.
sampleMimeType
);
@C
.
Encoding
int
encoding
=
getPassthroughEncoding
(
outputFormat
);
try
{
audioSink
.
configure
(
encoding
,
...
...
@@ -454,16 +447,22 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
/**
* Returns the {@link C.Encoding} constant to use for passthrough of the given format, or {@link
* C#ENCODING_INVALID} if passthrough is not possible.
*
* @param format The format for which to get the encoding.
* @return The {@link C.Encoding} corresponding to the format, or {@link C#ENCODING_INVALID} if
* the format is not supported.
*/
@C
.
Encoding
protected
int
getPassthroughEncoding
(
int
channelCount
,
String
mimeType
)
{
protected
int
getPassthroughEncoding
(
Format
format
)
{
@Nullable
String
mimeType
=
format
.
sampleMimeType
;
if
(
MimeTypes
.
AUDIO_RAW
.
equals
(
mimeType
))
{
// PCM passthrough is not supported.
return
C
.
ENCODING_INVALID
;
}
if
(
MimeTypes
.
AUDIO_E_AC3_JOC
.
equals
(
mimeType
))
{
// E-AC3 JOC is object-based so the output channel count is arbitrary.
if
(
audioSink
.
supportsOutput
(
/* channelCount= */
Format
.
NO_VALUE
,
C
.
ENCODING_E_AC3_JOC
))
{
if
(
audioSink
.
supportsOutput
(
/* channelCount= */
Format
.
NO_VALUE
,
format
.
sampleRate
,
C
.
ENCODING_E_AC3_JOC
))
{
return
MimeTypes
.
getEncoding
(
MimeTypes
.
AUDIO_E_AC3_JOC
);
}
// E-AC3 receivers can decode JOC streams, but in 2-D rather than 3-D, so try to fall back.
...
...
@@ -471,7 +470,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
@C
.
Encoding
int
encoding
=
MimeTypes
.
getEncoding
(
mimeType
);
if
(
audioSink
.
supportsOutput
(
channelCount
,
encoding
))
{
if
(
audioSink
.
supportsOutput
(
format
.
channelCount
,
format
.
sampleRate
,
encoding
))
{
return
encoding
;
}
else
{
return
C
.
ENCODING_INVALID
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
View file @
efff7a9d
...
...
@@ -578,8 +578,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return
;
}
if
(
inputFormat
.
drmInitData
==
null
&&
usePassthrough
(
inputFormat
.
channelCount
,
inputFormat
.
sampleMimeType
))
{
if
(
inputFormat
.
drmInitData
==
null
&&
usePassthrough
(
inputFormat
))
{
initPassthrough
(
inputFormat
);
return
;
}
...
...
@@ -632,12 +631,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
/**
* Returns whether encoded passthrough should be used for playing back the input format.
*
* @param channelCount The number of channels in the input media, or {@link Format#NO_VALUE} if
* not known.
* @param mimeType The type of input media.
* @param format The input {@link Format}.
* @return Whether passthrough playback is supported.
*/
protected
boolean
usePassthrough
(
int
channelCount
,
String
mimeType
)
{
protected
boolean
usePassthrough
(
Format
format
)
{
return
false
;
}
...
...
library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java
View file @
efff7a9d
...
...
@@ -200,14 +200,18 @@ public final class DefaultAudioSinkTest {
@Config
(
minSdk
=
OLDEST_SDK
,
maxSdk
=
20
)
@Test
public
void
doesNotSupportFloatOutputBeforeApi21
()
{
assertThat
(
defaultAudioSink
.
supportsOutput
(
CHANNEL_COUNT_STEREO
,
C
.
ENCODING_PCM_FLOAT
))
assertThat
(
defaultAudioSink
.
supportsOutput
(
CHANNEL_COUNT_STEREO
,
SAMPLE_RATE_44_1
,
C
.
ENCODING_PCM_FLOAT
))
.
isFalse
();
}
@Config
(
minSdk
=
21
,
maxSdk
=
TARGET_SDK
)
@Test
public
void
supportsFloatOutputFromApi21
()
{
assertThat
(
defaultAudioSink
.
supportsOutput
(
CHANNEL_COUNT_STEREO
,
C
.
ENCODING_PCM_FLOAT
))
assertThat
(
defaultAudioSink
.
supportsOutput
(
CHANNEL_COUNT_STEREO
,
SAMPLE_RATE_44_1
,
C
.
ENCODING_PCM_FLOAT
))
.
isTrue
();
}
...
...
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