]> git.sesse.net Git - mlt/blob - src/modules/vid.stab/common.c
Work around for vid.stab chroma skew when using 4:2:2
[mlt] / src / modules / vid.stab / common.c
1 /*
2  * common.c
3  * Copyright (C) 2014 Brian Matherly <pez4brian@yahoo.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19 #include <framework/mlt.h>
20 #include <vid.stab/libvidstab.h>
21 #include "common.h"
22
23 mlt_image_format validate_format( mlt_image_format format )
24 {
25         switch( format )
26         {
27         case mlt_image_rgb24a:
28         case mlt_image_rgb24:
29                 return mlt_image_rgb24;
30         case mlt_image_yuv420p:
31                 return mlt_image_yuv420p;
32         default:
33         case mlt_image_none:
34         case mlt_image_yuv422:
35         case mlt_image_opengl:
36         case mlt_image_glsl:
37         case mlt_image_glsl_texture:
38                 return mlt_image_yuv422;
39         }
40 }
41
42 /** Convert an MLT image to one that can be used by VS.
43  * Use free_vsimage() when done with the resulting image.
44  */
45
46 VSPixelFormat mltimage_to_vsimage( mlt_image_format mlt_format, int width, int height, uint8_t* mlt_img, uint8_t** vs_img )
47 {
48         switch( mlt_format )
49         {
50         case mlt_image_rgb24:
51                 // Convert packed RGB24 to planar YUV444
52                 // Note: vid.stab 0.98 does not seem to support PF_RGB24
53                 {
54                         *vs_img = mlt_pool_alloc( width * height * 3 );
55                         int y, u, v, r, g, b;
56                         int total = width * height + 1;
57                         uint8_t* yp = *vs_img;
58                         uint8_t* up = yp + ( width * height );
59                         uint8_t* vp = up + ( width * height );
60
61                         while( --total )
62                         {
63                                 r = *mlt_img++;
64                                 g = *mlt_img++;
65                                 b = *mlt_img++;
66                                 RGB2YUV_601_SCALED(r, g, b, y, u, v);
67                                 *yp++ = y;
68                                 *up++ = u;
69                                 *vp++ = v;
70                         }
71
72                         return PF_YUV444P;
73                 }
74         case mlt_image_yuv420p:
75                 // This format maps with no conversion
76                 {
77                         *vs_img = mlt_img;
78                         return PF_YUV420P;
79                 }
80         case mlt_image_yuv422:
81                 // Convert packed YUV422 to planar YUV444
82                 // Note: vid.stab 0.98 seems to suffer chroma bleeding
83                 // when using PF_YUV422P - which is why PF_YUV444P is used.
84                 {
85                         *vs_img = mlt_pool_alloc( width * height * 3 );
86                         uint8_t* yp = *vs_img;
87                         uint8_t* up = yp + ( width * height );
88                         uint8_t* vp = up + ( width * height );
89                         int i, j, n = width / 2 + 1;
90
91                         for ( i = 0; i < height; i++ )
92                         {
93                                 j = n;
94                                 while ( --j )
95                                 {
96                                         *yp++ = mlt_img[0];
97                                         *up++ = mlt_img[1];
98                                         *vp++ = mlt_img[3];
99                                         *yp++ = mlt_img[2];
100                                         *up++ = mlt_img[1];
101                                         *vp++ = mlt_img[3];
102                                         mlt_img += 4;
103                                 }
104                                 if ( width % 2 )
105                                 {
106                                         *yp++ = mlt_img[0];
107                                         *up++ = mlt_img[1];
108                                         *vp++ = (mlt_img - 4)[3];
109                                         mlt_img += 2;
110                                 }
111                         }
112
113                         return PF_YUV444P;
114                 }
115         default:
116                 return PF_NONE;
117         }
118 }
119
120 /** Convert a VS image back to the MLT image it originally came from in mltimage_to_vsimage().
121  */
122
123 void vsimage_to_mltimage( uint8_t* vs_img, uint8_t* mlt_img, mlt_image_format mlt_format, int width, int height )
124 {
125         switch( mlt_format )
126         {
127         case mlt_image_rgb24:
128                 // Convert packet YUV444 to packed RGB24.
129                 {
130                         int y, u, v, r, g, b;
131                         int total = width * height + 1;
132                         uint8_t* yp = vs_img;
133                         uint8_t* up = yp + ( width * height );
134                         uint8_t* vp = up + ( width * height );
135
136                         while( --total )
137                         {
138                                 y = *yp++;
139                                 u = *up++;
140                                 v = *vp++;
141                                 YUV2RGB_601_SCALED( y, u, v, r, g, b );
142                                 *mlt_img++ = r;
143                                 *mlt_img++ = g;
144                                 *mlt_img++ = b;
145                         }
146                 }
147                 break;
148         case mlt_image_yuv420p:
149                 // This format was never converted
150                 break;
151         case mlt_image_yuv422:
152                 // Convert planar YUV444 to packed YUV422
153                 {
154                         uint8_t* yp = vs_img;
155                         uint8_t* up = yp + ( width * height );
156                         uint8_t* vp = up + ( width * height );
157                         int i, j, n = width / 2 + 1;
158
159                         for ( i = 0; i < height; i++ )
160                         {
161                                 j = n;
162                                 while ( --j )
163                                 {
164                                         *mlt_img++ = yp[0];
165                                         *mlt_img++ = ( up[0] + up[1] ) >> 1;
166                                         *mlt_img++ = yp[1];
167                                         *mlt_img++ = ( vp[0] + vp[1] ) >> 1;
168                                         yp += 2;
169                                         up += 2;
170                                         vp += 2;
171                                 }
172                                 if ( width % 2 )
173                                 {
174                                         *mlt_img++ = yp[0];
175                                         *mlt_img++ = up[0];
176                                         yp += 1;
177                                         up += 1;
178                                         vp += 1;
179                                 }
180                         }
181                 }
182                 break;
183         default:
184                 break;
185         }
186 }
187
188 /** Free an image allocated by mltimage_to_vsimage().
189  */
190
191 void free_vsimage( uint8_t* vs_img, VSPixelFormat format )
192 {
193         if( format != PF_YUV420P )
194         {
195                 mlt_pool_release( vs_img );
196         }
197 }
198
199 /** Compare two VSMotionDetectConfig structures.
200  * Return 1 if they are different. 0 if they are the same.
201  */
202
203 int compare_motion_config( VSMotionDetectConfig* a, VSMotionDetectConfig* b )
204 {
205         if( a->shakiness != b->shakiness ||
206                 a->accuracy != b->accuracy ||
207                 a->stepSize != b->stepSize ||
208                 // Skip: Deprecated
209                 // a->algo != b->algo ||
210                 a->virtualTripod != b->virtualTripod ||
211                 a->show != b->show ||
212                 // Skip: inconsequential?
213                 // a->modName != b->modName ||
214                 a->contrastThreshold != b->contrastThreshold )
215         {
216                 return 1;
217         }
218         return 0;
219 }
220
221 /** Compare two VSTransformConfig structures.
222  * Return 1 if they are different. 0 if they are the same.
223  */
224
225 int compare_transform_config( VSTransformConfig* a, VSTransformConfig* b )
226 {
227         if( a->relative != b->relative ||
228                 a->smoothing != b->smoothing ||
229                 a->crop != b->crop ||
230                 a->invert != b->invert ||
231                 a->zoom != b->zoom ||
232                 a->optZoom != b->optZoom ||
233                 a->zoomSpeed != b->zoomSpeed ||
234                 a->interpolType != b->interpolType ||
235                 a->maxShift != b->maxShift ||
236                 a->maxAngle != b->maxAngle ||
237                 // Skip: inconsequential?
238                 // a->modName != b->modName ||
239                 // Skip: unused?
240                 // a->verbose != b->verbose ||
241                 a->simpleMotionCalculation != b->simpleMotionCalculation ||
242                 // Skip: unused?
243                 // a->storeTransforms != b->storeTransforms ||
244                 a->smoothZoom != b->smoothZoom ||
245                 a->camPathAlgo != b->camPathAlgo )
246         {
247                 return 1;
248         }
249         return 0;
250 }
251