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