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
61a20d5f
authored
Apr 06, 2022
by
claincly
Committed by
Ian Baker
Apr 07, 2022
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add test to query device capabilities.
PiperOrigin-RevId: 439861685
parent
b5eba24e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
306 additions
and
40 deletions
library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java
library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/EncoderCapabilityAnalysisTest.java
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java
library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java
View file @
61a20d5f
...
@@ -21,6 +21,7 @@ import android.content.Context;
...
@@ -21,6 +21,7 @@ import android.content.Context;
import
android.os.Build
;
import
android.os.Build
;
import
com.google.android.exoplayer2.Format
;
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.Util
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileWriter
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.IOException
;
...
@@ -126,14 +127,16 @@ public final class AndroidTestUtil {
...
@@ -126,14 +127,16 @@ public final class AndroidTestUtil {
* @param testId A unique identifier for the transformer test run.
* @param testId A unique identifier for the transformer test run.
* @param testJson A {@link JSONObject} containing a summary of the test run.
* @param testJson A {@link JSONObject} containing a summary of the test run.
*/
*/
/* package */
static
void
writeTestSummaryToFile
(
public
static
void
writeTestSummaryToFile
(
Context
context
,
String
testId
,
JSONObject
testJson
)
Context
context
,
String
testId
,
JSONObject
testJson
)
throws
IOException
,
JSONException
{
throws
IOException
,
JSONException
{
testJson
.
put
(
"testId"
,
testId
).
put
(
"device"
,
getDeviceDetailsAsJsonObject
());
testJson
.
put
(
"testId"
,
testId
).
put
(
"device"
,
getDeviceDetailsAsJsonObject
());
String
analysisContents
=
testJson
.
toString
(
/* indentSpaces= */
2
);
String
analysisContents
=
testJson
.
toString
(
/* indentSpaces= */
2
);
// Log contents as well as writing to file, for easier visibility on individual device testing.
// Log contents as well as writing to file, for easier visibility on individual device testing.
Log
.
i
(
testId
,
analysisContents
);
for
(
String
line
:
Util
.
split
(
analysisContents
,
"\n"
))
{
Log
.
i
(
testId
,
line
);
}
File
analysisFile
=
createExternalCacheFile
(
context
,
/* fileName= */
testId
+
"-result.txt"
);
File
analysisFile
=
createExternalCacheFile
(
context
,
/* fileName= */
testId
+
"-result.txt"
);
try
(
FileWriter
fileWriter
=
new
FileWriter
(
analysisFile
))
{
try
(
FileWriter
fileWriter
=
new
FileWriter
(
analysisFile
))
{
...
...
library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/EncoderCapabilityAnalysisTest.java
0 → 100644
View file @
61a20d5f
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
transformer
.
mh
.
analysis
;
import
static
android
.
media
.
MediaCodecInfo
.
EncoderCapabilities
.
BITRATE_MODE_CBR
;
import
static
android
.
media
.
MediaCodecInfo
.
EncoderCapabilities
.
BITRATE_MODE_CBR_FD
;
import
static
android
.
media
.
MediaCodecInfo
.
EncoderCapabilities
.
BITRATE_MODE_CQ
;
import
static
android
.
media
.
MediaCodecInfo
.
EncoderCapabilities
.
BITRATE_MODE_VBR
;
import
android.media.MediaCodecInfo
;
import
android.util.Pair
;
import
android.util.Range
;
import
android.util.Size
;
import
androidx.annotation.Nullable
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.transformer.AndroidTestUtil
;
import
com.google.android.exoplayer2.transformer.EncoderUtil
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.ImmutableSet
;
import
java.util.ArrayList
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
org.json.JSONObject
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
/** An analysis test to log encoder capabilities on a device. */
@RunWith
(
AndroidJUnit4
.
class
)
public
class
EncoderCapabilityAnalysisTest
{
// TODO(b/228167357): Remove after bumping compileApiVersion to 33.
/** Re-definition of {@code MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing} in API33. */
private
static
final
String
FEATURE_HdrEditing
=
"hdr-editing"
;
/**
* Re-definition of {@code MediaCodecInfo.CodecCapabilities.FEATURE_EncodingStatistics} in API33.
*/
private
static
final
String
FEATURE_EncodingStatistics
=
"encoding-statistics"
;
@Test
public
void
logEncoderCapabilities
()
throws
Exception
{
ImmutableSet
<
String
>
supportedVideoMimeTypes
=
EncoderUtil
.
getSupportedVideoMimeTypes
();
// Map from MIME type to a list of maps from capability name to value.
LinkedHashMap
<
String
,
List
<
Map
<
String
,
Object
>>>
mimeTypeToEncoderInfo
=
new
LinkedHashMap
<>();
for
(
String
mimeType
:
supportedVideoMimeTypes
)
{
ImmutableList
<
MediaCodecInfo
>
encoderInfos
=
EncoderUtil
.
getSupportedEncoders
(
mimeType
);
ArrayList
<
Map
<
String
,
Object
>>
encoderCapabilitiesForMimeType
=
new
ArrayList
<>();
for
(
MediaCodecInfo
encoderInfo
:
encoderInfos
)
{
LinkedHashMap
<
String
,
Object
>
capabilities
=
new
LinkedHashMap
<>();
capabilities
.
put
(
"encoder_name"
,
encoderInfo
.
getName
());
capabilities
.
put
(
"is_software_encoder"
,
!
EncoderUtil
.
isHardwareAccelerated
(
encoderInfo
,
mimeType
));
// Bitrate modes.
capabilities
.
put
(
"supports_vbr"
,
EncoderUtil
.
isBitrateModeSupported
(
encoderInfo
,
mimeType
,
BITRATE_MODE_VBR
));
capabilities
.
put
(
"supports_cbr"
,
EncoderUtil
.
isBitrateModeSupported
(
encoderInfo
,
mimeType
,
BITRATE_MODE_CBR
));
capabilities
.
put
(
"supports_cq"
,
EncoderUtil
.
isBitrateModeSupported
(
encoderInfo
,
mimeType
,
BITRATE_MODE_CQ
));
capabilities
.
put
(
"supports_cbr_fd"
,
EncoderUtil
.
isBitrateModeSupported
(
encoderInfo
,
mimeType
,
BITRATE_MODE_CBR_FD
));
capabilities
.
put
(
"supported_bitrate_range"
,
rangeToString
(
EncoderUtil
.
getSupportedBitrateRange
(
encoderInfo
,
mimeType
)));
// Resolution support.
Pair
<
Range
<
Integer
>,
Range
<
Integer
>>
supportedResolutionRanges
=
EncoderUtil
.
getSupportedResolutionRanges
(
encoderInfo
,
mimeType
);
capabilities
.
put
(
"supported_widths_range"
,
rangeToString
(
supportedResolutionRanges
.
first
));
capabilities
.
put
(
"supported_heights_range"
,
rangeToString
(
supportedResolutionRanges
.
second
));
checkResolutionSupport
(
encoderInfo
,
mimeType
,
capabilities
,
/* width= */
1280
,
/* height= */
720
);
checkResolutionSupport
(
encoderInfo
,
mimeType
,
capabilities
,
/* width= */
1920
,
/* height= */
1080
);
checkResolutionSupport
(
encoderInfo
,
mimeType
,
capabilities
,
/* width= */
2560
,
/* height= */
1440
);
checkResolutionSupport
(
encoderInfo
,
mimeType
,
capabilities
,
/* width= */
3840
,
/* height= */
2160
);
checkProfileLevelSupport
(
encoderInfo
,
mimeType
,
capabilities
);
capabilities
.
put
(
"supported_color_profiles"
,
EncoderUtil
.
getSupportedColorFormats
(
encoderInfo
,
mimeType
));
capabilities
.
put
(
"max_supported_instances"
,
Util
.
SDK_INT
>=
23
?
EncoderUtil
.
getMaxSupportedInstances
(
encoderInfo
,
mimeType
)
:
-
1
);
capabilities
.
put
(
"supports_qp_bounds"
,
Util
.
SDK_INT
>=
31
&&
EncoderUtil
.
isFeatureSupported
(
encoderInfo
,
mimeType
,
MediaCodecInfo
.
CodecCapabilities
.
FEATURE_QpBounds
));
capabilities
.
put
(
"supports_hdr_editing"
,
Util
.
SDK_INT
>=
33
&&
EncoderUtil
.
isFeatureSupported
(
encoderInfo
,
mimeType
,
FEATURE_HdrEditing
));
capabilities
.
put
(
"supports_encoding_statistics"
,
Util
.
SDK_INT
>=
33
&&
EncoderUtil
.
isFeatureSupported
(
encoderInfo
,
mimeType
,
FEATURE_EncodingStatistics
));
encoderCapabilitiesForMimeType
.
add
(
capabilities
);
}
mimeTypeToEncoderInfo
.
put
(
mimeType
,
encoderCapabilitiesForMimeType
);
}
JSONObject
resultJson
=
new
JSONObject
();
resultJson
.
put
(
"encoder_capabilities"
,
JSONObject
.
wrap
(
mimeTypeToEncoderInfo
));
AndroidTestUtil
.
writeTestSummaryToFile
(
ApplicationProvider
.
getApplicationContext
(),
/* testId= */
"encoderCapabilityAnalysisTest"
,
resultJson
);
}
private
static
void
checkResolutionSupport
(
MediaCodecInfo
encoder
,
String
mimeType
,
Map
<
String
,
Object
>
capabilities
,
int
width
,
int
height
)
{
Range
<
Integer
>
supportedWidths
=
EncoderUtil
.
getSupportedResolutionRanges
(
encoder
,
mimeType
).
first
;
@Nullable
Range
<
Integer
>
supportedHeights
=
null
;
if
(
supportedWidths
.
contains
(
width
))
{
supportedHeights
=
EncoderUtil
.
getSupportedHeights
(
encoder
,
mimeType
,
width
);
}
capabilities
.
put
(
Util
.
formatInvariant
(
"supported_heights_for_%d"
,
width
),
rangeToString
(
supportedHeights
));
@Nullable
Size
supportedResolution
=
EncoderUtil
.
getSupportedResolution
(
encoder
,
mimeType
,
width
,
height
);
if
(
supportedResolution
==
null
)
{
supportedResolution
=
new
Size
(
/* width= */
0
,
/* height= */
0
);
}
capabilities
.
put
(
Util
.
formatInvariant
(
"supports_%dx%d"
,
width
,
height
),
(
supportedResolution
.
getWidth
()
==
width
&&
supportedResolution
.
getHeight
()
==
height
));
capabilities
.
put
(
Util
.
formatInvariant
(
"fallback_%dx%d"
,
width
,
height
),
sizeToString
(
supportedResolution
));
}
private
static
void
checkProfileLevelSupport
(
MediaCodecInfo
encoder
,
String
mimeType
,
Map
<
String
,
Object
>
capabilities
)
{
LinkedHashMap
<
String
,
String
>
profileToHighestSupportedLevel
=
new
LinkedHashMap
<>();
ImmutableSet
<
Integer
>
supportedEncodingProfiles
=
EncoderUtil
.
findSupportedEncodingProfiles
(
encoder
,
mimeType
);
for
(
int
profile
:
supportedEncodingProfiles
)
{
profileToHighestSupportedLevel
.
put
(
String
.
valueOf
(
profile
),
String
.
valueOf
(
EncoderUtil
.
findHighestSupportedEncodingLevel
(
encoder
,
mimeType
,
profile
)));
}
capabilities
.
put
(
"supported_profile_levels"
,
profileToHighestSupportedLevel
);
}
private
static
String
rangeToString
(
@Nullable
Range
<
Integer
>
range
)
{
return
range
==
null
?
"0-0"
:
Util
.
formatInvariant
(
"%d-%d"
,
range
.
getLower
(),
range
.
getUpper
());
}
private
static
String
sizeToString
(
@Nullable
Size
size
)
{
return
size
==
null
?
"0x0"
:
Util
.
formatInvariant
(
"%dx%d"
,
size
.
getWidth
(),
size
.
getHeight
());
}
}
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java
View file @
61a20d5f
...
@@ -267,7 +267,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
...
@@ -267,7 +267,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
MediaCodecInfo
pickedEncoder
=
filteredEncoders
.
get
(
0
);
MediaCodecInfo
pickedEncoder
=
filteredEncoders
.
get
(
0
);
int
closestSupportedBitrate
=
int
closestSupportedBitrate
=
EncoderUtil
.
get
ClosestSupportedBitrate
(
pickedEncoder
,
mimeType
,
requestedBitrate
);
EncoderUtil
.
get
SupportedBitrateRange
(
pickedEncoder
,
mimeType
).
clamp
(
requestedBitrate
);
VideoEncoderSettings
.
Builder
supportedEncodingSettingBuilder
=
VideoEncoderSettings
.
Builder
supportedEncodingSettingBuilder
=
videoEncoderSettings
.
buildUpon
().
setBitrate
(
closestSupportedBitrate
);
videoEncoderSettings
.
buildUpon
().
setBitrate
(
closestSupportedBitrate
);
...
@@ -320,7 +320,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
...
@@ -320,7 +320,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
encoders
,
encoders
,
/* cost= */
(
encoderInfo
)
->
{
/* cost= */
(
encoderInfo
)
->
{
int
achievableBitrate
=
int
achievableBitrate
=
EncoderUtil
.
get
ClosestSupportedBitrate
(
encoderInfo
,
mimeType
,
requestedBitrate
);
EncoderUtil
.
get
SupportedBitrateRange
(
encoderInfo
,
mimeType
).
clamp
(
requestedBitrate
);
return
abs
(
achievableBitrate
-
requestedBitrate
);
return
abs
(
achievableBitrate
-
requestedBitrate
);
},
},
/* filterName= */
"bitrate"
);
/* filterName= */
"bitrate"
);
...
...
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/EncoderUtil.java
View file @
61a20d5f
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
transformer
;
package
com
.
google
.
android
.
exoplayer2
.
transformer
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkNotNull
;
import
static
java
.
lang
.
Math
.
max
;
import
static
java
.
lang
.
Math
.
max
;
import
static
java
.
lang
.
Math
.
round
;
import
static
java
.
lang
.
Math
.
round
;
...
@@ -23,6 +24,8 @@ import android.media.MediaCodec;
...
@@ -23,6 +24,8 @@ import android.media.MediaCodec;
import
android.media.MediaCodecInfo
;
import
android.media.MediaCodecInfo
;
import
android.media.MediaCodecList
;
import
android.media.MediaCodecList
;
import
android.media.MediaFormat
;
import
android.media.MediaFormat
;
import
android.util.Pair
;
import
android.util.Range
;
import
android.util.Size
;
import
android.util.Size
;
import
androidx.annotation.DoNotInline
;
import
androidx.annotation.DoNotInline
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
...
@@ -32,9 +35,12 @@ import com.google.android.exoplayer2.util.MediaFormatUtil;
...
@@ -32,9 +35,12 @@ import com.google.android.exoplayer2.util.MediaFormatUtil;
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
com.google.common.base.Ascii
;
import
com.google.common.base.Ascii
;
import
com.google.common.base.Supplier
;
import
com.google.common.base.Suppliers
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.ImmutableList
;
import
java.util.ArrayList
;
import
com.google.common.collect.ImmutableListMultimap
;
import
java.util.List
;
import
com.google.common.collect.ImmutableSet
;
import
com.google.common.primitives.Ints
;
/** Utility methods for {@link MediaCodec} encoders. */
/** Utility methods for {@link MediaCodec} encoders. */
public
final
class
EncoderUtil
{
public
final
class
EncoderUtil
{
...
@@ -42,26 +48,47 @@ public final class EncoderUtil {
...
@@ -42,26 +48,47 @@ public final class EncoderUtil {
/** A value to indicate the encoding level is not set. */
/** A value to indicate the encoding level is not set. */
public
static
final
int
LEVEL_UNSET
=
Format
.
NO_VALUE
;
public
static
final
int
LEVEL_UNSET
=
Format
.
NO_VALUE
;
private
static
final
List
<
MediaCodecInfo
>
encoders
=
new
ArrayList
<>();
private
static
final
Supplier
<
ImmutableListMultimap
<
String
,
MediaCodecInfo
>>
MIME_TYPE_TO_ENCODERS
=
Suppliers
.
memoize
(
EncoderUtil:
:
populateEncoderInfos
);
/**
/**
* Returns a list of {@linkplain MediaCodecInfo encoders} that support the given {@code mimeType},
* Returns a list of {@linkplain MediaCodecInfo encoders} that support the given {@code mimeType},
* or an empty list if there is none.
* or an empty list if there is none.
*/
*/
public
static
ImmutableList
<
MediaCodecInfo
>
getSupportedEncoders
(
String
mimeType
)
{
public
static
ImmutableList
<
MediaCodecInfo
>
getSupportedEncoders
(
String
mimeType
)
{
maybePopulateEncoderInfos
();
return
checkNotNull
(
MIME_TYPE_TO_ENCODERS
.
get
()).
get
(
Ascii
.
toLowerCase
(
mimeType
));
}
ImmutableList
.
Builder
<
MediaCodecInfo
>
availableEncoders
=
new
ImmutableList
.
Builder
<>();
for
(
int
i
=
0
;
i
<
encoders
.
size
();
i
++)
{
/** Returns a list of video {@linkplain MimeTypes MIME types} that can be encoded. */
MediaCodecInfo
encoderInfo
=
encoders
.
get
(
i
);
public
static
ImmutableSet
<
String
>
getSupportedVideoMimeTypes
()
{
String
[]
supportedMimeTypes
=
encoderInfo
.
getSupportedTypes
();
return
checkNotNull
(
MIME_TYPE_TO_ENCODERS
.
get
()).
keySet
();
for
(
String
supportedMimeType
:
supportedMimeTypes
)
{
}
if
(
Ascii
.
equalsIgnoreCase
(
supportedMimeType
,
mimeType
))
{
availableEncoders
.
add
(
encoderInfo
);
/**
}
* Returns a {@link Range} of supported heights for the given {@link MediaCodecInfo encoder},
}
* {@linkplain MimeTypes MIME type} and {@code width}.
}
*
return
availableEncoders
.
build
();
* @throws IllegalArgumentException When the width is not in the range of {@linkplain
* #getSupportedResolutionRanges supported widths}.
*/
public
static
Range
<
Integer
>
getSupportedHeights
(
MediaCodecInfo
encoderInfo
,
String
mimeType
,
int
width
)
{
return
encoderInfo
.
getCapabilitiesForType
(
mimeType
)
.
getVideoCapabilities
()
.
getSupportedHeightsFor
(
width
);
}
/**
* Returns a {@link Pair} of supported width and height {@link Range ranges} for the given {@link
* MediaCodecInfo encoder} and {@linkplain MimeTypes MIME type}.
*/
public
static
Pair
<
Range
<
Integer
>,
Range
<
Integer
>>
getSupportedResolutionRanges
(
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
MediaCodecInfo
.
VideoCapabilities
videoCapabilities
=
encoderInfo
.
getCapabilitiesForType
(
mimeType
).
getVideoCapabilities
();
return
Pair
.
create
(
videoCapabilities
.
getSupportedWidths
(),
videoCapabilities
.
getSupportedHeights
());
}
}
/**
/**
...
@@ -131,6 +158,22 @@ public final class EncoderUtil {
...
@@ -131,6 +158,22 @@ public final class EncoderUtil {
}
}
/**
/**
* Returns a {@link ImmutableSet set} of supported {@linkplain MediaCodecInfo.CodecProfileLevel
* encoding profiles} for the given {@linkplain MediaCodecInfo encoder} and {@linkplain MimeTypes
* MIME type}.
*/
public
static
ImmutableSet
<
Integer
>
findSupportedEncodingProfiles
(
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
MediaCodecInfo
.
CodecProfileLevel
[]
profileLevels
=
encoderInfo
.
getCapabilitiesForType
(
mimeType
).
profileLevels
;
ImmutableSet
.
Builder
<
Integer
>
supportedProfilesBuilder
=
new
ImmutableSet
.
Builder
<>();
for
(
MediaCodecInfo
.
CodecProfileLevel
profileLevel
:
profileLevels
)
{
supportedProfilesBuilder
.
add
(
profileLevel
.
profile
);
}
return
supportedProfilesBuilder
.
build
();
}
/**
* Finds the highest supported encoding level given a profile.
* Finds the highest supported encoding level given a profile.
*
*
* @param encoderInfo The {@link MediaCodecInfo encoderInfo}.
* @param encoderInfo The {@link MediaCodecInfo encoderInfo}.
...
@@ -180,17 +223,10 @@ public final class EncoderUtil {
...
@@ -180,17 +223,10 @@ public final class EncoderUtil {
return
mediaCodecName
;
return
mediaCodecName
;
}
}
/**
/** Returns the range of supported bitrates for the given {@linkplain MimeTypes MIME type}. */
* Finds the {@linkplain MediaCodecInfo encoder}'s closest supported bitrate from the given
public
static
Range
<
Integer
>
getSupportedBitrateRange
(
* bitrate.
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
*/
return
encoderInfo
.
getCapabilitiesForType
(
mimeType
).
getVideoCapabilities
().
getBitrateRange
();
public
static
int
getClosestSupportedBitrate
(
MediaCodecInfo
encoderInfo
,
String
mimeType
,
int
bitrate
)
{
return
encoderInfo
.
getCapabilitiesForType
(
mimeType
)
.
getVideoCapabilities
()
.
getBitrateRange
()
.
clamp
(
bitrate
);
}
}
/** Returns whether the bitrate mode is supported by the encoder. */
/** Returns whether the bitrate mode is supported by the encoder. */
...
@@ -202,6 +238,17 @@ public final class EncoderUtil {
...
@@ -202,6 +238,17 @@ public final class EncoderUtil {
.
isBitrateModeSupported
(
bitrateMode
);
.
isBitrateModeSupported
(
bitrateMode
);
}
}
/**
* Returns a {@link ImmutableList list} of supported {@linkplain
* MediaCodecInfo.CodecCapabilities#colorFormats color formats} for the given {@linkplain
* MediaCodecInfo encoder} and {@linkplain MimeTypes MIME type}.
*/
public
static
ImmutableList
<
Integer
>
getSupportedColorFormats
(
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
return
ImmutableList
.
copyOf
(
Ints
.
asList
(
encoderInfo
.
getCapabilitiesForType
(
mimeType
).
colorFormats
));
}
/** Checks if a {@linkplain MediaCodecInfo codec} is hardware-accelerated. */
/** Checks if a {@linkplain MediaCodecInfo codec} is hardware-accelerated. */
public
static
boolean
isHardwareAccelerated
(
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
public
static
boolean
isHardwareAccelerated
(
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
// TODO(b/214964116): Merge into MediaCodecUtil.
// TODO(b/214964116): Merge into MediaCodecUtil.
...
@@ -213,6 +260,18 @@ public final class EncoderUtil {
...
@@ -213,6 +260,18 @@ public final class EncoderUtil {
return
!
isSoftwareOnly
(
encoderInfo
,
mimeType
);
return
!
isSoftwareOnly
(
encoderInfo
,
mimeType
);
}
}
/** Returns whether a given feature is supported. */
public
static
boolean
isFeatureSupported
(
MediaCodecInfo
encoderInfo
,
String
mimeType
,
String
featureName
)
{
return
encoderInfo
.
getCapabilitiesForType
(
mimeType
).
isFeatureSupported
(
featureName
);
}
/** Returns the number of max number of the supported concurrent codec instances. */
@RequiresApi
(
23
)
public
static
int
getMaxSupportedInstances
(
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
return
encoderInfo
.
getCapabilitiesForType
(
mimeType
).
getMaxSupportedInstances
();
}
private
static
boolean
isSoftwareOnly
(
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
private
static
boolean
isSoftwareOnly
(
MediaCodecInfo
encoderInfo
,
String
mimeType
)
{
if
(
Util
.
SDK_INT
>=
29
)
{
if
(
Util
.
SDK_INT
>=
29
)
{
return
Api29
.
isSoftwareOnly
(
encoderInfo
);
return
Api29
.
isSoftwareOnly
(
encoderInfo
);
...
@@ -256,18 +315,25 @@ public final class EncoderUtil {
...
@@ -256,18 +315,25 @@ public final class EncoderUtil {
:
alignment
*
Math
.
round
((
float
)
size
/
alignment
);
:
alignment
*
Math
.
round
((
float
)
size
/
alignment
);
}
}
private
static
synchronized
void
maybePopulateEncoderInfos
()
{
private
static
ImmutableListMultimap
<
String
,
MediaCodecInfo
>
populateEncoderInfos
()
{
if
(
encoders
.
isEmpty
())
{
ImmutableListMultimap
.
Builder
<
String
,
MediaCodecInfo
>
encoderInfosBuilder
=
MediaCodecList
mediaCodecList
=
new
MediaCodecList
(
MediaCodecList
.
ALL_CODECS
);
new
ImmutableListMultimap
.
Builder
<>();
MediaCodecInfo
[]
allCodecInfos
=
mediaCodecList
.
getCodecInfos
();
for
(
MediaCodecInfo
mediaCodecInfo
:
allCodecInfos
)
{
MediaCodecList
mediaCodecList
=
new
MediaCodecList
(
MediaCodecList
.
ALL_CODECS
);
if
(!
mediaCodecInfo
.
isEncoder
())
{
MediaCodecInfo
[]
allCodecInfos
=
mediaCodecList
.
getCodecInfos
();
continue
;
for
(
MediaCodecInfo
mediaCodecInfo
:
allCodecInfos
)
{
if
(!
mediaCodecInfo
.
isEncoder
())
{
continue
;
}
String
[]
supportedMimeTypes
=
mediaCodecInfo
.
getSupportedTypes
();
for
(
String
mimeType
:
supportedMimeTypes
)
{
if
(
MimeTypes
.
isVideo
(
mimeType
))
{
encoderInfosBuilder
.
put
(
Ascii
.
toLowerCase
(
mimeType
),
mediaCodecInfo
);
}
}
encoders
.
add
(
mediaCodecInfo
);
}
}
}
}
return
encoderInfosBuilder
.
build
();
}
}
@RequiresApi
(
29
)
@RequiresApi
(
29
)
...
...
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