1 /*****************************************************************************
2 * i420_nv12.c : Planar YUV 4:2:0 to SemiPlanar NV12 4:2:0
3 *****************************************************************************
4 * Copyright (C) 2016 VLC authors and VideoLAN
6 * Authors: Steve Lhomme <robux4@videolabs.io>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_filter.h>
34 #include <vlc_picture.h>
42 #define GET_PITCHES( pic ) { \
43 pic->p[Y_PLANE].i_pitch, \
44 pic->p[U_PLANE].i_pitch, \
45 pic->p[V_PLANE].i_pitch \
48 #define GET_PLANES( pic ) { \
49 pic->p[Y_PLANE].p_pixels, \
50 pic->p[U_PLANE].p_pixels, \
51 pic->p[V_PLANE].p_pixels \
54 /*****************************************************************************
55 * planar I420 4:2:0 Y:U:V to planar NV12 4:2:0 Y:UV
56 *****************************************************************************/
57 static void I420_NV12( filter_t
*p_filter
, picture_t
*p_src
,
60 filter_sys_t
*p_sys
= p_filter
->p_sys
;
61 p_dst
->format
.i_x_offset
= p_src
->format
.i_x_offset
;
62 p_dst
->format
.i_y_offset
= p_src
->format
.i_y_offset
;
63 const size_t pitches
[] = GET_PITCHES( p_src
);
64 const uint8_t *planes
[] = GET_PLANES( p_src
);
66 Copy420_P_to_SP( p_dst
, planes
, pitches
,
67 p_src
->format
.i_y_offset
+ p_src
->format
.i_visible_height
,
71 /*****************************************************************************
72 * planar YV12 4:2:0 Y:V:U to planar NV12 4:2:0 Y:UV
73 *****************************************************************************/
74 static void YV12_NV12( filter_t
*p_filter
, picture_t
*p_src
,
77 picture_SwapUV( p_src
);
78 I420_NV12( p_filter
, p_src
, p_dst
);
81 static void NV12_I420( filter_t
*p_filter
, picture_t
*p_src
,
84 filter_sys_t
*p_sys
= p_filter
->p_sys
;
85 p_dst
->format
.i_x_offset
= p_src
->format
.i_x_offset
;
86 p_dst
->format
.i_y_offset
= p_src
->format
.i_y_offset
;
87 const size_t pitches
[] = GET_PITCHES( p_src
);
88 const uint8_t *planes
[] = GET_PLANES( p_src
);
90 Copy420_SP_to_P( p_dst
, planes
, pitches
,
91 p_src
->format
.i_y_offset
+ p_src
->format
.i_visible_height
,
95 static void NV12_YV12( filter_t
*p_filter
, picture_t
*p_src
,
98 NV12_I420( p_filter
, p_src
, p_dst
);
99 picture_SwapUV( p_dst
);
102 static void I42010B_P010( filter_t
*p_filter
, picture_t
*p_src
,
105 filter_sys_t
*p_sys
= p_filter
->p_sys
;
106 p_dst
->format
.i_x_offset
= p_src
->format
.i_x_offset
;
107 p_dst
->format
.i_y_offset
= p_src
->format
.i_y_offset
;
108 const size_t pitches
[] = GET_PITCHES( p_src
);
109 const uint8_t *planes
[] = GET_PLANES( p_src
);
111 Copy420_16_P_to_SP( p_dst
, planes
, pitches
,
112 p_src
->format
.i_y_offset
+ p_src
->format
.i_visible_height
,
116 static void P010_I42010B( filter_t
*p_filter
, picture_t
*p_src
,
119 filter_sys_t
*p_sys
= p_filter
->p_sys
;
120 p_dst
->format
.i_x_offset
= p_src
->format
.i_x_offset
;
121 p_dst
->format
.i_y_offset
= p_src
->format
.i_y_offset
;
122 const size_t pitches
[] = GET_PITCHES( p_src
);
123 const uint8_t *planes
[] = GET_PLANES( p_src
);
125 Copy420_16_SP_to_P( p_dst
, planes
, pitches
,
126 p_src
->format
.i_y_offset
+ p_src
->format
.i_visible_height
,
130 /* Following functions are local */
131 static void Delete(filter_t
*p_filter
)
133 filter_sys_t
*p_sys
= p_filter
->p_sys
;
134 CopyCleanCache( &p_sys
->cache
);
137 VIDEO_FILTER_WRAPPER_CLOSE( I420_NV12
, Delete
)
138 VIDEO_FILTER_WRAPPER_CLOSE( YV12_NV12
, Delete
)
139 VIDEO_FILTER_WRAPPER_CLOSE( NV12_I420
, Delete
)
140 VIDEO_FILTER_WRAPPER_CLOSE( NV12_YV12
, Delete
)
141 VIDEO_FILTER_WRAPPER_CLOSE( I42010B_P010
, Delete
)
142 VIDEO_FILTER_WRAPPER_CLOSE( P010_I42010B
, Delete
)
144 /*****************************************************************************
145 * Create: allocate a chroma function
146 *****************************************************************************
147 * This function allocates and initializes a chroma function
148 *****************************************************************************/
149 static int Create( filter_t
*p_filter
)
151 /* video must be even, because 4:2:0 is subsampled by 2 in both ways */
152 if( p_filter
->fmt_in
.video
.i_width
& 1
153 || p_filter
->fmt_in
.video
.i_height
& 1 )
156 /* resizing not supported */
157 if( p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
!=
158 p_filter
->fmt_out
.video
.i_x_offset
+ p_filter
->fmt_out
.video
.i_visible_width
159 || p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
!=
160 p_filter
->fmt_out
.video
.i_y_offset
+ p_filter
->fmt_out
.video
.i_visible_height
161 || p_filter
->fmt_in
.video
.orientation
!= p_filter
->fmt_out
.video
.orientation
)
164 vlc_fourcc_t infcc
= p_filter
->fmt_in
.video
.i_chroma
;
165 vlc_fourcc_t outfcc
= p_filter
->fmt_out
.video
.i_chroma
;
166 uint8_t pixel_bytes
= 1;
172 if( outfcc
!= VLC_CODEC_NV12
)
174 p_filter
->ops
= &I420_NV12_ops
;
178 if( outfcc
!= VLC_CODEC_NV12
)
180 p_filter
->ops
= &YV12_NV12_ops
;
187 p_filter
->ops
= &NV12_I420_ops
;
190 p_filter
->ops
= &NV12_YV12_ops
;
197 case VLC_CODEC_I420_10L
:
198 if( outfcc
!= VLC_CODEC_P010
)
201 p_filter
->ops
= &I42010B_P010_ops
;
205 if( outfcc
!= VLC_CODEC_I420_10L
)
208 p_filter
->ops
= &P010_I42010B_ops
;
215 filter_sys_t
*p_sys
= vlc_obj_malloc( VLC_OBJECT( p_filter
),
220 if( CopyInitCache( &p_sys
->cache
, ( p_filter
->fmt_in
.video
.i_x_offset
+
221 p_filter
->fmt_in
.video
.i_visible_width
) * pixel_bytes
) )
224 p_filter
->p_sys
= p_sys
;
229 /*****************************************************************************
231 *****************************************************************************/
233 set_description( N_("YUV planar to semiplanar conversions") )
234 set_callback_video_converter( Create
, 160 )