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
e21467f6
authored
Sep 09, 2019
by
andrewlewis
Committed by
Oliver Woodman
Sep 10, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Fix Dolby Vision fallback to AVC and HEVC
PiperOrigin-RevId: 267979637
parent
0aba89b6
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
24 additions
and
12 deletions
RELEASENOTES.md
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
library/core/src/test/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtilTest.java
RELEASENOTES.md
View file @
e21467f6
...
@@ -67,6 +67,7 @@
...
@@ -67,6 +67,7 @@
*
Add
`uid`
to
`Timeline.Window`
to uniquely identify window instances.
*
Add
`uid`
to
`Timeline.Window`
to uniquely identify window instances.
*
Fix decoder selection for E-AC3 JOC streams
*
Fix decoder selection for E-AC3 JOC streams
(
[
#6398
](
https://github.com/google/ExoPlayer/issues/6398
)
).
(
[
#6398
](
https://github.com/google/ExoPlayer/issues/6398
)
).
*
Fix Dolby Vision fallback to AVC and HEVC.
### 2.10.4 ###
### 2.10.4 ###
...
...
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java
View file @
e21467f6
...
@@ -81,8 +81,6 @@ public final class MediaCodecUtil {
...
@@ -81,8 +81,6 @@ public final class MediaCodecUtil {
// Dolby Vision.
// Dolby Vision.
private
static
final
Map
<
String
,
Integer
>
DOLBY_VISION_STRING_TO_PROFILE
;
private
static
final
Map
<
String
,
Integer
>
DOLBY_VISION_STRING_TO_PROFILE
;
private
static
final
Map
<
String
,
Integer
>
DOLBY_VISION_STRING_TO_LEVEL
;
private
static
final
Map
<
String
,
Integer
>
DOLBY_VISION_STRING_TO_LEVEL
;
private
static
final
String
CODEC_ID_DVHE
=
"dvhe"
;
private
static
final
String
CODEC_ID_DVH1
=
"dvh1"
;
// AV1.
// AV1.
private
static
final
SparseIntArray
AV1_LEVEL_NUMBER_TO_CONST
;
private
static
final
SparseIntArray
AV1_LEVEL_NUMBER_TO_CONST
;
private
static
final
String
CODEC_ID_AV01
=
"av01"
;
private
static
final
String
CODEC_ID_AV01
=
"av01"
;
...
@@ -245,6 +243,10 @@ public final class MediaCodecUtil {
...
@@ -245,6 +243,10 @@ public final class MediaCodecUtil {
return
null
;
return
null
;
}
}
String
[]
parts
=
format
.
codecs
.
split
(
"\\."
);
String
[]
parts
=
format
.
codecs
.
split
(
"\\."
);
// Dolby Vision can use DV, AVC or HEVC codec IDs, so check the MIME type first.
if
(
MimeTypes
.
VIDEO_DOLBY_VISION
.
equals
(
format
.
sampleMimeType
))
{
return
getDolbyVisionProfileAndLevel
(
format
.
codecs
,
parts
);
}
switch
(
parts
[
0
])
{
switch
(
parts
[
0
])
{
case
CODEC_ID_AVC1:
case
CODEC_ID_AVC1:
case
CODEC_ID_AVC2:
case
CODEC_ID_AVC2:
...
@@ -254,9 +256,6 @@ public final class MediaCodecUtil {
...
@@ -254,9 +256,6 @@ public final class MediaCodecUtil {
case
CODEC_ID_HEV1:
case
CODEC_ID_HEV1:
case
CODEC_ID_HVC1:
case
CODEC_ID_HVC1:
return
getHevcProfileAndLevel
(
format
.
codecs
,
parts
);
return
getHevcProfileAndLevel
(
format
.
codecs
,
parts
);
case
CODEC_ID_DVHE:
case
CODEC_ID_DVH1:
return
getDolbyVisionProfileAndLevel
(
format
.
codecs
,
parts
);
case
CODEC_ID_AV01:
case
CODEC_ID_AV01:
return
getAv1ProfileAndLevel
(
format
.
codecs
,
parts
,
format
.
colorInfo
);
return
getAv1ProfileAndLevel
(
format
.
codecs
,
parts
,
format
.
colorInfo
);
case
CODEC_ID_MP4A:
case
CODEC_ID_MP4A:
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
View file @
e21467f6
...
@@ -21,6 +21,7 @@ import android.content.Context;
...
@@ -21,6 +21,7 @@ import android.content.Context;
import
android.graphics.Point
;
import
android.graphics.Point
;
import
android.media.MediaCodec
;
import
android.media.MediaCodec
;
import
android.media.MediaCodecInfo.CodecCapabilities
;
import
android.media.MediaCodecInfo.CodecCapabilities
;
import
android.media.MediaCodecInfo.CodecProfileLevel
;
import
android.media.MediaCrypto
;
import
android.media.MediaCrypto
;
import
android.media.MediaFormat
;
import
android.media.MediaFormat
;
import
android.os.Bundle
;
import
android.os.Bundle
;
...
@@ -393,15 +394,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -393,15 +394,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
format
.
sampleMimeType
,
requiresSecureDecoder
,
requiresTunnelingDecoder
);
format
.
sampleMimeType
,
requiresSecureDecoder
,
requiresTunnelingDecoder
);
decoderInfos
=
MediaCodecUtil
.
getDecoderInfosSortedByFormatSupport
(
decoderInfos
,
format
);
decoderInfos
=
MediaCodecUtil
.
getDecoderInfosSortedByFormatSupport
(
decoderInfos
,
format
);
if
(
MimeTypes
.
VIDEO_DOLBY_VISION
.
equals
(
format
.
sampleMimeType
))
{
if
(
MimeTypes
.
VIDEO_DOLBY_VISION
.
equals
(
format
.
sampleMimeType
))
{
// Fallback to primary decoders for H.265/HEVC or H.264/AVC for the relevant DV profiles.
// Fall back to H.264/AVC or H.265/HEVC for the relevant DV profiles.
@Nullable
Pair
<
Integer
,
Integer
>
codecProfileAndLevel
=
MediaCodecUtil
.
getCodecProfileAndLevel
(
format
);
Pair
<
Integer
,
Integer
>
codecProfileAndLevel
=
MediaCodecUtil
.
getCodecProfileAndLevel
(
format
);
if
(
codecProfileAndLevel
!=
null
)
{
if
(
codecProfileAndLevel
!=
null
)
{
int
profile
=
codecProfileAndLevel
.
first
;
int
profile
=
codecProfileAndLevel
.
first
;
if
(
profile
==
4
||
profile
==
8
)
{
if
(
profile
==
CodecProfileLevel
.
DolbyVisionProfileDvheDtr
||
profile
==
CodecProfileLevel
.
DolbyVisionProfileDvheSt
)
{
decoderInfos
.
addAll
(
decoderInfos
.
addAll
(
mediaCodecSelector
.
getDecoderInfos
(
mediaCodecSelector
.
getDecoderInfos
(
MimeTypes
.
VIDEO_H265
,
requiresSecureDecoder
,
requiresTunnelingDecoder
));
MimeTypes
.
VIDEO_H265
,
requiresSecureDecoder
,
requiresTunnelingDecoder
));
}
else
if
(
profile
==
9
)
{
}
else
if
(
profile
==
CodecProfileLevel
.
DolbyVisionProfileDvavSe
)
{
decoderInfos
.
addAll
(
decoderInfos
.
addAll
(
mediaCodecSelector
.
getDecoderInfos
(
mediaCodecSelector
.
getDecoderInfos
(
MimeTypes
.
VIDEO_H264
,
requiresSecureDecoder
,
requiresTunnelingDecoder
));
MimeTypes
.
VIDEO_H264
,
requiresSecureDecoder
,
requiresTunnelingDecoder
));
...
...
library/core/src/test/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtilTest.java
View file @
e21467f6
...
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
...
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import
android.media.MediaCodecInfo
;
import
android.media.MediaCodecInfo
;
import
android.util.Pair
;
import
android.util.Pair
;
import
androidx.annotation.Nullable
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Format
;
...
@@ -34,6 +35,7 @@ public final class MediaCodecUtilTest {
...
@@ -34,6 +35,7 @@ public final class MediaCodecUtilTest {
@Test
@Test
public
void
getCodecProfileAndLevel_handlesVp9Profile1CodecString
()
{
public
void
getCodecProfileAndLevel_handlesVp9Profile1CodecString
()
{
assertCodecProfileAndLevelForCodecsString
(
assertCodecProfileAndLevelForCodecsString
(
MimeTypes
.
VIDEO_VP9
,
"vp09.01.51"
,
"vp09.01.51"
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Profile1
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Profile1
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Level51
);
MediaCodecInfo
.
CodecProfileLevel
.
VP9Level51
);
...
@@ -42,6 +44,7 @@ public final class MediaCodecUtilTest {
...
@@ -42,6 +44,7 @@ public final class MediaCodecUtilTest {
@Test
@Test
public
void
getCodecProfileAndLevel_handlesVp9Profile2CodecString
()
{
public
void
getCodecProfileAndLevel_handlesVp9Profile2CodecString
()
{
assertCodecProfileAndLevelForCodecsString
(
assertCodecProfileAndLevelForCodecsString
(
MimeTypes
.
VIDEO_VP9
,
"vp09.02.10"
,
"vp09.02.10"
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Profile2
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Profile2
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Level1
);
MediaCodecInfo
.
CodecProfileLevel
.
VP9Level1
);
...
@@ -51,6 +54,7 @@ public final class MediaCodecUtilTest {
...
@@ -51,6 +54,7 @@ public final class MediaCodecUtilTest {
public
void
getCodecProfileAndLevel_handlesFullVp9CodecString
()
{
public
void
getCodecProfileAndLevel_handlesFullVp9CodecString
()
{
// Example from https://www.webmproject.org/vp9/mp4/#codecs-parameter-string.
// Example from https://www.webmproject.org/vp9/mp4/#codecs-parameter-string.
assertCodecProfileAndLevelForCodecsString
(
assertCodecProfileAndLevelForCodecsString
(
MimeTypes
.
VIDEO_VP9
,
"vp09.02.10.10.01.09.16.09.01"
,
"vp09.02.10.10.01.09.16.09.01"
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Profile2
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Profile2
,
MediaCodecInfo
.
CodecProfileLevel
.
VP9Level1
);
MediaCodecInfo
.
CodecProfileLevel
.
VP9Level1
);
...
@@ -59,6 +63,7 @@ public final class MediaCodecUtilTest {
...
@@ -59,6 +63,7 @@ public final class MediaCodecUtilTest {
@Test
@Test
public
void
getCodecProfileAndLevel_handlesDolbyVisionCodecString
()
{
public
void
getCodecProfileAndLevel_handlesDolbyVisionCodecString
()
{
assertCodecProfileAndLevelForCodecsString
(
assertCodecProfileAndLevelForCodecsString
(
MimeTypes
.
VIDEO_DOLBY_VISION
,
"dvh1.05.05"
,
"dvh1.05.05"
,
MediaCodecInfo
.
CodecProfileLevel
.
DolbyVisionProfileDvheStn
,
MediaCodecInfo
.
CodecProfileLevel
.
DolbyVisionProfileDvheStn
,
MediaCodecInfo
.
CodecProfileLevel
.
DolbyVisionLevelFhd60
);
MediaCodecInfo
.
CodecProfileLevel
.
DolbyVisionLevelFhd60
);
...
@@ -67,6 +72,7 @@ public final class MediaCodecUtilTest {
...
@@ -67,6 +72,7 @@ public final class MediaCodecUtilTest {
@Test
@Test
public
void
getCodecProfileAndLevel_handlesAv1ProfileMain8CodecString
()
{
public
void
getCodecProfileAndLevel_handlesAv1ProfileMain8CodecString
()
{
assertCodecProfileAndLevelForCodecsString
(
assertCodecProfileAndLevelForCodecsString
(
MimeTypes
.
VIDEO_AV1
,
"av01.0.10M.08"
,
"av01.0.10M.08"
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1ProfileMain8
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1ProfileMain8
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1Level42
);
MediaCodecInfo
.
CodecProfileLevel
.
AV1Level42
);
...
@@ -75,6 +81,7 @@ public final class MediaCodecUtilTest {
...
@@ -75,6 +81,7 @@ public final class MediaCodecUtilTest {
@Test
@Test
public
void
getCodecProfileAndLevel_handlesAv1ProfileMain10CodecString
()
{
public
void
getCodecProfileAndLevel_handlesAv1ProfileMain10CodecString
()
{
assertCodecProfileAndLevelForCodecsString
(
assertCodecProfileAndLevelForCodecsString
(
MimeTypes
.
VIDEO_AV1
,
"av01.0.20M.10"
,
"av01.0.20M.10"
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1ProfileMain10
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1ProfileMain10
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1Level7
);
MediaCodecInfo
.
CodecProfileLevel
.
AV1Level7
);
...
@@ -91,7 +98,7 @@ public final class MediaCodecUtilTest {
...
@@ -91,7 +98,7 @@ public final class MediaCodecUtilTest {
Format
format
=
Format
format
=
Format
.
createVideoSampleFormat
(
Format
.
createVideoSampleFormat
(
/* id= */
null
,
/* id= */
null
,
/* sampleMimeType= */
MimeTypes
.
VIDEO_UNKNOWN
,
MimeTypes
.
VIDEO_AV1
,
/* codecs= */
"av01.0.21M.10"
,
/* codecs= */
"av01.0.21M.10"
,
/* bitrate= */
Format
.
NO_VALUE
,
/* bitrate= */
Format
.
NO_VALUE
,
/* maxInputSize= */
Format
.
NO_VALUE
,
/* maxInputSize= */
Format
.
NO_VALUE
,
...
@@ -122,7 +129,7 @@ public final class MediaCodecUtilTest {
...
@@ -122,7 +129,7 @@ public final class MediaCodecUtilTest {
Format
format
=
Format
format
=
Format
.
createVideoSampleFormat
(
Format
.
createVideoSampleFormat
(
/* id= */
null
,
/* id= */
null
,
/* sampleMimeType= */
MimeTypes
.
VIDEO_UNKNOWN
,
MimeTypes
.
VIDEO_AV1
,
/* codecs= */
"av01.0.21M.10"
,
/* codecs= */
"av01.0.21M.10"
,
/* bitrate= */
Format
.
NO_VALUE
,
/* bitrate= */
Format
.
NO_VALUE
,
/* maxInputSize= */
Format
.
NO_VALUE
,
/* maxInputSize= */
Format
.
NO_VALUE
,
...
@@ -146,6 +153,7 @@ public final class MediaCodecUtilTest {
...
@@ -146,6 +153,7 @@ public final class MediaCodecUtilTest {
public
void
getCodecProfileAndLevel_handlesFullAv1CodecString
()
{
public
void
getCodecProfileAndLevel_handlesFullAv1CodecString
()
{
// Example from https://aomediacodec.github.io/av1-isobmff/#codecsparam.
// Example from https://aomediacodec.github.io/av1-isobmff/#codecsparam.
assertCodecProfileAndLevelForCodecsString
(
assertCodecProfileAndLevelForCodecsString
(
MimeTypes
.
VIDEO_AV1
,
"av01.0.04M.10.0.112.09.16.09.0"
,
"av01.0.04M.10.0.112.09.16.09.0"
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1ProfileMain10
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1ProfileMain10
,
MediaCodecInfo
.
CodecProfileLevel
.
AV1Level3
);
MediaCodecInfo
.
CodecProfileLevel
.
AV1Level3
);
...
@@ -186,11 +194,11 @@ public final class MediaCodecUtilTest {
...
@@ -186,11 +194,11 @@ public final class MediaCodecUtilTest {
}
}
private
static
void
assertCodecProfileAndLevelForCodecsString
(
private
static
void
assertCodecProfileAndLevelForCodecsString
(
String
codecs
,
int
profile
,
int
level
)
{
String
mimeType
,
String
codecs
,
int
profile
,
int
level
)
{
Format
format
=
Format
format
=
Format
.
createVideoSampleFormat
(
Format
.
createVideoSampleFormat
(
/* id= */
null
,
/* id= */
null
,
/* sampleMimeType= */
MimeTypes
.
VIDEO_UNKNOWN
,
mimeType
,
/* codecs= */
codecs
,
/* codecs= */
codecs
,
/* bitrate= */
Format
.
NO_VALUE
,
/* bitrate= */
Format
.
NO_VALUE
,
/* maxInputSize= */
Format
.
NO_VALUE
,
/* maxInputSize= */
Format
.
NO_VALUE
,
...
@@ -203,6 +211,7 @@ public final class MediaCodecUtilTest {
...
@@ -203,6 +211,7 @@ public final class MediaCodecUtilTest {
}
}
private
static
void
assertCodecProfileAndLevelForFormat
(
Format
format
,
int
profile
,
int
level
)
{
private
static
void
assertCodecProfileAndLevelForFormat
(
Format
format
,
int
profile
,
int
level
)
{
@Nullable
Pair
<
Integer
,
Integer
>
codecProfileAndLevel
=
MediaCodecUtil
.
getCodecProfileAndLevel
(
format
);
Pair
<
Integer
,
Integer
>
codecProfileAndLevel
=
MediaCodecUtil
.
getCodecProfileAndLevel
(
format
);
assertThat
(
codecProfileAndLevel
).
isNotNull
();
assertThat
(
codecProfileAndLevel
).
isNotNull
();
assertThat
(
codecProfileAndLevel
.
first
).
isEqualTo
(
profile
);
assertThat
(
codecProfileAndLevel
.
first
).
isEqualTo
(
profile
);
...
...
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