1 /*****************************************************************************
2  * i420_10_P010.c : Planar YUV 4:2:0 to SemiPlanar P010 4:2:0
3  *****************************************************************************
4  * Copyright (C) 2016 VLC authors and VideoLAN
5  *
6  * Authors: Steve Lhomme <robux4@videolabs.io>
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
22 
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_filter.h>
34 #include <vlc_picture.h>
35 #include "copy.h"
36 
37 /*****************************************************************************
38  * Local and extern prototypes.
39  *****************************************************************************/
40 static void I420_10_P010( filter_t *, picture_t *, picture_t * );
41 static picture_t *I420_10_P010_Filter( filter_t *, picture_t * );
42 
43 struct filter_sys_t
44 {
45     copy_cache_t cache;
46 };
47 
48 /*****************************************************************************
49  * Create: allocate a chroma function
50  *****************************************************************************
51  * This function allocates and initializes a chroma function
52  *****************************************************************************/
Create(vlc_object_t * p_this)53 static int Create( vlc_object_t *p_this )
54 {
55     filter_t *p_filter = (filter_t *)p_this;
56 
57     if ( p_filter->fmt_out.video.i_chroma != VLC_CODEC_P010 )
58         return -1;
59 
60     /* video must be even, because 4:2:0 is subsampled by 2 in both ways */
61     if( p_filter->fmt_in.video.i_width  & 1
62      || p_filter->fmt_in.video.i_height & 1 )
63     {
64         return -1;
65     }
66 
67     /* resizing not supported */
68     if( p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width !=
69             p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width
70        || p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height !=
71             p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height
72        || p_filter->fmt_in.video.orientation != p_filter->fmt_out.video.orientation )
73         return -1;
74 
75     if ( p_filter->fmt_in.video.i_chroma != VLC_CODEC_I420_10L)
76         return -1;
77 
78     filter_sys_t *p_sys = vlc_obj_malloc( VLC_OBJECT( p_filter ),
79                                           sizeof(*p_sys) );
80     if (!p_sys)
81          return VLC_ENOMEM;
82 
83     p_filter->pf_video_filter = I420_10_P010_Filter;
84     CopyInitCache( &p_sys->cache, p_filter->fmt_in.video.i_x_offset +
85                                   p_filter->fmt_in.video.i_visible_width );
86     p_filter->p_sys = p_sys;
87 
88     return 0;
89 }
90 
Delete(vlc_object_t * p_this)91 static void Delete(vlc_object_t *p_this)
92 {
93     filter_t *p_filter = (filter_t *)p_this;
94     filter_sys_t *p_sys = p_filter->p_sys;
95     CopyCleanCache( &p_sys->cache );
96 }
97 
98 /* Following functions are local */
VIDEO_FILTER_WRAPPER(I420_10_P010)99 VIDEO_FILTER_WRAPPER( I420_10_P010 )
100 
101 /*****************************************************************************
102  * planar I420 4:2:0 10-bit Y:U:V to semiplanar P010 10/16-bit 4:2:0 Y:UV
103  *****************************************************************************/
104 static void I420_10_P010( filter_t *p_filter, picture_t *p_src,
105                                            picture_t *p_dst )
106 {
107     p_dst->format.i_x_offset = p_src->format.i_x_offset;
108     p_dst->format.i_y_offset = p_src->format.i_y_offset;
109 
110     const size_t pitch[3] = {
111         p_src->p[Y_PLANE].i_pitch,
112         p_src->p[U_PLANE].i_pitch,
113         p_src->p[V_PLANE].i_pitch,
114     };
115 
116     const uint8_t *plane[3] = {
117         (uint8_t*)p_src->p[Y_PLANE].p_pixels,
118         (uint8_t*)p_src->p[U_PLANE].p_pixels,
119         (uint8_t*)p_src->p[V_PLANE].p_pixels,
120     };
121 
122     CopyFromI420_10ToP010( p_dst, plane, pitch,
123                         p_src->format.i_y_offset + p_src->format.i_visible_height,
124                         &p_filter->p_sys->cache );
125 }
126 
127 /*****************************************************************************
128  * Module descriptor
129  *****************************************************************************/
130 vlc_module_begin ()
131     set_description( N_("YUV 10-bits planar to semiplanar 10-bits conversions") )
132     set_capability( "video converter", 1 )
133     set_callbacks( Create, Delete )
134 vlc_module_end ()
135