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
2347bd2c
authored
Apr 18, 2019
by
andrewlewis
Committed by
Andrew Lewis
Apr 18, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Prioritize decoders with format support
PiperOrigin-RevId: 244167456
parent
a985ca93
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
82 additions
and
51 deletions
RELEASENOTES.md
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
RELEASENOTES.md
View file @
2347bd2c
...
@@ -2,6 +2,9 @@
...
@@ -2,6 +2,9 @@
### dev-v2 (not yet released) ###
### dev-v2 (not yet released) ###
*
Decoders: prefer codecs that advertise format support over ones that do not,
even if they are listed lower in the
`MediaCodecList`
.
### 2.10.0 ###
### 2.10.0 ###
*
Core library:
*
Core library:
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
View file @
2347bd2c
...
@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
...
@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import
com.google.android.exoplayer2.mediacodec.MediaCodecInfo
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecInfo
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecRenderer
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecRenderer
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecSelector
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecSelector
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecUtil
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException
;
import
com.google.android.exoplayer2.mediacodec.MediaFormatUtil
;
import
com.google.android.exoplayer2.mediacodec.MediaFormatUtil
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
...
@@ -290,8 +291,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -290,8 +291,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
}
}
}
List
<
MediaCodecInfo
>
decoderInfos
=
List
<
MediaCodecInfo
>
decoderInfos
=
mediaCodecSelector
.
getDecoderInfos
(
getDecoderInfos
(
mediaCodecSelector
,
format
,
requiresSecureDecryption
);
format
.
sampleMimeType
,
requiresSecureDecryption
,
/* requiresTunnelingDecoder= */
false
);
if
(
decoderInfos
.
isEmpty
())
{
if
(
decoderInfos
.
isEmpty
())
{
return
requiresSecureDecryption
return
requiresSecureDecryption
&&
!
mediaCodecSelector
&&
!
mediaCodecSelector
...
@@ -327,8 +327,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -327,8 +327,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
return
Collections
.
singletonList
(
passthroughDecoderInfo
);
return
Collections
.
singletonList
(
passthroughDecoderInfo
);
}
}
}
}
return
mediaCodecSelector
.
getDecoderInfos
(
List
<
MediaCodecInfo
>
decoderInfos
=
mediaCodecSelector
.
getDecoderInfos
(
format
.
sampleMimeType
,
requiresSecureDecoder
,
/* requiresTunnelingDecoder= */
false
);
format
.
sampleMimeType
,
requiresSecureDecoder
,
/* requiresTunnelingDecoder= */
false
);
decoderInfos
=
MediaCodecUtil
.
getDecoderInfosSortedByFormatSupport
(
decoderInfos
,
format
);
return
Collections
.
unmodifiableList
(
decoderInfos
);
}
}
/**
/**
...
...
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java
View file @
2347bd2c
...
@@ -20,16 +20,17 @@ import android.annotation.TargetApi;
...
@@ -20,16 +20,17 @@ import android.annotation.TargetApi;
import
android.media.MediaCodecInfo.CodecCapabilities
;
import
android.media.MediaCodecInfo.CodecCapabilities
;
import
android.media.MediaCodecInfo.CodecProfileLevel
;
import
android.media.MediaCodecInfo.CodecProfileLevel
;
import
android.media.MediaCodecList
;
import
android.media.MediaCodecList
;
import
androidx.annotation.CheckResult
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
android.text.TextUtils
;
import
android.text.TextUtils
;
import
android.util.Pair
;
import
android.util.Pair
;
import
android.util.SparseIntArray
;
import
android.util.SparseIntArray
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -186,6 +187,26 @@ public final class MediaCodecUtil {
...
@@ -186,6 +187,26 @@ public final class MediaCodecUtil {
}
}
/**
/**
* Returns a copy of the provided decoder list sorted such that decoders with format support are
* listed first. The returned list is modifiable for convenience.
*/
@CheckResult
public
static
List
<
MediaCodecInfo
>
getDecoderInfosSortedByFormatSupport
(
List
<
MediaCodecInfo
>
decoderInfos
,
Format
format
)
{
decoderInfos
=
new
ArrayList
<>(
decoderInfos
);
sortByScore
(
decoderInfos
,
decoderInfo
->
{
try
{
return
decoderInfo
.
isFormatSupported
(
format
)
?
1
:
0
;
}
catch
(
DecoderQueryException
e
)
{
return
-
1
;
}
});
return
decoderInfos
;
}
/**
* Returns the maximum frame size supported by the default H264 decoder.
* Returns the maximum frame size supported by the default H264 decoder.
*
*
* @return The maximum frame size for an H264 stream that can be decoded on the device.
* @return The maximum frame size for an H264 stream that can be decoded on the device.
...
@@ -484,7 +505,22 @@ public final class MediaCodecUtil {
...
@@ -484,7 +505,22 @@ public final class MediaCodecUtil {
*/
*/
private
static
void
applyWorkarounds
(
String
mimeType
,
List
<
MediaCodecInfo
>
decoderInfos
)
{
private
static
void
applyWorkarounds
(
String
mimeType
,
List
<
MediaCodecInfo
>
decoderInfos
)
{
if
(
MimeTypes
.
AUDIO_RAW
.
equals
(
mimeType
))
{
if
(
MimeTypes
.
AUDIO_RAW
.
equals
(
mimeType
))
{
Collections
.
sort
(
decoderInfos
,
new
RawAudioCodecComparator
());
// Work around inconsistent raw audio decoding behavior across different devices.
sortByScore
(
decoderInfos
,
decoderInfo
->
{
String
name
=
decoderInfo
.
name
;
if
(
name
.
startsWith
(
"OMX.google"
)
||
name
.
startsWith
(
"c2.android"
))
{
// Prefer generic decoders over ones provided by the device.
return
1
;
}
if
(
Util
.
SDK_INT
<
26
&&
name
.
equals
(
"OMX.MTK.AUDIO.DECODER.RAW"
))
{
// This decoder may modify the audio, so any other compatible decoders take
// precedence. See [Internal: b/62337687].
return
-
1
;
}
return
0
;
});
}
else
if
(
Util
.
SDK_INT
<
21
&&
decoderInfos
.
size
()
>
1
)
{
}
else
if
(
Util
.
SDK_INT
<
21
&&
decoderInfos
.
size
()
>
1
)
{
String
firstCodecName
=
decoderInfos
.
get
(
0
).
name
;
String
firstCodecName
=
decoderInfos
.
get
(
0
).
name
;
if
(
"OMX.SEC.mp3.dec"
.
equals
(
firstCodecName
)
if
(
"OMX.SEC.mp3.dec"
.
equals
(
firstCodecName
)
...
@@ -494,7 +530,7 @@ public final class MediaCodecUtil {
...
@@ -494,7 +530,7 @@ public final class MediaCodecUtil {
// OMX.brcm.audio.mp3.decoder on older devices. See:
// OMX.brcm.audio.mp3.decoder on older devices. See:
// https://github.com/google/ExoPlayer/issues/398 and
// https://github.com/google/ExoPlayer/issues/398 and
// https://github.com/google/ExoPlayer/issues/4519.
// https://github.com/google/ExoPlayer/issues/4519.
Collections
.
sort
(
decoderInfos
,
new
PreferOmxGoogleCodecComparator
()
);
sortByScore
(
decoderInfos
,
decoderInfo
->
decoderInfo
.
name
.
startsWith
(
"OMX.google"
)
?
1
:
0
);
}
}
}
}
}
}
...
@@ -676,6 +712,17 @@ public final class MediaCodecUtil {
...
@@ -676,6 +712,17 @@ public final class MediaCodecUtil {
return
null
;
return
null
;
}
}
/** Stably sorts the provided {@code list} in-place, in order of decreasing score. */
private
static
<
T
>
void
sortByScore
(
List
<
T
>
list
,
ScoreProvider
<
T
>
scoreProvider
)
{
Collections
.
sort
(
list
,
(
a
,
b
)
->
scoreProvider
.
getScore
(
b
)
-
scoreProvider
.
getScore
(
a
));
}
/** Interface for providers of item scores. */
private
interface
ScoreProvider
<
T
>
{
/** Returns the score of the provided item. */
int
getScore
(
T
t
);
}
private
interface
MediaCodecListCompat
{
private
interface
MediaCodecListCompat
{
/**
/**
...
@@ -826,44 +873,6 @@ public final class MediaCodecUtil {
...
@@ -826,44 +873,6 @@ public final class MediaCodecUtil {
}
}
/**
* Comparator for ordering media codecs that handle {@link MimeTypes#AUDIO_RAW} to work around
* possible inconsistent behavior across different devices. A list sorted with this comparator has
* more preferred codecs first.
*/
private
static
final
class
RawAudioCodecComparator
implements
Comparator
<
MediaCodecInfo
>
{
@Override
public
int
compare
(
MediaCodecInfo
a
,
MediaCodecInfo
b
)
{
return
scoreMediaCodecInfo
(
a
)
-
scoreMediaCodecInfo
(
b
);
}
private
static
int
scoreMediaCodecInfo
(
MediaCodecInfo
mediaCodecInfo
)
{
String
name
=
mediaCodecInfo
.
name
;
if
(
name
.
startsWith
(
"OMX.google"
)
||
name
.
startsWith
(
"c2.android"
))
{
// Prefer generic decoders over ones provided by the device.
return
-
1
;
}
if
(
Util
.
SDK_INT
<
26
&&
name
.
equals
(
"OMX.MTK.AUDIO.DECODER.RAW"
))
{
// This decoder may modify the audio, so any other compatible decoders take precedence. See
// [Internal: b/62337687].
return
1
;
}
return
0
;
}
}
/** Comparator for preferring OMX.google media codecs. */
private
static
final
class
PreferOmxGoogleCodecComparator
implements
Comparator
<
MediaCodecInfo
>
{
@Override
public
int
compare
(
MediaCodecInfo
a
,
MediaCodecInfo
b
)
{
return
scoreMediaCodecInfo
(
a
)
-
scoreMediaCodecInfo
(
b
);
}
private
static
int
scoreMediaCodecInfo
(
MediaCodecInfo
mediaCodecInfo
)
{
return
mediaCodecInfo
.
name
.
startsWith
(
"OMX.google"
)
?
-
1
:
0
;
}
}
static
{
static
{
AVC_PROFILE_NUMBER_TO_CONST
=
new
SparseIntArray
();
AVC_PROFILE_NUMBER_TO_CONST
=
new
SparseIntArray
();
AVC_PROFILE_NUMBER_TO_CONST
.
put
(
66
,
CodecProfileLevel
.
AVCProfileBaseline
);
AVC_PROFILE_NUMBER_TO_CONST
.
put
(
66
,
CodecProfileLevel
.
AVCProfileBaseline
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
View file @
2347bd2c
...
@@ -306,12 +306,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -306,12 +306,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
}
}
List
<
MediaCodecInfo
>
decoderInfos
=
List
<
MediaCodecInfo
>
decoderInfos
=
getDecoderInfos
(
mediaCodecSelector
,
format
,
requiresSecureDecryption
);
getDecoderInfos
(
mediaCodecSelector
,
format
,
requiresSecureDecryption
,
/* requiresTunnelingDecoder= */
false
);
if
(
decoderInfos
.
isEmpty
())
{
if
(
decoderInfos
.
isEmpty
())
{
return
requiresSecureDecryption
return
requiresSecureDecryption
&&
!
mediaCodecSelector
&&
!
getDecoderInfos
(
.
getDecoderInfos
(
mediaCodecSelector
,
format
.
sampleMimeType
,
format
,
/* requiresSecureDecoder= */
false
,
/* requiresSecureDecoder= */
false
,
/* requiresTunnelingDecoder= */
false
)
/* requiresTunnelingDecoder= */
false
)
.
isEmpty
()
.
isEmpty
()
...
@@ -331,8 +335,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -331,8 +335,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
int
tunnelingSupport
=
TUNNELING_NOT_SUPPORTED
;
int
tunnelingSupport
=
TUNNELING_NOT_SUPPORTED
;
if
(
isFormatSupported
)
{
if
(
isFormatSupported
)
{
List
<
MediaCodecInfo
>
tunnelingDecoderInfos
=
List
<
MediaCodecInfo
>
tunnelingDecoderInfos
=
mediaCodecSelector
.
getDecoderInfos
(
getDecoderInfos
(
format
.
sampleMimeType
,
mediaCodecSelector
,
format
,
requiresSecureDecryption
,
requiresSecureDecryption
,
/* requiresTunnelingDecoder= */
true
);
/* requiresTunnelingDecoder= */
true
);
if
(!
tunnelingDecoderInfos
.
isEmpty
())
{
if
(!
tunnelingDecoderInfos
.
isEmpty
())
{
...
@@ -351,8 +356,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -351,8 +356,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
protected
List
<
MediaCodecInfo
>
getDecoderInfos
(
protected
List
<
MediaCodecInfo
>
getDecoderInfos
(
MediaCodecSelector
mediaCodecSelector
,
Format
format
,
boolean
requiresSecureDecoder
)
MediaCodecSelector
mediaCodecSelector
,
Format
format
,
boolean
requiresSecureDecoder
)
throws
DecoderQueryException
{
throws
DecoderQueryException
{
return
getDecoderInfos
(
mediaCodecSelector
,
format
,
requiresSecureDecoder
,
tunneling
);
}
private
static
List
<
MediaCodecInfo
>
getDecoderInfos
(
MediaCodecSelector
mediaCodecSelector
,
Format
format
,
boolean
requiresSecureDecoder
,
boolean
requiresTunnelingDecoder
)
throws
DecoderQueryException
{
List
<
MediaCodecInfo
>
decoderInfos
=
List
<
MediaCodecInfo
>
decoderInfos
=
mediaCodecSelector
.
getDecoderInfos
(
format
.
sampleMimeType
,
requiresSecureDecoder
,
tunneling
);
mediaCodecSelector
.
getDecoderInfos
(
format
.
sampleMimeType
,
requiresSecureDecoder
,
requiresTunnelingDecoder
);
decoderInfos
=
MediaCodecUtil
.
getDecoderInfosSortedByFormatSupport
(
decoderInfos
,
format
);
return
Collections
.
unmodifiableList
(
decoderInfos
);
return
Collections
.
unmodifiableList
(
decoderInfos
);
}
}
...
...
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