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
404192e4
authored
Apr 28, 2022
by
huangdarwin
Committed by
Ian Baker
May 09, 2022
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Transformer: Restrict frame buffer size for all omx decoders API >= 29.
PiperOrigin-RevId: 445119411
parent
a161482c
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
37 additions
and
32 deletions
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java
View file @
404192e4
...
...
@@ -33,6 +33,8 @@ import java.util.List;
* buffers.
*/
public
interface
Codec
{
/** Default value for the pending frame count, which represents applying no limit. */
int
UNLIMITED_PENDING_FRAME_COUNT
=
Integer
.
MAX_VALUE
;
/** A factory for {@linkplain Codec decoder} instances. */
interface
DecoderFactory
{
...
...
@@ -138,6 +140,14 @@ public interface Codec {
Surface
getInputSurface
();
/**
* Returns the maximum number of frames that may be pending in the output {@code Codec} at a time,
* or {@link #UNLIMITED_PENDING_FRAME_COUNT} if it's not necessary to enforce a limit.
*/
default
int
getMaxPendingFrameCount
()
{
return
UNLIMITED_PENDING_FRAME_COUNT
;
}
/**
* Dequeues a writable input buffer, if available.
*
* <p>This method must not be called from video encoders because they must use a {@link Surface}
...
...
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java
View file @
404192e4
...
...
@@ -30,6 +30,8 @@ import com.google.android.exoplayer2.Format;
import
com.google.android.exoplayer2.decoder.DecoderInputBuffer
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.TraceUtil
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.common.base.Ascii
;
import
com.google.common.collect.ImmutableList
;
import
java.io.IOException
;
import
java.nio.ByteBuffer
;
...
...
@@ -119,6 +121,29 @@ public final class DefaultCodec implements Codec {
}
@Override
public
int
getMaxPendingFrameCount
()
{
if
(
Util
.
SDK_INT
<
29
)
{
// Prior to API 29, decoders may drop frames to keep their output surface from growing out of
// bounds. From API 29, the {@link MediaFormat#KEY_ALLOW_FRAME_DROP} key prevents frame
// dropping even when the surface is full. Frame dropping is never desired, so allow a maximum
// of one frame to be pending at a time.
// TODO(b/226330223): Investigate increasing this limit.
return
1
;
}
if
(
Ascii
.
toUpperCase
(
mediaCodec
.
getCodecInfo
().
getCanonicalName
()).
startsWith
(
"OMX."
))
{
// Some OMX decoders don't correctly track their number of output buffers available, and get
// stuck if too many frames are rendered without being processed, so limit the number of
// pending frames to avoid getting stuck. This value is experimentally determined. See also
// b/213455700, b/230097284, and b/229978305,.
// TODO(b/230097284): Add a maximum API check after we know which APIs will never use OMX.
return
10
;
}
// Otherwise don't limit the number of frames that can be pending at a time, to maximize
// throughput.
return
UNLIMITED_PENDING_FRAME_COUNT
;
}
@Override
@EnsuresNonNullIf
(
expression
=
"#1.data"
,
result
=
true
)
public
boolean
maybeDequeueInputBuffer
(
DecoderInputBuffer
inputBuffer
)
throws
TransformationException
{
...
...
library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java
View file @
404192e4
...
...
@@ -34,9 +34,6 @@ import org.checkerframework.dataflow.qual.Pure;
* Pipeline to decode video samples, apply transformations on the raw samples, and re-encode them.
*/
/* package */
final
class
VideoTranscodingSamplePipeline
implements
SamplePipeline
{
private
static
final
int
FRAME_COUNT_UNLIMITED
=
-
1
;
private
final
int
outputRotationDegrees
;
private
final
DecoderInputBuffer
decoderInputBuffer
;
private
final
Codec
decoder
;
...
...
@@ -135,7 +132,7 @@ import org.checkerframework.dataflow.qual.Pure;
inputFormat
,
frameProcessorChain
.
getInputSurface
(),
transformationRequest
.
enableRequestSdrToneMapping
);
maxPendingFrameCount
=
getMaxPendingFrameCount
();
maxPendingFrameCount
=
decoder
.
getMaxPendingFrameCount
();
}
@Override
...
...
@@ -254,7 +251,7 @@ import org.checkerframework.dataflow.qual.Pure;
return
false
;
}
if
(
maxPendingFrameCount
!=
FRAME_COUNT_UNLIMITED
if
(
maxPendingFrameCount
!=
Codec
.
UNLIMITED_PENDING_FRAME_COUNT
&&
frameProcessorChain
.
getPendingFrameCount
()
==
maxPendingFrameCount
)
{
return
false
;
}
...
...
@@ -263,31 +260,4 @@ import org.checkerframework.dataflow.qual.Pure;
decoder
.
releaseOutputBuffer
(
/* render= */
true
);
return
true
;
}
/**
* Returns the maximum number of frames that may be pending in the output {@link
* FrameProcessorChain} at a time, or {@link #FRAME_COUNT_UNLIMITED} if it's not necessary to
* enforce a limit.
*/
private
static
int
getMaxPendingFrameCount
()
{
if
(
Util
.
SDK_INT
<
29
)
{
// Prior to API 29, decoders may drop frames to keep their output surface from growing out of
// bounds, while from API 29, the {@link MediaFormat#KEY_ALLOW_FRAME_DROP} key prevents frame
// dropping even when the surface is full. We never want frame dropping so allow a maximum of
// one frame to be pending at a time.
// TODO(b/226330223): Investigate increasing this limit.
return
1
;
}
if
(
Util
.
SDK_INT
<
33
&&
(
"OnePlus"
.
equals
(
Util
.
MANUFACTURER
)
||
"samsung"
.
equals
(
Util
.
MANUFACTURER
)))
{
// Some OMX decoders don't correctly track their number of output buffers available, and get
// stuck if too many frames are rendered without being processed, so we limit the number of
// pending frames to avoid getting stuck. This value is experimentally determined. See also
// b/213455700.
return
10
;
}
// Otherwise don't limit the number of frames that can be pending at a time, to maximize
// throughput.
return
FRAME_COUNT_UNLIMITED
;
}
}
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