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
4d1283f4
authored
Dec 21, 2022
by
tofunmi
Committed by
Marc Baechinger
Jan 04, 2023
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add support for customizing overlay anchor point.
PiperOrigin-RevId: 496956035
parent
890fd0a9
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
98 additions
and
12 deletions
library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/OverlayTextureProcessorPixelTest.java
library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlaySettings.java
library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayTextureProcessor.java
testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_anchored.png
library/effect/src/androidTest/java/com/google/android/exoplayer2/effect/OverlayTextureProcessorPixelTest.java
View file @
4d1283f4
...
@@ -62,6 +62,8 @@ public class OverlayTextureProcessorPixelTest {
...
@@ -62,6 +62,8 @@ public class OverlayTextureProcessorPixelTest {
"media/bitmap/sample_mp4_first_frame/electrical_colors/original.png"
;
"media/bitmap/sample_mp4_first_frame/electrical_colors/original.png"
;
public
static
final
String
OVERLAY_BITMAP_DEFAULT
=
public
static
final
String
OVERLAY_BITMAP_DEFAULT
=
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_default.png"
;
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_default.png"
;
public
static
final
String
OVERLAY_BITMAP_ANCHORED
=
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_anchored.png"
;
public
static
final
String
OVERLAY_BITMAP_SCALED
=
public
static
final
String
OVERLAY_BITMAP_SCALED
=
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_scaled.png"
;
"media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_scaled.png"
;
public
static
final
String
OVERLAY_BITMAP_TRANSLUCENT
=
public
static
final
String
OVERLAY_BITMAP_TRANSLUCENT
=
...
@@ -174,6 +176,33 @@ public class OverlayTextureProcessorPixelTest {
...
@@ -174,6 +176,33 @@ public class OverlayTextureProcessorPixelTest {
}
}
@Test
@Test
public
void
drawFrame_anchoredBitmapOverlay_blendsBitmapIntoTopLeftOfFrame
()
throws
Exception
{
String
testId
=
"drawFrame_anchoredBitmapOverlay"
;
Bitmap
overlayBitmap
=
readBitmap
(
OVERLAY_PNG_ASSET_PATH
);
float
[]
translateMatrix
=
GlUtil
.
create4x4IdentityMatrix
();
Matrix
.
translateM
(
translateMatrix
,
/* mOffset= */
0
,
/* x= */
-
1
f
,
/* y= */
1
f
,
/* z= */
1
);
OverlaySettings
overlaySettings
=
new
OverlaySettings
.
Builder
().
setMatrix
(
translateMatrix
).
setAnchor
(-
1
f
,
1
f
).
build
();
BitmapOverlay
staticBitmapOverlay
=
BitmapOverlay
.
createStaticBitmapOverlay
(
overlayBitmap
,
overlaySettings
);
overlayTextureProcessor
=
new
OverlayEffect
(
ImmutableList
.
of
(
staticBitmapOverlay
))
.
toGlTextureProcessor
(
context
,
/* useHdr= */
false
);
Size
outputSize
=
overlayTextureProcessor
.
configure
(
inputWidth
,
inputHeight
);
setupOutputTexture
(
outputSize
.
getWidth
(),
outputSize
.
getHeight
());
Bitmap
expectedBitmap
=
readBitmap
(
OVERLAY_BITMAP_ANCHORED
);
overlayTextureProcessor
.
drawFrame
(
inputTexId
,
/* presentationTimeUs= */
0
);
Bitmap
actualBitmap
=
createArgb8888BitmapFromCurrentGlFramebuffer
(
outputSize
.
getWidth
(),
outputSize
.
getHeight
());
maybeSaveTestBitmapToCacheDirectory
(
testId
,
/* bitmapLabel= */
"actual"
,
actualBitmap
);
float
averagePixelAbsoluteDifference
=
getBitmapAveragePixelAbsoluteDifferenceArgb8888
(
expectedBitmap
,
actualBitmap
,
testId
);
assertThat
(
averagePixelAbsoluteDifference
).
isAtMost
(
MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE
);
}
@Test
public
void
drawFrame_translucentBitmapOverlay_blendsBitmapIntoFrame
()
throws
Exception
{
public
void
drawFrame_translucentBitmapOverlay_blendsBitmapIntoFrame
()
throws
Exception
{
String
testId
=
"drawFrame_translucentBitmapOverlay"
;
String
testId
=
"drawFrame_translucentBitmapOverlay"
;
Bitmap
bitmap
=
readBitmap
(
OVERLAY_PNG_ASSET_PATH
);
Bitmap
bitmap
=
readBitmap
(
OVERLAY_PNG_ASSET_PATH
);
...
...
library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlaySettings.java
View file @
4d1283f4
...
@@ -16,6 +16,7 @@ package com.google.android.exoplayer2.effect;
...
@@ -16,6 +16,7 @@ package com.google.android.exoplayer2.effect;
*/
*/
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkArgument
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkArgument
;
import
android.util.Pair
;
import
androidx.annotation.FloatRange
;
import
androidx.annotation.FloatRange
;
import
com.google.android.exoplayer2.util.GlUtil
;
import
com.google.android.exoplayer2.util.GlUtil
;
import
com.google.errorprone.annotations.CanIgnoreReturnValue
;
import
com.google.errorprone.annotations.CanIgnoreReturnValue
;
...
@@ -25,11 +26,13 @@ public final class OverlaySettings {
...
@@ -25,11 +26,13 @@ public final class OverlaySettings {
public
final
boolean
useHdr
;
public
final
boolean
useHdr
;
public
final
float
alpha
;
public
final
float
alpha
;
public
final
float
[]
matrix
;
public
final
float
[]
matrix
;
public
final
Pair
<
Float
,
Float
>
anchor
;
private
OverlaySettings
(
boolean
useHdr
,
float
alpha
,
float
[]
matrix
)
{
private
OverlaySettings
(
boolean
useHdr
,
float
alpha
,
float
[]
matrix
,
Pair
<
Float
,
Float
>
anchor
)
{
this
.
useHdr
=
useHdr
;
this
.
useHdr
=
useHdr
;
this
.
alpha
=
alpha
;
this
.
alpha
=
alpha
;
this
.
matrix
=
matrix
;
this
.
matrix
=
matrix
;
this
.
anchor
=
anchor
;
}
}
/** A builder for {@link OverlaySettings} instances. */
/** A builder for {@link OverlaySettings} instances. */
...
@@ -37,10 +40,12 @@ public final class OverlaySettings {
...
@@ -37,10 +40,12 @@ public final class OverlaySettings {
private
boolean
useHdr
;
private
boolean
useHdr
;
private
float
alpha
=
1
;
private
float
alpha
=
1
;
private
float
[]
matrix
;
private
float
[]
matrix
;
private
Pair
<
Float
,
Float
>
anchor
;
/** Creates a new {@link Builder}. */
/** Creates a new {@link Builder}. */
public
Builder
()
{
public
Builder
()
{
matrix
=
GlUtil
.
create4x4IdentityMatrix
();
matrix
=
GlUtil
.
create4x4IdentityMatrix
();
anchor
=
Pair
.
create
(
0
f
,
0
f
);
}
}
/**
/**
...
@@ -81,9 +86,33 @@ public final class OverlaySettings {
...
@@ -81,9 +86,33 @@ public final class OverlaySettings {
return
this
;
return
this
;
}
}
/**
* Sets the coordinates for the anchor point of the overlay.
*
* <p>The anchor point is the point inside the overlay that the overlay is positioned from.
*
* <p>The coordinates are specified in Normalised Device Coordinates (NDCs). Set to always
* return {@code (0,0)} (the center) by default.
*
* @param x the NDC x-coordinate.
* @param y the NDC y-coordinate.
*/
@CanIgnoreReturnValue
public
Builder
setAnchor
(
@FloatRange
(
from
=
-
1
,
to
=
1
)
float
x
,
@FloatRange
(
from
=
-
1
,
to
=
1
)
float
y
)
{
checkArgument
(
-
1
<=
x
&&
x
<=
1
,
"x needs to be specified in terms of NDCs which lie in the interval [-1, 1]."
);
checkArgument
(
-
1
<=
y
&&
y
<=
1
,
"y needs to be specified in terms of NDCs which lie in the interval [-1, 1]."
);
this
.
anchor
=
Pair
.
create
(
x
,
y
);
return
this
;
}
/** Creates an instance of {@link OverlaySettings}, using defaults if values are unset. */
/** Creates an instance of {@link OverlaySettings}, using defaults if values are unset. */
public
OverlaySettings
build
()
{
public
OverlaySettings
build
()
{
return
new
OverlaySettings
(
useHdr
,
alpha
,
matrix
);
return
new
OverlaySettings
(
useHdr
,
alpha
,
matrix
,
anchor
);
}
}
}
}
}
}
library/effect/src/main/java/com/google/android/exoplayer2/effect/OverlayTextureProcessor.java
View file @
4d1283f4
...
@@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkArgument;
...
@@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import
android.content.Context
;
import
android.content.Context
;
import
android.opengl.GLES20
;
import
android.opengl.GLES20
;
import
android.opengl.Matrix
;
import
android.opengl.Matrix
;
import
android.util.Pair
;
import
com.google.android.exoplayer2.util.FrameProcessingException
;
import
com.google.android.exoplayer2.util.FrameProcessingException
;
import
com.google.android.exoplayer2.util.GlProgram
;
import
com.google.android.exoplayer2.util.GlProgram
;
import
com.google.android.exoplayer2.util.GlUtil
;
import
com.google.android.exoplayer2.util.GlUtil
;
...
@@ -36,6 +37,8 @@ import com.google.common.collect.ImmutableList;
...
@@ -36,6 +37,8 @@ import com.google.common.collect.ImmutableList;
private
final
ImmutableList
<
TextureOverlay
>
overlays
;
private
final
ImmutableList
<
TextureOverlay
>
overlays
;
private
final
float
[]
aspectRatioMatrix
;
private
final
float
[]
aspectRatioMatrix
;
private
final
float
[]
overlayMatrix
;
private
final
float
[]
overlayMatrix
;
private
final
float
[]
anchorMatrix
;
private
final
float
[]
transformationMatrix
;
private
int
videoWidth
;
private
int
videoWidth
;
private
int
videoHeight
;
private
int
videoHeight
;
...
@@ -61,7 +64,8 @@ import com.google.common.collect.ImmutableList;
...
@@ -61,7 +64,8 @@ import com.google.common.collect.ImmutableList;
this
.
overlays
=
overlays
;
this
.
overlays
=
overlays
;
aspectRatioMatrix
=
GlUtil
.
create4x4IdentityMatrix
();
aspectRatioMatrix
=
GlUtil
.
create4x4IdentityMatrix
();
overlayMatrix
=
GlUtil
.
create4x4IdentityMatrix
();
overlayMatrix
=
GlUtil
.
create4x4IdentityMatrix
();
anchorMatrix
=
GlUtil
.
create4x4IdentityMatrix
();
transformationMatrix
=
GlUtil
.
create4x4IdentityMatrix
();
try
{
try
{
glProgram
=
glProgram
=
new
GlProgram
(
createVertexShader
(
overlays
.
size
()),
createFragmentShader
(
overlays
.
size
()));
new
GlProgram
(
createVertexShader
(
overlays
.
size
()),
createFragmentShader
(
overlays
.
size
()));
...
@@ -89,10 +93,12 @@ import com.google.common.collect.ImmutableList;
...
@@ -89,10 +93,12 @@ import com.google.common.collect.ImmutableList;
if
(!
overlays
.
isEmpty
())
{
if
(!
overlays
.
isEmpty
())
{
for
(
int
texUnitIndex
=
1
;
texUnitIndex
<=
overlays
.
size
();
texUnitIndex
++)
{
for
(
int
texUnitIndex
=
1
;
texUnitIndex
<=
overlays
.
size
();
texUnitIndex
++)
{
TextureOverlay
overlay
=
overlays
.
get
(
texUnitIndex
-
1
);
TextureOverlay
overlay
=
overlays
.
get
(
texUnitIndex
-
1
);
glProgram
.
setSamplerTexIdUniform
(
glProgram
.
setSamplerTexIdUniform
(
Util
.
formatInvariant
(
"uOverlayTexSampler%d"
,
texUnitIndex
),
Util
.
formatInvariant
(
"uOverlayTexSampler%d"
,
texUnitIndex
),
overlay
.
getTextureId
(
presentationTimeUs
),
overlay
.
getTextureId
(
presentationTimeUs
),
texUnitIndex
);
texUnitIndex
);
GlUtil
.
setToIdentity
(
aspectRatioMatrix
);
GlUtil
.
setToIdentity
(
aspectRatioMatrix
);
Matrix
.
scaleM
(
Matrix
.
scaleM
(
aspectRatioMatrix
,
aspectRatioMatrix
,
...
@@ -100,15 +106,40 @@ import com.google.common.collect.ImmutableList;
...
@@ -100,15 +106,40 @@ import com.google.common.collect.ImmutableList;
videoWidth
/
(
float
)
overlay
.
getTextureSize
(
presentationTimeUs
).
getWidth
(),
videoWidth
/
(
float
)
overlay
.
getTextureSize
(
presentationTimeUs
).
getWidth
(),
videoHeight
/
(
float
)
overlay
.
getTextureSize
(
presentationTimeUs
).
getHeight
(),
videoHeight
/
(
float
)
overlay
.
getTextureSize
(
presentationTimeUs
).
getHeight
(),
/* z= */
1
);
/* z= */
1
);
glProgram
.
setFloatsUniform
(
Util
.
formatInvariant
(
"uAspectRatioMatrix%d"
,
texUnitIndex
),
aspectRatioMatrix
);
Matrix
.
invertM
(
Matrix
.
invertM
(
overlayMatrix
,
overlayMatrix
,
MATRIX_OFFSET
,
MATRIX_OFFSET
,
overlay
.
getOverlaySettings
(
presentationTimeUs
).
matrix
,
overlay
.
getOverlaySettings
(
presentationTimeUs
).
matrix
,
MATRIX_OFFSET
);
MATRIX_OFFSET
);
Pair
<
Float
,
Float
>
overlayAnchor
=
overlay
.
getOverlaySettings
(
presentationTimeUs
).
anchor
;
GlUtil
.
setToIdentity
(
anchorMatrix
);
Matrix
.
translateM
(
anchorMatrix
,
/* mOffset= */
0
,
overlayAnchor
.
first
*
overlay
.
getTextureSize
(
presentationTimeUs
).
getWidth
()
/
videoWidth
,
overlayAnchor
.
second
*
overlay
.
getTextureSize
(
presentationTimeUs
).
getHeight
()
/
videoHeight
,
/* z= */
1
);
Matrix
.
multiplyMM
(
transformationMatrix
,
MATRIX_OFFSET
,
overlayMatrix
,
MATRIX_OFFSET
,
anchorMatrix
,
MATRIX_OFFSET
);
Matrix
.
multiplyMM
(
transformationMatrix
,
MATRIX_OFFSET
,
aspectRatioMatrix
,
MATRIX_OFFSET
,
transformationMatrix
,
MATRIX_OFFSET
);
glProgram
.
setFloatsUniform
(
glProgram
.
setFloatsUniform
(
Util
.
formatInvariant
(
"uOverlayMatrix%d"
,
texUnitIndex
),
overlayMatrix
);
Util
.
formatInvariant
(
"uTransformationMatrix%d"
,
texUnitIndex
),
transformationMatrix
);
glProgram
.
setFloatUniform
(
glProgram
.
setFloatUniform
(
Util
.
formatInvariant
(
"uOverlayAlpha%d"
,
texUnitIndex
),
Util
.
formatInvariant
(
"uOverlayAlpha%d"
,
texUnitIndex
),
overlay
.
getOverlaySettings
(
presentationTimeUs
).
alpha
);
overlay
.
getOverlaySettings
(
presentationTimeUs
).
alpha
);
...
@@ -143,9 +174,8 @@ import com.google.common.collect.ImmutableList;
...
@@ -143,9 +174,8 @@ import com.google.common.collect.ImmutableList;
for
(
int
texUnitIndex
=
1
;
texUnitIndex
<=
numOverlays
;
texUnitIndex
++)
{
for
(
int
texUnitIndex
=
1
;
texUnitIndex
<=
numOverlays
;
texUnitIndex
++)
{
shader
shader
.
append
(
Util
.
formatInvariant
(
"uniform mat4 uAspectRatioMatrix%d;\n"
,
texUnitIndex
))
.
append
(
Util
.
formatInvariant
(
"uniform mat4 uTransformationMatrix%s;\n"
,
texUnitIndex
))
.
append
(
Util
.
formatInvariant
(
"uniform mat4 uOverlayMatrix%d;\n"
,
texUnitIndex
))
.
append
(
Util
.
formatInvariant
(
"varying vec2 vOverlayTexSamplingCoord%s;\n"
,
texUnitIndex
));
.
append
(
Util
.
formatInvariant
(
"varying vec2 vOverlayTexSamplingCoord%d;\n"
,
texUnitIndex
));
}
}
shader
shader
...
@@ -160,9 +190,7 @@ import com.google.common.collect.ImmutableList;
...
@@ -160,9 +190,7 @@ import com.google.common.collect.ImmutableList;
shader
shader
.
append
(
Util
.
formatInvariant
(
" vec4 aOverlayPosition%d = \n"
,
texUnitIndex
))
.
append
(
Util
.
formatInvariant
(
" vec4 aOverlayPosition%d = \n"
,
texUnitIndex
))
.
append
(
.
append
(
Util
.
formatInvariant
(
Util
.
formatInvariant
(
" uTransformationMatrix%s * aFramePosition;\n"
,
texUnitIndex
))
" uAspectRatioMatrix%d * uOverlayMatrix%d * aFramePosition;\n"
,
texUnitIndex
,
texUnitIndex
))
.
append
(
.
append
(
Util
.
formatInvariant
(
Util
.
formatInvariant
(
" vOverlayTexSamplingCoord%d = getTexSamplingCoord(aOverlayPosition%d.xy);\n"
,
" vOverlayTexSamplingCoord%d = getTexSamplingCoord(aOverlayPosition%d.xy);\n"
,
...
...
testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/overlay_bitmap_anchored.png
0 → 100644
View file @
4d1283f4
545 KB
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