Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
6215934b
Commit
6215934b
authored
Aug 31, 2007
by
Jean-Paul Saman
Committed by
Jean-Paul Saman
Mar 05, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add chroma conversion routines for RGBA
parent
bf7d6ce0
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
472 additions
and
34 deletions
+472
-34
modules/video_filter/blend.c
modules/video_filter/blend.c
+472
-34
No files found.
modules/video_filter/blend.c
View file @
6215934b
...
...
@@ -2,7 +2,7 @@
* blend.c: alpha blend 2 pictures together
*****************************************************************************
* Copyright (C) 2003 the VideoLAN team
* $Id$
* $Id
: 16477b6ff92349827bbdb56e73aa7179ebdd31f3
$
*
* Author: Gildas Bazin <gbazin@videolan.org>
*
...
...
@@ -60,6 +60,16 @@ static void BlendPalYUVPacked( filter_t *, picture_t *, picture_t *, picture_t *
static
void
BlendPalRV
(
filter_t
*
,
picture_t
*
,
picture_t
*
,
picture_t
*
,
int
,
int
,
int
,
int
,
int
);
/* RGBA */
static
void
BlendRGBAI420
(
filter_t
*
,
picture_t
*
,
picture_t
*
,
picture_t
*
,
int
,
int
,
int
,
int
,
int
);
static
void
BlendRGBAYUVPacked
(
filter_t
*
,
picture_t
*
,
picture_t
*
,
picture_t
*
,
int
,
int
,
int
,
int
,
int
);
static
void
BlendRGBAR16
(
filter_t
*
,
picture_t
*
,
picture_t
*
,
picture_t
*
,
int
,
int
,
int
,
int
,
int
);
static
void
BlendRGBAR24
(
filter_t
*
,
picture_t
*
,
picture_t
*
,
picture_t
*
,
int
,
int
,
int
,
int
,
int
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
...
...
@@ -80,7 +90,8 @@ static int OpenFilter( vlc_object_t *p_this )
/* Check if we can handle that format.
* We could try to use a chroma filter if we can't. */
if
(
(
p_filter
->
fmt_in
.
video
.
i_chroma
!=
VLC_FOURCC
(
'Y'
,
'U'
,
'V'
,
'A'
)
&&
p_filter
->
fmt_in
.
video
.
i_chroma
!=
VLC_FOURCC
(
'Y'
,
'U'
,
'V'
,
'P'
)
)
||
p_filter
->
fmt_in
.
video
.
i_chroma
!=
VLC_FOURCC
(
'Y'
,
'U'
,
'V'
,
'P'
)
&&
p_filter
->
fmt_in
.
video
.
i_chroma
!=
VLC_FOURCC
(
'R'
,
'G'
,
'B'
,
'A'
)
)
||
(
p_filter
->
fmt_out
.
video
.
i_chroma
!=
VLC_FOURCC
(
'I'
,
'4'
,
'2'
,
'0'
)
&&
p_filter
->
fmt_out
.
video
.
i_chroma
!=
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
)
&&
p_filter
->
fmt_out
.
video
.
i_chroma
!=
VLC_FOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
)
&&
...
...
@@ -108,10 +119,54 @@ static int OpenFilter( vlc_object_t *p_this )
(
char
*
)
&
p_filter
->
fmt_in
.
video
.
i_chroma
,
(
char
*
)
&
p_filter
->
fmt_out
.
video
.
i_chroma
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* CloseFilter: clean up the filter
*****************************************************************************/
static
void
CloseFilter
(
vlc_object_t
*
p_this
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
free
(
p_sys
);
}
/***********************************************************************
* Utils
***********************************************************************/
static
inline
void
yuv_to_rgb
(
int
*
r
,
int
*
g
,
int
*
b
,
uint8_t
y1
,
uint8_t
u1
,
uint8_t
v1
)
{
/* macros used for YUV pixel conversions */
# define SCALEBITS 10
# define ONE_HALF (1 << (SCALEBITS - 1))
# define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
# define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
int
y
,
cb
,
cr
,
r_add
,
g_add
,
b_add
;
cb
=
u1
-
128
;
cr
=
v1
-
128
;
r_add
=
FIX
(
1
.
40200
*
255
.
0
/
224
.
0
)
*
cr
+
ONE_HALF
;
g_add
=
-
FIX
(
0
.
34414
*
255
.
0
/
224
.
0
)
*
cb
-
FIX
(
0
.
71414
*
255
.
0
/
224
.
0
)
*
cr
+
ONE_HALF
;
b_add
=
FIX
(
1
.
77200
*
255
.
0
/
224
.
0
)
*
cb
+
ONE_HALF
;
y
=
(
y1
-
16
)
*
FIX
(
255
.
0
/
219
.
0
);
*
r
=
CLAMP
((
y
+
r_add
)
>>
SCALEBITS
);
*
g
=
CLAMP
((
y
+
g_add
)
>>
SCALEBITS
);
*
b
=
CLAMP
((
y
+
b_add
)
>>
SCALEBITS
);
}
static
inline
void
rgb_to_yuv
(
uint8_t
*
y
,
uint8_t
*
u
,
uint8_t
*
v
,
int
r
,
int
g
,
int
b
)
{
*
y
=
(
(
(
66
*
r
+
129
*
g
+
25
*
b
+
128
)
>>
8
)
+
16
);
*
u
=
(
(
-
38
*
r
-
74
*
g
+
112
*
b
+
128
)
>>
8
)
+
128
;
*
v
=
(
(
112
*
r
-
94
*
g
-
18
*
b
+
128
)
>>
8
)
+
128
;
}
/****************************************************************************
* Blend: the whole thing
****************************************************************************
...
...
@@ -189,7 +244,36 @@ static void Blend( filter_t *p_filter, picture_t *p_dst,
i_x_offset
,
i_y_offset
,
i_width
,
i_height
,
i_alpha
);
return
;
}
if
(
p_filter
->
fmt_in
.
video
.
i_chroma
==
VLC_FOURCC
(
'R'
,
'G'
,
'B'
,
'A'
)
)
{
switch
(
p_filter
->
fmt_out
.
video
.
i_chroma
)
{
case
VLC_FOURCC
(
'I'
,
'4'
,
'2'
,
'0'
):
case
VLC_FOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
):
BlendRGBAI420
(
p_filter
,
p_dst
,
p_dst_orig
,
p_src
,
i_x_offset
,
i_y_offset
,
i_width
,
i_height
,
i_alpha
);
return
;
case
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
):
case
VLC_FOURCC
(
'U'
,
'Y'
,
'V'
,
'Y'
):
case
VLC_FOURCC
(
'Y'
,
'V'
,
'Y'
,
'U'
):
BlendRGBAYUVPacked
(
p_filter
,
p_dst
,
p_dst_orig
,
p_src
,
i_x_offset
,
i_y_offset
,
i_width
,
i_height
,
i_alpha
);
return
;
case
VLC_FOURCC
(
'R'
,
'V'
,
'2'
,
'4'
):
case
VLC_FOURCC
(
'R'
,
'V'
,
'3'
,
'2'
):
BlendRGBAR24
(
p_filter
,
p_dst
,
p_dst_orig
,
p_src
,
i_x_offset
,
i_y_offset
,
i_width
,
i_height
,
i_alpha
);
return
;
case
VLC_FOURCC
(
'R'
,
'V'
,
'1'
,
'6'
):
BlendRGBAR16
(
p_filter
,
p_dst
,
p_dst_orig
,
p_src
,
i_x_offset
,
i_y_offset
,
i_width
,
i_height
,
i_alpha
);
return
;
}
}
msg_Dbg
(
p_filter
,
"no matching alpha blending routine"
);
}
...
...
@@ -310,29 +394,6 @@ static void BlendI420( filter_t *p_filter, picture_t *p_dst,
return
;
}
static
inline
void
yuv_to_rgb
(
int
*
r
,
int
*
g
,
int
*
b
,
uint8_t
y1
,
uint8_t
u1
,
uint8_t
v1
)
{
/* macros used for YUV pixel conversions */
# define SCALEBITS 10
# define ONE_HALF (1 << (SCALEBITS - 1))
# define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
# define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
int
y
,
cb
,
cr
,
r_add
,
g_add
,
b_add
;
cb
=
u1
-
128
;
cr
=
v1
-
128
;
r_add
=
FIX
(
1
.
40200
*
255
.
0
/
224
.
0
)
*
cr
+
ONE_HALF
;
g_add
=
-
FIX
(
0
.
34414
*
255
.
0
/
224
.
0
)
*
cb
-
FIX
(
0
.
71414
*
255
.
0
/
224
.
0
)
*
cr
+
ONE_HALF
;
b_add
=
FIX
(
1
.
77200
*
255
.
0
/
224
.
0
)
*
cb
+
ONE_HALF
;
y
=
(
y1
-
16
)
*
FIX
(
255
.
0
/
219
.
0
);
*
r
=
CLAMP
((
y
+
r_add
)
>>
SCALEBITS
);
*
g
=
CLAMP
((
y
+
g_add
)
>>
SCALEBITS
);
*
b
=
CLAMP
((
y
+
b_add
)
>>
SCALEBITS
);
}
static
void
BlendR16
(
filter_t
*
p_filter
,
picture_t
*
p_dst_pic
,
picture_t
*
p_dst_orig
,
picture_t
*
p_src
,
int
i_x_offset
,
int
i_y_offset
,
...
...
@@ -970,13 +1031,390 @@ static void BlendPalRV( filter_t *p_filter, picture_t *p_dst_pic,
return
;
}
/*****************************************************************************
* CloseFilter: clean up the filter
*****************************************************************************/
static
void
CloseFilter
(
vlc_object_t
*
p_this
)
/***********************************************************************
* RGBA
***********************************************************************/
static
void
BlendRGBAI420
(
filter_t
*
p_filter
,
picture_t
*
p_dst
,
picture_t
*
p_dst_orig
,
picture_t
*
p_src
,
int
i_x_offset
,
int
i_y_offset
,
int
i_width
,
int
i_height
,
int
i_alpha
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
int
i_src1_pitch
,
i_src2_pitch
,
i_dst_pitch
,
i_src_pix_pitch
;
uint8_t
*
p_src1_y
,
*
p_dst_y
;
uint8_t
*
p_src1_u
,
*
p_dst_u
;
uint8_t
*
p_src1_v
,
*
p_dst_v
;
uint8_t
*
p_src2
;
int
i_x
,
i_y
,
i_trans
;
uint8_t
y
,
u
,
v
;
free
(
p_sys
);
vlc_bool_t
b_even_scanline
=
i_y_offset
%
2
;
i_dst_pitch
=
p_dst
->
p
[
Y_PLANE
].
i_pitch
;
p_dst_y
=
p_dst
->
p
[
Y_PLANE
].
p_pixels
+
i_x_offset
+
p_filter
->
fmt_out
.
video
.
i_x_offset
+
p_dst
->
p
[
Y_PLANE
].
i_pitch
*
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
);
p_dst_u
=
p_dst
->
p
[
U_PLANE
].
p_pixels
+
i_x_offset
/
2
+
p_filter
->
fmt_out
.
video
.
i_x_offset
/
2
+
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
)
/
2
*
p_dst
->
p
[
U_PLANE
].
i_pitch
;
p_dst_v
=
p_dst
->
p
[
V_PLANE
].
p_pixels
+
i_x_offset
/
2
+
p_filter
->
fmt_out
.
video
.
i_x_offset
/
2
+
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
)
/
2
*
p_dst
->
p
[
V_PLANE
].
i_pitch
;
i_src1_pitch
=
p_dst_orig
->
p
[
Y_PLANE
].
i_pitch
;
p_src1_y
=
p_dst_orig
->
p
[
Y_PLANE
].
p_pixels
+
i_x_offset
+
p_filter
->
fmt_out
.
video
.
i_x_offset
+
p_dst_orig
->
p
[
Y_PLANE
].
i_pitch
*
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
);
p_src1_u
=
p_dst_orig
->
p
[
U_PLANE
].
p_pixels
+
i_x_offset
/
2
+
p_filter
->
fmt_out
.
video
.
i_x_offset
/
2
+
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
)
/
2
*
p_dst_orig
->
p
[
U_PLANE
].
i_pitch
;
p_src1_v
=
p_dst_orig
->
p
[
V_PLANE
].
p_pixels
+
i_x_offset
/
2
+
p_filter
->
fmt_out
.
video
.
i_x_offset
/
2
+
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
)
/
2
*
p_dst_orig
->
p
[
V_PLANE
].
i_pitch
;
i_src_pix_pitch
=
p_src
->
p
->
i_pixel_pitch
;
i_src2_pitch
=
p_src
->
p
->
i_pitch
;
p_src2
=
p_src
->
p
->
p_pixels
+
p_filter
->
fmt_in
.
video
.
i_x_offset
*
i_src2_pitch
+
p_src
->
p
->
i_pitch
*
p_filter
->
fmt_in
.
video
.
i_y_offset
;
#define MAX_TRANS 255
#define TRANS_BITS 8
/* Draw until we reach the bottom of the subtitle */
for
(
i_y
=
0
;
i_y
<
i_height
;
i_y
++
,
p_dst_y
+=
i_dst_pitch
,
p_src1_y
+=
i_src1_pitch
,
p_dst_u
+=
b_even_scanline
?
i_dst_pitch
/
2
:
0
,
p_src1_u
+=
b_even_scanline
?
i_src1_pitch
/
2
:
0
,
p_dst_v
+=
b_even_scanline
?
i_dst_pitch
/
2
:
0
,
p_src1_v
+=
b_even_scanline
?
i_src1_pitch
/
2
:
0
,
p_src2
+=
i_src2_pitch
)
{
b_even_scanline
=
!
b_even_scanline
;
/* Draw until we reach the end of the line */
for
(
i_x
=
0
;
i_x
<
i_width
;
i_x
++
)
{
#define R ( p_src2[i_x * i_src_pix_pitch + 0] )
#define G ( p_src2[i_x * i_src_pix_pitch + 1] )
#define B ( p_src2[i_x * i_src_pix_pitch + 2] )
i_trans
=
(
p_src2
[
i_x
*
i_src_pix_pitch
+
3
]
*
i_alpha
)
/
255
;
if
(
!
i_trans
)
{
/* Completely transparent. Don't change pixel */
continue
;
}
else
if
(
i_trans
==
MAX_TRANS
)
{
/* Completely opaque. Completely overwrite underlying pixel */
rgb_to_yuv
(
&
y
,
&
u
,
&
v
,
R
,
G
,
B
);
p_dst_y
[
i_x
]
=
y
;
if
(
b_even_scanline
&&
i_x
%
2
==
0
)
{
p_dst_u
[
i_x
/
2
]
=
u
;
p_dst_v
[
i_x
/
2
]
=
v
;
}
continue
;
}
/* Blending */
rgb_to_yuv
(
&
y
,
&
u
,
&
v
,
R
,
G
,
B
);
p_dst_y
[
i_x
]
=
(
(
uint16_t
)
y
*
i_trans
+
(
uint16_t
)
p_src1_y
[
i_x
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
if
(
b_even_scanline
&&
i_x
%
2
==
0
)
{
p_dst_u
[
i_x
/
2
]
=
(
(
uint16_t
)
u
*
i_trans
+
(
uint16_t
)
p_src1_u
[
i_x
/
2
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
p_dst_v
[
i_x
/
2
]
=
(
(
uint16_t
)
v
*
i_trans
+
(
uint16_t
)
p_src1_v
[
i_x
/
2
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
}
#undef R
#undef G
#undef B
}
}
#undef MAX_TRANS
#undef TRANS_BITS
return
;
}
static
void
BlendRGBAR24
(
filter_t
*
p_filter
,
picture_t
*
p_dst_pic
,
picture_t
*
p_dst_orig
,
picture_t
*
p_src
,
int
i_x_offset
,
int
i_y_offset
,
int
i_width
,
int
i_height
,
int
i_alpha
)
{
int
i_src1_pitch
,
i_src2_pitch
,
i_dst_pitch
;
uint8_t
*
p_dst
,
*
p_src1
,
*
p_src2
;
int
i_x
,
i_y
,
i_pix_pitch
,
i_trans
,
i_src_pix_pitch
;
i_pix_pitch
=
p_dst_pic
->
p
->
i_pixel_pitch
;
i_dst_pitch
=
p_dst_pic
->
p
->
i_pitch
;
p_dst
=
p_dst_pic
->
p
->
p_pixels
+
i_x_offset
*
i_pix_pitch
+
p_filter
->
fmt_out
.
video
.
i_x_offset
*
i_pix_pitch
+
p_dst_pic
->
p
->
i_pitch
*
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
);
i_src1_pitch
=
p_dst_orig
->
p
->
i_pitch
;
p_src1
=
p_dst_orig
->
p
->
p_pixels
+
i_x_offset
*
i_pix_pitch
+
p_filter
->
fmt_out
.
video
.
i_x_offset
*
i_pix_pitch
+
p_dst_orig
->
p
->
i_pitch
*
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
);
i_src_pix_pitch
=
p_src
->
p
->
i_pixel_pitch
;
i_src2_pitch
=
p_src
->
p
->
i_pitch
;
p_src2
=
p_src
->
p
->
p_pixels
+
p_filter
->
fmt_in
.
video
.
i_x_offset
*
i_pix_pitch
+
p_src
->
p
->
i_pitch
*
p_filter
->
fmt_in
.
video
.
i_y_offset
;
#define MAX_TRANS 255
#define TRANS_BITS 8
/* Draw until we reach the bottom of the subtitle */
for
(
i_y
=
0
;
i_y
<
i_height
;
i_y
++
,
p_dst
+=
i_dst_pitch
,
p_src1
+=
i_src1_pitch
,
p_src2
+=
i_src2_pitch
)
{
/* Draw until we reach the end of the line */
for
(
i_x
=
0
;
i_x
<
i_width
;
i_x
++
)
{
#define R ( p_src2[i_x * i_src_pix_pitch + 0] )
#define G ( p_src2[i_x * i_src_pix_pitch + 1] )
#define B ( p_src2[i_x * i_src_pix_pitch + 2] )
i_trans
=
(
p_src2
[
i_x
*
i_src_pix_pitch
+
3
]
*
i_alpha
)
/
255
;
if
(
!
i_trans
)
{
/* Completely transparent. Don't change pixel */
continue
;
}
else
if
(
i_trans
==
MAX_TRANS
)
{
/* Completely opaque. Completely overwrite underlying pixel */
p_dst
[
i_x
*
i_pix_pitch
+
0
]
=
R
;
p_dst
[
i_x
*
i_pix_pitch
+
1
]
=
G
;
p_dst
[
i_x
*
i_pix_pitch
+
2
]
=
B
;
continue
;
}
/* Blending */
p_dst
[
i_x
*
i_pix_pitch
+
0
]
=
(
R
*
i_trans
+
(
uint16_t
)
p_src1
[
i_x
*
i_pix_pitch
+
0
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
p_dst
[
i_x
*
i_pix_pitch
+
1
]
=
(
G
*
i_trans
+
(
uint16_t
)
p_src1
[
i_x
*
i_pix_pitch
+
1
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
p_dst
[
i_x
*
i_pix_pitch
+
2
]
=
(
B
*
i_trans
+
(
uint16_t
)
p_src1
[
i_x
*
i_pix_pitch
+
2
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
#undef R
#undef G
#undef B
}
}
#undef MAX_TRANS
#undef TRANS_BITS
return
;
}
static
void
BlendRGBAR16
(
filter_t
*
p_filter
,
picture_t
*
p_dst_pic
,
picture_t
*
p_dst_orig
,
picture_t
*
p_src
,
int
i_x_offset
,
int
i_y_offset
,
int
i_width
,
int
i_height
,
int
i_alpha
)
{
int
i_src1_pitch
,
i_src2_pitch
,
i_dst_pitch
;
uint8_t
*
p_dst
,
*
p_src1
,
*
p_src2
;
int
i_x
,
i_y
,
i_pix_pitch
,
i_trans
,
i_src_pix_pitch
;
uint16_t
i_pix
;
i_pix_pitch
=
p_dst_pic
->
p
->
i_pixel_pitch
;
i_dst_pitch
=
p_dst_pic
->
p
->
i_pitch
;
p_dst
=
p_dst_pic
->
p
->
p_pixels
+
i_x_offset
*
i_pix_pitch
+
p_filter
->
fmt_out
.
video
.
i_x_offset
*
i_pix_pitch
+
p_dst_pic
->
p
->
i_pitch
*
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
);
i_src1_pitch
=
p_dst_orig
->
p
->
i_pitch
;
p_src1
=
p_dst_orig
->
p
->
p_pixels
+
i_x_offset
*
i_pix_pitch
+
p_filter
->
fmt_out
.
video
.
i_x_offset
*
i_pix_pitch
+
p_dst_orig
->
p
->
i_pitch
*
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
);
i_src_pix_pitch
=
p_src
->
p
->
i_pixel_pitch
;
i_src2_pitch
=
p_src
->
p
->
i_pitch
;
p_src2
=
p_src
->
p
->
p_pixels
+
p_filter
->
fmt_in
.
video
.
i_x_offset
*
i_pix_pitch
+
p_src
->
p
->
i_pitch
*
p_filter
->
fmt_in
.
video
.
i_y_offset
;
#define MAX_TRANS 255
#define TRANS_BITS 8
/* Draw until we reach the bottom of the subtitle */
for
(
i_y
=
0
;
i_y
<
i_height
;
i_y
++
,
p_dst
+=
i_dst_pitch
,
p_src1
+=
i_src1_pitch
,
p_src2
+=
i_src2_pitch
)
{
/* Draw until we reach the end of the line */
for
(
i_x
=
0
;
i_x
<
i_width
;
i_x
++
)
{
#define R ( p_src2[i_x * i_src_pix_pitch + 0] )
#define G ( p_src2[i_x * i_src_pix_pitch + 1] )
#define B ( p_src2[i_x * i_src_pix_pitch + 2] )
i_trans
=
(
p_src2
[
i_x
*
i_src_pix_pitch
+
3
]
*
i_alpha
)
/
255
;
if
(
!
i_trans
)
{
/* Completely transparent. Don't change pixel */
continue
;
}
else
if
(
i_trans
==
MAX_TRANS
)
{
/* Completely opaque. Completely overwrite underlying pixel */
*
((
uint16_t
*
)(
&
p_dst
[
i_x
*
i_pix_pitch
]))
=
((
R
>>
3
)
<<
11
)
|
((
G
>>
2
)
<<
5
)
|
(
B
>>
3
);
continue
;
}
/* Blending */
i_pix
=
*
((
uint16_t
*
)(
&
p_dst
[
i_x
*
i_pix_pitch
]));
*
((
uint16_t
*
)(
&
p_dst
[
i_x
*
i_pix_pitch
]))
=
(
(
(
(
R
>>
3
)
*
i_trans
+
(
i_pix
>>
11
)
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
)
<<
11
)
|
(
(
(
(
G
>>
2
)
*
i_trans
+
((
i_pix
&
0x07e0
)
>>
5
)
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
)
<<
5
)
|
(
(
(
(
B
>>
3
)
*
i_trans
+
(
i_pix
&
0x001f
)
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
)
);
#undef R
#undef G
#undef B
}
}
#undef MAX_TRANS
#undef TRANS_BITS
return
;
}
static
void
BlendRGBAYUVPacked
(
filter_t
*
p_filter
,
picture_t
*
p_dst_pic
,
picture_t
*
p_dst_orig
,
picture_t
*
p_src
,
int
i_x_offset
,
int
i_y_offset
,
int
i_width
,
int
i_height
,
int
i_alpha
)
{
int
i_src1_pitch
,
i_src2_pitch
,
i_dst_pitch
,
i_src_pix_pitch
;
uint8_t
*
p_dst
,
*
p_src1
,
*
p_src2
;
uint8_t
*
p_trans
;
int
i_x
,
i_y
,
i_pix_pitch
,
i_trans
;
vlc_bool_t
b_even
=
!
((
i_x_offset
+
p_filter
->
fmt_out
.
video
.
i_x_offset
)
%
2
);
int
i_l_offset
=
0
,
i_u_offset
=
0
,
i_v_offset
=
0
;
uint8_t
y
,
u
,
v
;
if
(
p_filter
->
fmt_out
.
video
.
i_chroma
==
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
)
)
{
i_l_offset
=
0
;
i_u_offset
=
1
;
i_v_offset
=
3
;
}
else
if
(
p_filter
->
fmt_out
.
video
.
i_chroma
==
VLC_FOURCC
(
'U'
,
'Y'
,
'V'
,
'Y'
)
)
{
i_l_offset
=
1
;
i_u_offset
=
0
;
i_v_offset
=
2
;
}
else
if
(
p_filter
->
fmt_out
.
video
.
i_chroma
==
VLC_FOURCC
(
'Y'
,
'V'
,
'Y'
,
'U'
)
)
{
i_l_offset
=
0
;
i_u_offset
=
3
;
i_v_offset
=
1
;
}
i_pix_pitch
=
2
;
i_dst_pitch
=
p_dst_pic
->
p
->
i_pitch
;
p_dst
=
p_dst_pic
->
p
->
p_pixels
+
i_x_offset
*
i_pix_pitch
+
p_filter
->
fmt_out
.
video
.
i_x_offset
*
i_pix_pitch
+
p_dst_pic
->
p
->
i_pitch
*
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
);
i_src1_pitch
=
p_dst_orig
->
p
[
Y_PLANE
].
i_pitch
;
p_src1
=
p_dst_orig
->
p
->
p_pixels
+
i_x_offset
*
i_pix_pitch
+
p_filter
->
fmt_out
.
video
.
i_x_offset
*
i_pix_pitch
+
p_dst_orig
->
p
->
i_pitch
*
(
i_y_offset
+
p_filter
->
fmt_out
.
video
.
i_y_offset
);
i_src_pix_pitch
=
p_src
->
p
->
i_pixel_pitch
;
i_src2_pitch
=
p_src
->
p
->
i_pitch
;
p_src2
=
p_src
->
p
->
p_pixels
+
p_filter
->
fmt_in
.
video
.
i_x_offset
*
i_src2_pitch
+
p_src
->
p
->
i_pitch
*
p_filter
->
fmt_in
.
video
.
i_y_offset
;
i_width
=
(
i_width
>>
1
)
<<
1
;
/* Needs to be a multiple of 2 */
#define MAX_TRANS 255
#define TRANS_BITS 8
/* Draw until we reach the bottom of the subtitle */
for
(
i_y
=
0
;
i_y
<
i_height
;
i_y
++
,
p_trans
+=
i_src2_pitch
,
p_dst
+=
i_dst_pitch
,
p_src1
+=
i_src1_pitch
,
p_src2
+=
i_src2_pitch
)
{
/* Draw until we reach the end of the line */
for
(
i_x
=
0
;
i_x
<
i_width
;
i_x
++
,
b_even
=
!
b_even
)
{
#define R ( p_src2[i_x * i_src_pix_pitch + 0] )
#define G ( p_src2[i_x * i_src_pix_pitch + 1] )
#define B ( p_src2[i_x * i_src_pix_pitch + 2] )
i_trans
=
(
p_src2
[
i_x
*
i_src_pix_pitch
+
3
]
*
i_alpha
)
/
255
;
if
(
!
i_trans
)
{
/* Completely transparent. Don't change pixel */
}
else
if
(
i_trans
==
MAX_TRANS
)
{
/* Completely opaque. Completely overwrite underlying pixel */
rgb_to_yuv
(
&
y
,
&
u
,
&
v
,
R
,
G
,
B
);
p_dst
[
i_x
*
2
+
i_l_offset
]
=
y
;
if
(
b_even
)
{
p_dst
[
i_x
*
2
+
i_u_offset
]
=
u
;
p_dst
[
i_x
*
2
+
i_v_offset
]
=
v
;
}
}
else
{
/* Blending */
rgb_to_yuv
(
&
y
,
&
u
,
&
v
,
R
,
G
,
B
);
p_dst
[
i_x
*
2
+
i_l_offset
]
=
(
(
uint16_t
)
y
*
i_trans
+
(
uint16_t
)
p_src1
[
i_x
*
2
+
i_l_offset
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
if
(
b_even
)
{
p_dst
[
i_x
*
2
+
i_u_offset
]
=
(
(
uint16_t
)
u
*
i_trans
+
(
uint16_t
)
p_src1
[
i_x
*
2
+
i_u_offset
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
p_dst
[
i_x
*
2
+
i_v_offset
]
=
(
(
uint16_t
)
v
*
i_trans
+
(
uint16_t
)
p_src1
[
i_x
*
2
+
i_v_offset
]
*
(
MAX_TRANS
-
i_trans
)
)
>>
TRANS_BITS
;
}
}
}
}
#undef MAX_TRANS
#undef TRANS_BITS
return
;
}
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