• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2013 Wim Taymans <wim.taymans@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23 
24 #include <string.h>
25 #include <stdio.h>
26 
27 #include "video-orc.h"
28 #include "video-format.h"
29 #include <gst/video/video-enumtypes.h>
30 
31 /**
32  * SECTION:gstvideochroma
33  * @title: GstVideoChromaResample
34  * @short_description: Functions and utility object for operating on chroma video planes
35  *
36  * The functions gst_video_chroma_from_string() and gst_video_chroma_to_string() convert
37  * between #GstVideoChromaSite and string descriptions.
38  *
39  * #GstVideoChromaResample is a utility object for resampling chroma planes
40  * and converting between different chroma sampling sitings.
41  *
42  */
43 
44 #ifndef GST_DISABLE_GST_DEBUG
45 #define GST_CAT_DEFAULT ensure_debug_category()
46 static GstDebugCategory *
ensure_debug_category(void)47 ensure_debug_category (void)
48 {
49   static gsize cat_gonce = 0;
50 
51   if (g_once_init_enter (&cat_gonce)) {
52     gsize cat_done;
53 
54     cat_done = (gsize) _gst_debug_category_new ("video-chroma", 0,
55         "video-chroma object");
56 
57     g_once_init_leave (&cat_gonce, cat_done);
58   }
59 
60   return (GstDebugCategory *) cat_gonce;
61 }
62 #else
63 #define ensure_debug_category() /* NOOP */
64 #endif /* GST_DISABLE_GST_DEBUG */
65 
66 typedef struct
67 {
68   const gchar *name;
69   GstVideoChromaSite site;
70 } ChromaSiteInfo;
71 
72 static const ChromaSiteInfo chromasite[] = {
73   {"jpeg", GST_VIDEO_CHROMA_SITE_JPEG},
74   {"mpeg2", GST_VIDEO_CHROMA_SITE_MPEG2},
75   {"dv", GST_VIDEO_CHROMA_SITE_DV},
76   {"alt-line", GST_VIDEO_CHROMA_SITE_ALT_LINE},
77   {"cosited", GST_VIDEO_CHROMA_SITE_COSITED},
78 };
79 
80 /**
81  * gst_video_chroma_from_string:
82  * @s: a chromasite string
83  *
84  * Convert @s to a #GstVideoChromaSite
85  *
86  * Deprecated: 1.20: Use gst_video_chroma_site_from_string() instead.
87  *
88  * Returns: a #GstVideoChromaSite or %GST_VIDEO_CHROMA_SITE_UNKNOWN when @s does
89  * not contain a valid chroma description.
90  */
91 GstVideoChromaSite
gst_video_chroma_from_string(const gchar * s)92 gst_video_chroma_from_string (const gchar * s)
93 {
94   return gst_video_chroma_site_from_string (s);
95 }
96 
97 /**
98  * gst_video_chroma_site_from_string:
99  * @s: a chromasite string
100  *
101  * Convert @s to a #GstVideoChromaSite
102  *
103  * Returns: a #GstVideoChromaSite or %GST_VIDEO_CHROMA_SITE_UNKNOWN when @s does
104  * not contain a valid chroma-site description.
105  *
106  * Since: 1.20
107  */
108 GstVideoChromaSite
gst_video_chroma_site_from_string(const gchar * s)109 gst_video_chroma_site_from_string (const gchar * s)
110 {
111   gint i;
112   gchar **split;
113   gchar **iter;
114   GstVideoChromaSite ret = GST_VIDEO_CHROMA_SITE_UNKNOWN;
115   GFlagsClass *klass;
116 
117   for (i = 0; i < G_N_ELEMENTS (chromasite); i++) {
118     if (g_str_equal (chromasite[i].name, s))
119       return chromasite[i].site;
120   }
121 
122   klass = (GFlagsClass *) g_type_class_ref (GST_TYPE_VIDEO_CHROMA_SITE);
123   split = g_strsplit (s, "+", 0);
124   for (iter = split; *iter; iter++) {
125     GFlagsValue *value;
126 
127     value = g_flags_get_value_by_nick (klass, *iter);
128     if (!value) {
129       ret = GST_VIDEO_CHROMA_SITE_UNKNOWN;
130       goto out;
131     }
132 
133     ret |= value->value;
134   }
135 
136 out:
137   g_type_class_unref (klass);
138   g_strfreev (split);
139 
140   /* Doesn't make sense */
141   if ((ret & GST_VIDEO_CHROMA_SITE_NONE) != 0 &&
142       ret != GST_VIDEO_CHROMA_SITE_NONE)
143     return GST_VIDEO_CHROMA_SITE_UNKNOWN;
144 
145   return ret;
146 }
147 
148 /**
149  * gst_video_chroma_to_string:
150  * @site: a #GstVideoChromaSite
151  *
152  * Converts @site to its string representation.
153  *
154  * Deprecated: 1.20: Use gst_video_chroma_site_to_string() instead.
155  *
156  * Returns: a string describing @site.
157  */
158 const gchar *
gst_video_chroma_to_string(GstVideoChromaSite site)159 gst_video_chroma_to_string (GstVideoChromaSite site)
160 {
161   gint i;
162   for (i = 0; i < G_N_ELEMENTS (chromasite); i++) {
163     if (chromasite[i].site == site)
164       return chromasite[i].name;
165   }
166   return NULL;
167 }
168 
169 /**
170  * gst_video_chroma_site_to_string:
171  * @site: a #GstVideoChromaSite
172  *
173  * Converts @site to its string representation.
174  *
175  * Returns: (transfer full) (nullable): a string representation of @site
176  *          or %NULL if @site contains undefined value or
177  *          is equal to %GST_VIDEO_CHROMA_SITE_UNKNOWN
178  *
179  * Since: 1.20
180  */
181 gchar *
gst_video_chroma_site_to_string(GstVideoChromaSite site)182 gst_video_chroma_site_to_string (GstVideoChromaSite site)
183 {
184   gint i;
185   GString *str;
186   GFlagsValue *value;
187   GFlagsClass *klass;
188 
189   /* return null string for GST_VIDEO_CHROMA_SITE_UNKNOWN */
190   if (site == 0)
191     return NULL;
192 
193   for (i = 0; i < G_N_ELEMENTS (chromasite); i++) {
194     if (chromasite[i].site == site)
195       return g_strdup (chromasite[i].name);
196   }
197 
198   /* Doesn't make sense */
199   if ((site & GST_VIDEO_CHROMA_SITE_NONE) != 0 &&
200       site != GST_VIDEO_CHROMA_SITE_NONE)
201     return NULL;
202 
203   /* Construct new string */
204   klass = (GFlagsClass *) g_type_class_ref (GST_TYPE_VIDEO_CHROMA_SITE);
205   str = g_string_new (NULL);
206   while (site != GST_VIDEO_CHROMA_SITE_UNKNOWN &&
207       (value = g_flags_get_first_value (klass, site))) {
208     if (str->len > 0)
209       g_string_append (str, "+");
210 
211     g_string_append (str, value->value_nick);
212     site &= ~value->value;
213   }
214   g_type_class_unref (klass);
215 
216   /* This means given chroma-site has unknown value */
217   if (site != 0)
218     return g_string_free (str, TRUE);
219 
220   return g_string_free (str, FALSE);
221 }
222 
223 struct _GstVideoChromaResample
224 {
225   GstVideoChromaMethod method;
226   GstVideoChromaSite site;
227   GstVideoChromaFlags flags;
228   GstVideoFormat format;
229   gint h_factor, v_factor;
230   guint n_lines;
231   gint offset;
232   void (*h_resample) (GstVideoChromaResample * resample, gpointer pixels,
233       gint width);
234   void (*v_resample) (GstVideoChromaResample * resample, gpointer lines[],
235       gint width);
236 };
237 
238 #define PR(i)          (p[2 + 4 * (i)])
239 #define PB(i)          (p[3 + 4 * (i)])
240 
241 #define PR0(i)         (l0[2 + 4 * (i)])
242 #define PR1(i)         (l1[2 + 4 * (i)])
243 #define PR2(i)         (l2[2 + 4 * (i)])
244 #define PR3(i)         (l3[2 + 4 * (i)])
245 #define PB0(i)         (l0[3 + 4 * (i)])
246 #define PB1(i)         (l1[3 + 4 * (i)])
247 #define PB2(i)         (l2[3 + 4 * (i)])
248 #define PB3(i)         (l3[3 + 4 * (i)])
249 
250 #define FILT_1_1(a,b)          ((a) + (b) + 1) >> 1
251 #define FILT_1_3_3_1(a,b,c,d)  ((a) + 3*((b)+(c)) + (d) + 4) >> 3
252 
253 #define FILT_3_1(a,b)          (3*(a) + (b) + 2) >> 2
254 #define FILT_1_3(a,b)          ((a) + 3*(b) + 2) >> 2
255 #define FILT_1_2_1(a,b,c)      ((a) + 2*(b) + (c) + 2) >> 2
256 
257 #define FILT_7_1(a,b)          (7*(a) + 1*(b) + 4) >> 3
258 #define FILT_1_7(a,b)          (1*(a) + 7*(b) + 4) >> 3
259 
260 #define FILT_5_3(a,b)          (5*(a) + 3*(b) + 4) >> 3
261 #define FILT_3_5(a,b)          (3*(a) + 5*(b) + 4) >> 3
262 
263 #define FILT_10_3_2_1(a,b,c,d)      (10*(a) + 3*(b) + 2*(c) + (d) + 8) >> 16
264 #define FILT_1_2_3_10(a,b,c,d)      ((a) + 2*(b) + 3*(c) + 10*(d) + 8) >> 16
265 #define FILT_1_2_3_4_3_2_1(a,b,c,d,e,f,g) ((a) + 2*((b)+(f)) + 3*((c)+(e)) + 4*(d) + (g) + 8) >> 16
266 
267 /* 2x horizontal upsampling without cositing
268  *
269  * +----------    a
270  * | +------ (3*a +   b + 2) >> 2
271  * | | +---- (  a + 3*b + 2) >> 2
272  * v v v
273  * O-O-O-O-
274  *  x   x
275  *  a   b
276  */
277 #define MAKE_UPSAMPLE_H2(name,type)                                     \
278 static void                                                             \
279 video_chroma_up_h2_##name (GstVideoChromaResample *resample,            \
280     gpointer pixels, gint width)                                        \
281 {                                                                       \
282   type *p = pixels;                                                     \
283   gint i;                                                               \
284   type tr0, tr1;                                                        \
285   type tb0, tb1;                                                        \
286                                                                         \
287   tr1 = PR(0);                                                          \
288   tb1 = PB(0);                                                          \
289   for (i = 1; i < width - 1; i += 2) {                                  \
290     tr0 = tr1, tr1 = PR(i+1);                                           \
291     tb0 = tb1, tb1 = PB(i+1);                                           \
292                                                                         \
293     PR(i) = FILT_3_1 (tr0, tr1);                                        \
294     PB(i) = FILT_3_1 (tb0, tb1);                                        \
295     PR(i+1) = FILT_1_3 (tr0, tr1);                                      \
296     PB(i+1) = FILT_1_3 (tb0, tb1);                                      \
297   }                                                                     \
298 }
299 
300 /* 2x vertical upsampling without cositing
301  *
302  *   O--O--O-  <---- a
303  * a x  x  x
304  *   O--O--O-  <---- (3*a +   b + 2) >> 2
305  *   O--O--O-  <-----(  a + 3*b + 2) >> 2
306  * b x  x  x
307  *   O--O--O-  <---- b
308  */
309 #define MAKE_UPSAMPLE_V2(name,type)                                     \
310 static void                                                             \
311 video_chroma_up_v2_##name (GstVideoChromaResample *resample,            \
312     gpointer lines[], gint width)                                       \
313 {                                                                       \
314   type *l0 = lines[0];                                                  \
315   type *l1 = lines[1];                                                  \
316                                                                         \
317   if (resample->h_resample) {                                           \
318     resample->h_resample (resample, l0, width);                         \
319     if (l0 != l1)                                                       \
320       resample->h_resample (resample, l1, width);                       \
321   }                                                                     \
322   if (l0 != l1) {                                                       \
323     type *d0 = l0;							\
324     type *d1 = l1;							\
325     video_orc_chroma_up_v2_##name (d0, d1, l0, l1, width);              \
326   }                                                                     \
327 }
328 /* 2x vertical upsampling interlaced without cositing
329  *
330  *   even           odd
331  *
332  *   O--O--O--------------- <---  a
333  * a x  x  x
334  *   --------------O--O--O- <---  c
335  *   O--O--O--------------- <--- (5*a + 3*b + 4) >> 3
336  * c               x  x  x
337  *   --------------O--O--O- <--- (7*c +   d + 4) >> 3
338  *   O--O--O--------------- <--- (  a + 7*b + 4) >> 3
339  * b x  x  x
340  *   --------------O--O--O- <--- (3*c + 5*d + 4) >> 3
341  *   O--O--O---------------
342  * d               x  x  x
343  *   --------------O--O--O-
344  */
345 #define MAKE_UPSAMPLE_VI2(name,type)                                    \
346 static void                                                             \
347 video_chroma_up_vi2_##name (GstVideoChromaResample *resample,           \
348     gpointer lines[], gint width)                                       \
349 {                                                                       \
350   gint i;                                                               \
351   type *l0 = lines[0];                                                  \
352   type *l1 = lines[1];                                                  \
353   type *l2 = lines[2];                                                  \
354   type *l3 = lines[3];                                                  \
355   type tr0, tr1, tr2, tr3;                                              \
356   type tb0, tb1, tb2, tb3;                                              \
357                                                                         \
358   if (resample->h_resample) {                                           \
359     if (l0 != l1) {                                                     \
360       resample->h_resample (resample, l0, width);                       \
361       resample->h_resample (resample, l1, width);                       \
362     }                                                                   \
363     if (l2 != l3) {                                                     \
364       resample->h_resample (resample, l2, width);                       \
365       resample->h_resample (resample, l3, width);                       \
366     }                                                                   \
367   }                                                                     \
368   if (l0 != l1 && l2 != l3) {                                           \
369     for (i = 0; i < width; i++) {                                       \
370       tr0 = PR0(i), tr2 = PR2(i);                                       \
371       tb0 = PB0(i), tb2 = PB2(i);                                       \
372       tr1 = PR1(i), tr3 = PR3(i);                                       \
373       tb1 = PB1(i), tb3 = PB3(i);                                       \
374                                                                         \
375       PR0(i) = FILT_5_3 (tr0, tr2);                                     \
376       PB0(i) = FILT_5_3 (tb0, tb2);                                     \
377       PR1(i) = FILT_7_1 (tr1, tr3);                                     \
378       PB1(i) = FILT_7_1 (tb1, tb3);                                     \
379       PR2(i) = FILT_1_7 (tr0, tr2);                                     \
380       PB2(i) = FILT_1_7 (tb0, tb2);                                     \
381       PR3(i) = FILT_3_5 (tr1, tr3);                                     \
382       PB3(i) = FILT_3_5 (tb1, tb3);                                     \
383     }                                                                   \
384   }                                                                     \
385 }
386 
387 /* 2x horizontal downsampling without cositing
388  *
389  *  +------ (a + b+ 1) >> 1
390  *  |
391  *  v
392  * -O---O--
393  * x x x x
394  * a b c d
395  */
396 #define MAKE_DOWNSAMPLE_H2_ORC(name,type)                               \
397 static void                                                             \
398 video_chroma_down_h2_##name (GstVideoChromaResample *resample,          \
399     gpointer pixels, gint width)                                        \
400 {                                                                       \
401   type *p = pixels;                                                     \
402   type *d = p;								\
403                                                                         \
404   video_orc_chroma_down_h2_##name (d, p, width / 2);                    \
405 }
406 
407 #define MAKE_DOWNSAMPLE_H2(name,type)                                   \
408 static void                                                             \
409 video_chroma_down_h2_##name (GstVideoChromaResample *resample,          \
410     gpointer pixels, gint width)                                        \
411 {                                                                       \
412   type *p = pixels;                                                     \
413   gint i;                                                               \
414                                                                         \
415   for (i = 0; i < width - 1; i += 2) {                                  \
416     type tr0 = PR(i), tr1 = PR(i+1);                                    \
417     type tb0 = PB(i), tb1 = PB(i+1);                                    \
418                                                                         \
419     PR(i) = FILT_1_1 (tr0, tr1);                                        \
420     PB(i) = FILT_1_1 (tb0, tb1);                                        \
421   }                                                                     \
422 }
423 /* 2x vertical downsampling without cositing
424  *
425  * a x--x--x-
426  *   O  O  O <---- (a + b + 1) >> 1
427  * b x--x--x-
428  * c x--x--x-
429  *   O  O  O
430  * d x--x--x-
431  */
432 #define MAKE_DOWNSAMPLE_V2(name,type)                                   \
433 static void                                                             \
434 video_chroma_down_v2_##name (GstVideoChromaResample *resample,          \
435     gpointer lines[], gint width)                                       \
436 {                                                                       \
437   type *l0 = lines[0];                                                  \
438   type *l1 = lines[1];                                                  \
439                                                                         \
440   if (l0 != l1) {							\
441     type *d0 = l0;							\
442     video_orc_chroma_down_v2_##name (d0, l0, l1, width);                \
443   }									\
444                                                                         \
445   if (resample->h_resample)                                             \
446     resample->h_resample (resample, l0, width);                         \
447 }
448 /* 2x vertical downsampling interlaced without cositing
449  *
450  *   even           odd
451  *
452  * a x--x--x---------------
453  *   O  O  O                <---
454  * b --------------x--x--x-
455  * c x--x--x---------------
456  *                 O  O  O  <---
457  * d --------------x--x--x-
458  */
459 #define MAKE_DOWNSAMPLE_VI2(name,type)                                  \
460 static void                                                             \
461 video_chroma_down_vi2_##name (GstVideoChromaResample *resample,         \
462     gpointer lines[], gint width)                                       \
463 {                                                                       \
464   /* FIXME */                                                           \
465   if (resample->h_resample)                                             \
466     resample->h_resample (resample, lines[0], width);                   \
467 }
468 
469 MAKE_UPSAMPLE_H2 (u16, guint16);
470 MAKE_UPSAMPLE_H2 (u8, guint8);
471 MAKE_UPSAMPLE_V2 (u16, guint16);
472 MAKE_UPSAMPLE_V2 (u8, guint8);
473 MAKE_UPSAMPLE_VI2 (u16, guint16);
474 MAKE_UPSAMPLE_VI2 (u8, guint8);
475 MAKE_DOWNSAMPLE_H2 (u16, guint16);
476 MAKE_DOWNSAMPLE_H2_ORC (u8, guint8);
477 MAKE_DOWNSAMPLE_V2 (u16, guint16);
478 MAKE_DOWNSAMPLE_V2 (u8, guint8);
479 MAKE_DOWNSAMPLE_VI2 (u16, guint16);
480 MAKE_DOWNSAMPLE_VI2 (u8, guint8);
481 
482 /* 4x horizontal upsampling without cositing
483  *
484  *     +---------- (7*a +   b + 4) >> 3
485  *     | +-------- (5*a + 3*b + 4) >> 3
486  * a a | | +------ (3*a + 5*b + 4) >> 3
487  * | | | | | +---- (  a + 7*b + 4) >> 3
488  * v v v v v v
489  * O-O-O-O-O-O-O-O-
490  *    x       x
491  *    a       b
492  */
493 #define MAKE_UPSAMPLE_H4(name,type)                                          \
494 static void                                                             \
495 video_chroma_up_h4_##name (GstVideoChromaResample *resample,           \
496     gpointer pixels, gint width)                        \
497 {                                                                       \
498   type *p = pixels;                                                     \
499   gint i;                                                               \
500   type tr0, tr1;                                                        \
501   type tb0, tb1;                                                        \
502                                                                         \
503   tr1 = PR(0);                                                          \
504   tb1 = PB(0);                                                          \
505   for (i = 2; i < width - 3; i += 4) {                                  \
506     tr0 = tr1, tr1 = PR(i+2);                                           \
507     tb0 = tb1, tb1 = PB(i+2);                                           \
508                                                                         \
509     PR(i) = FILT_7_1 (tr0, tr1);                                        \
510     PB(i) = FILT_7_1 (tb0, tb1);                                        \
511     PR(i+1) = FILT_5_3 (tr0, tr1);                                      \
512     PB(i+1) = FILT_5_3 (tb0, tb1);                                      \
513     PR(i+2) = FILT_3_5 (tr0, tr1);                                      \
514     PB(i+2) = FILT_3_5 (tb0, tb1);                                      \
515     PR(i+3) = FILT_1_7 (tr0, tr1);                                      \
516     PB(i+3) = FILT_1_7 (tb0, tb1);                                      \
517   }                                                                     \
518 }
519 
520 /* 4x vertical upsampling without cositing
521  *
522  *   O--O--O-  <---- a
523  *   O--O--O-  <---- a
524  * a x  x  x
525  *   O--O--O-  <---- (7*a +   b + 4) >> 3
526  *   O--O--O-  <---- (5*a + 3*b + 4) >> 3
527  *   O--O--O-  <---- (3*a + 5*b + 4) >> 3
528  *   O--O--O-  <-----(  a + 7*b + 4) >> 3
529  * b x  x  x
530  *   O--O--O-
531  *   O--O--O-
532  */
533 #define MAKE_UPSAMPLE_V4(name,type)                                          \
534 static void                                                             \
535 video_chroma_up_v4_##name (GstVideoChromaResample *resample,            \
536     gpointer lines[], gint width)                                       \
537 {                                                                       \
538   gint i;                                                               \
539   type *l0 = lines[0];                                                  \
540   type *l1 = lines[1];                                                  \
541   type *l2 = lines[2];                                                  \
542   type *l3 = lines[3];                                                  \
543   type tr0, tr1;                                                        \
544   type tb0, tb1;                                                        \
545                                                                         \
546   if (resample->h_resample) {                                           \
547     if (l0 != l1) {                                                     \
548       resample->h_resample (resample, l0, width);                       \
549       resample->h_resample (resample, l1, width);                       \
550     }                                                                   \
551     if (l2 != l3) {                                                     \
552       resample->h_resample (resample, l2, width);                       \
553       resample->h_resample (resample, l3, width);                       \
554     }                                                                   \
555   }                                                                     \
556   if (l0 != l1 && l2 != l3) {                                           \
557     for (i = 0; i < width; i++) {                                       \
558       tr0 = PR0(i), tr1 = PR2(i);                                       \
559       tb0 = PB0(i), tb1 = PB2(i);                                       \
560                                                                         \
561       PR0(i) = FILT_7_1 (tr0, tr1);                                     \
562       PB0(i) = FILT_7_1 (tb0, tb1);                                     \
563       PR1(i) = FILT_5_3 (tr0, tr1);                                     \
564       PB1(i) = FILT_5_3 (tb0, tb1);                                     \
565       PR2(i) = FILT_3_5 (tr0, tr1);                                     \
566       PB2(i) = FILT_3_5 (tb0, tb1);                                     \
567       PR3(i) = FILT_1_7 (tr0, tr1);                                     \
568       PB3(i) = FILT_1_7 (tb0, tb1);                                     \
569     }                                                                   \
570   }                                                                     \
571 }
572 /* 4x vertical upsampling interlaced without cositing
573  *
574  */
575 #define MAKE_UPSAMPLE_VI4(name,type)                                         \
576 static void                                                             \
577 video_chroma_up_vi4_##name (GstVideoChromaResample *resample,           \
578     gpointer lines[], gint width)                                       \
579 {                                                                       \
580   /* FIXME */                                                           \
581   if (resample->h_resample) {                                           \
582     resample->h_resample (resample, lines[0], width);                   \
583   }                                                                     \
584 }
585 
586 /* 4x horizontal downsampling without cositing
587  *
588  *    +------ (a + 3*b + 3*c + d + 4) >> 3
589  *    |
590  *    v
591  * ---O-------O---
592  * x x x x x x x x
593  * a b c d e f g h
594  */
595 #define MAKE_DOWNSAMPLE_H4(name,type)                                        \
596 static void                                                             \
597 video_chroma_down_h4_##name (GstVideoChromaResample *resample,         \
598     gpointer pixels, gint width)                        \
599 {                                                                       \
600   type *p = pixels;                                                     \
601   gint i;                                                               \
602                                                                         \
603   for (i = 0; i < width - 4; i += 4) {                                  \
604     type tr0 = PR(i), tr1 = PR(i+1), tr2 = PR(i+2), tr3 = PR(i+3);      \
605     type tb0 = PB(i), tb1 = PB(i+1), tb2 = PB(i+2), tb3 = PB(i+3);      \
606                                                                         \
607     PR(i) = FILT_1_3_3_1 (tr0, tr1, tr2, tr3);                          \
608     PB(i) = FILT_1_3_3_1 (tb0, tb1, tb2, tb3);                          \
609   }                                                                     \
610 }
611 
612 /* 4x vertical downsampling without cositing
613  *
614  * a x--x--x-
615  * b x--x--x-
616  *   O  O  O   <---- (a + 3*b + 3*c + d + 4) >> 4
617  * c x--x--x-
618  * d x--x--x-
619  * e x--x--x-
620  * f x--x--x-
621  *   O  O  O
622  * g x--x--x-
623  * h x--x--x-
624  */
625 #define MAKE_DOWNSAMPLE_V4(name,type)                               \
626 static void                                                             \
627 video_chroma_down_v4_##name (GstVideoChromaResample *resample,          \
628     gpointer lines[], gint width)                                       \
629 {                                                                       \
630   type *l0 = lines[0];                                                  \
631   type *l1 = lines[1];                                                  \
632   type *l2 = lines[2];                                                  \
633   type *l3 = lines[3];                                                  \
634   type *d = l0;								\
635 									\
636   video_orc_chroma_down_v4_##name(d, l0, l1, l2, l3, width);		\
637                                                                         \
638   if (resample->h_resample)                                             \
639     resample->h_resample (resample, l0, width);                         \
640 }
641 /* 4x vertical downsampling interlaced without cositing
642  *
643  */
644 #define MAKE_DOWNSAMPLE_VI4(name,type)                                       \
645 static void                                                             \
646 video_chroma_down_vi4_##name (GstVideoChromaResample *resample,         \
647     gpointer lines[], gint width)                                       \
648 {                                                                       \
649   /* FIXME */                                                           \
650   if (resample->h_resample) {                                           \
651     resample->h_resample (resample, lines[0], width);                   \
652   }                                                                     \
653 }
654 
655 MAKE_UPSAMPLE_H4 (u16, guint16);
656 MAKE_UPSAMPLE_H4 (u8, guint8);
657 MAKE_UPSAMPLE_V4 (u16, guint16);
658 MAKE_UPSAMPLE_V4 (u8, guint8);
659 MAKE_UPSAMPLE_VI4 (u16, guint16);
660 MAKE_UPSAMPLE_VI4 (u8, guint8);
661 MAKE_DOWNSAMPLE_H4 (u16, guint16);
662 MAKE_DOWNSAMPLE_H4 (u8, guint8);
663 MAKE_DOWNSAMPLE_V4 (u16, guint16);
664 MAKE_DOWNSAMPLE_V4 (u8, guint8);
665 MAKE_DOWNSAMPLE_VI4 (u16, guint16);
666 MAKE_DOWNSAMPLE_VI4 (u8, guint8);
667 
668 /* 2x horizontal upsampling with cositing
669  *
670  * a +------ (a + b + 1) >> 1
671  * | |
672  * v v
673  * O-O-O-O
674  * x   x
675  * a   b
676  */
677 #define MAKE_UPSAMPLE_H2_CS_ORC(name,type)                              \
678 static void                                                             \
679 video_chroma_up_h2_cs_##name (GstVideoChromaResample *resample,         \
680     gpointer pixels, gint width)                                        \
681 {                                                                       \
682   type *p = pixels;                                                     \
683   /* ORC version is slower */                                           \
684   video_orc_chroma_up_h2_cs_##name (p, p, p, width-1);                  \
685 }
686 
687 #define MAKE_UPSAMPLE_H2_CS(name,type)                                  \
688 static void                                                             \
689 video_chroma_up_h2_cs_##name (GstVideoChromaResample *resample,         \
690     gpointer pixels, gint width)                                        \
691 {                                                                       \
692   type *p = pixels;                                                     \
693   gint i;                                                               \
694                                                                         \
695   for (i = 1; i < width - 1; i += 2) {                                  \
696     PR(i) = FILT_1_1 (PR(i-1), PR(i+1));                                \
697     PB(i) = FILT_1_1 (PB(i-1), PB(i+1));                                \
698   }                                                                     \
699 }
700 /* 2x vertical upsampling with cositing
701  *
702  * a x O--O--O-  <---- a
703  *     O--O--O-  <---- (a +  b + 1) >> 1
704  * b x O--O--O-
705  *     O--O--O-
706  */
707 #define MAKE_UPSAMPLE_V2_CS(name,type)                                       \
708 static void                                                             \
709 video_chroma_up_v2_cs_##name (GstVideoChromaResample *resample,         \
710     gpointer lines[], gint width)                                       \
711 {                                                                       \
712   /* FIXME */                                                           \
713   if (resample->h_resample) {                                           \
714     resample->h_resample (resample, lines[0], width);                   \
715   }                                                                     \
716 }
717 /* 2x vertical upsampling interlaced with cositing
718  *
719  */
720 #define MAKE_UPSAMPLE_VI2_CS(name,type)                                      \
721 static void                                                             \
722 video_chroma_up_vi2_cs_##name (GstVideoChromaResample *resample,        \
723     gpointer lines[], gint width)                                       \
724 {                                                                       \
725   /* FIXME */                                                           \
726   if (resample->h_resample) {                                           \
727     resample->h_resample (resample, lines[0], width);                   \
728   }                                                                     \
729 }
730 
731 /* 2x horizontal downsampling with cositing
732  *
733  * a
734  * |   +------ (b + 2*c + d + 2) >> 2
735  * v   v
736  * O---O---O---
737  * x x x x x x
738  * a b c d e f
739  */
740 #define MAKE_DOWNSAMPLE_H2_CS(name,type)                                     \
741 static void                                                             \
742 video_chroma_down_h2_cs_##name (GstVideoChromaResample *resample,       \
743     gpointer pixels, gint width)                                        \
744 {                                                                       \
745   type *p = pixels;                                                     \
746   gint i;                                                               \
747                                                                         \
748   if (width < 2)                                                        \
749     return;                                                             \
750                                                                         \
751   PR(0) = FILT_3_1 (PR(0), PR(1));                                      \
752   PB(0) = FILT_3_1 (PB(0), PB(1));                                      \
753                                                                         \
754   for (i = 2; i < width - 2; i += 2) {                                  \
755     PR(i) = FILT_1_2_1 (PR(i-1), PR(i), PR(i+1));                       \
756     PB(i) = FILT_1_2_1 (PB(i-1), PB(i), PB(i+1));                       \
757   }                                                                     \
758   if (i < width) {                                                      \
759     PR(i) = FILT_1_3 (PR(i-1), PR(i));                                  \
760     PB(i) = FILT_1_3 (PB(i-1), PB(i));                                  \
761   }                                                                     \
762 }
763 /* 2x vertical downsampling with cositing
764  *
765  * a x O--O--O-  <---- a
766  * b x --------
767  * c x O--O--O-  <---- (b + 2*c + d + 2) >> 2
768  * d x --------
769  * e x O--O--O-
770  * f x --------
771  */
772 #define MAKE_DOWNSAMPLE_V2_CS(name,type)                                     \
773 static void                                                             \
774 video_chroma_down_v2_cs_##name (GstVideoChromaResample *resample,       \
775     gpointer lines[], gint width)                                       \
776 {                                                                       \
777   /* FIXME */                                                           \
778   if (resample->h_resample) {                                           \
779     resample->h_resample (resample, lines[0], width);                   \
780   }                                                                     \
781 }
782 /* 2x vertical downsampling interlaced with cositing
783  *
784  */
785 #define MAKE_DOWNSAMPLE_VI2_CS(name,type)                                    \
786 static void                                                             \
787 video_chroma_down_vi2_cs_##name (GstVideoChromaResample *resample,      \
788     gpointer lines[], gint width)                                       \
789 {                                                                       \
790   /* FIXME */                                                           \
791   if (resample->h_resample) {                                           \
792     resample->h_resample (resample, lines[0], width);                   \
793   }                                                                     \
794 }
795 
796 MAKE_UPSAMPLE_H2_CS (u16, guint16);
797 MAKE_UPSAMPLE_H2_CS (u8, guint8);
798 MAKE_UPSAMPLE_V2_CS (u16, guint16);
799 MAKE_UPSAMPLE_V2_CS (u8, guint8);
800 MAKE_UPSAMPLE_VI2_CS (u16, guint16);
801 MAKE_UPSAMPLE_VI2_CS (u8, guint8);
802 MAKE_DOWNSAMPLE_H2_CS (u16, guint16);
803 MAKE_DOWNSAMPLE_H2_CS (u8, guint8);
804 MAKE_DOWNSAMPLE_V2_CS (u16, guint16);
805 MAKE_DOWNSAMPLE_V2_CS (u8, guint8);
806 MAKE_DOWNSAMPLE_VI2_CS (u16, guint16);
807 MAKE_DOWNSAMPLE_VI2_CS (u8, guint8);
808 
809 /* 4x horizontal upsampling with cositing
810  *
811  *   +---------- (3*a +   b + 2) >> 2
812  * a | +-------- (  a +   b + 1) >> 1
813  * | | | +------ (  a + 3*b + 2) >> 2
814  * v v v v
815  * O-O-O-O-O-O-O-O
816  * x       x
817  * a       b
818  */
819 #define MAKE_UPSAMPLE_H4_CS(name,type)                                       \
820 static void                                                             \
821 video_chroma_up_h4_cs_##name (GstVideoChromaResample *resample,        \
822     gpointer pixels, gint width)                        \
823 {                                                                       \
824   type *p = pixels;                                                        \
825   gint i;                                                               \
826                                                                         \
827   for (i = 0; i < width - 4; i += 4) {                                  \
828     type tr0 = PR(i), tr1 = PR(i+4);                                    \
829     type tb0 = PB(i), tb1 = PB(i+4);                                    \
830                                                                         \
831     PR(i+1) = FILT_3_1 (tr0, tr1);                                      \
832     PB(i+1) = FILT_3_1 (tb0, tb1);                                      \
833     PR(i+2) = FILT_1_1 (tr0, tr1);                                      \
834     PB(i+2) = FILT_1_1 (tb0, tb1);                                      \
835     PR(i+3) = FILT_1_3 (tr0, tr1);                                      \
836     PB(i+3) = FILT_1_3 (tb0, tb1);                                      \
837   }                                                                     \
838 }
839 /* 4x vertical upsampling with cositing
840  *
841  * a x O--O--O-  <---- a
842  *     O--O--O-  <---- (3*a +   b + 2) >> 2
843  *     O--O--O-  <---- (  a +   b + 1) >> 1
844  *     O--O--O-  <---- (  a + 3*b + 2) >> 2
845  * b x O--O--O-
846  *     O--O--O-
847  */
848 #define MAKE_UPSAMPLE_V4_CS(name,type)                                       \
849 static void                                                             \
850 video_chroma_up_v4_cs_##name (GstVideoChromaResample *resample,         \
851     gpointer lines[], gint width)                                       \
852 {                                                                       \
853   /* FIXME */                                                           \
854   if (resample->h_resample) {                                           \
855     resample->h_resample (resample, lines[0], width);                   \
856   }                                                                     \
857 }
858 /* 4x vertical upsampling interlaced with cositing
859  *
860  */
861 #define MAKE_UPSAMPLE_VI4_CS(name,type)                                      \
862 static void                                                             \
863 video_chroma_up_vi4_cs_##name (GstVideoChromaResample *resample,        \
864     gpointer lines[], gint width)                                       \
865 {                                                                       \
866   /* FIXME */                                                           \
867   if (resample->h_resample) {                                           \
868     resample->h_resample (resample, lines[0], width);                   \
869   }                                                                     \
870 }
871 /* 4x horizontal downsampling with cositing
872  *
873  * a
874  * |       +------ (b + 2*c + 3*d + 4*e + 3*f + 2*g + h + 8) >> 16
875  * v       v
876  * O-------O-------
877  * x x x x x x x x
878  * a b c d e f g h
879  */
880 #define MAKE_DOWNSAMPLE_H4_CS(name,type)                                     \
881 static void                                                             \
882 video_chroma_down_h4_cs_##name (GstVideoChromaResample *resample,      \
883     gpointer pixels, gint width)                        \
884 {                                                                       \
885   type *p = pixels;                                                     \
886   gint i;                                                               \
887                                                                         \
888   if (width < 4)                                                        \
889     return;                                                             \
890                                                                         \
891   PR(0) = FILT_10_3_2_1 (PR(0), PR(1), PR(2), PR(3));                   \
892   PB(0) = FILT_10_3_2_1 (PB(0), PB(1), PB(2), PB(3));                   \
893                                                                         \
894   for (i = 4; i < width - 4; i += 4) {                                  \
895     PR(i) = FILT_1_2_3_4_3_2_1 (PR(i-3), PR(i-2), PR(i-1), PR(i), PR(i+1), PR(i+2), PR(i+3));   \
896     PB(i) = FILT_1_2_3_4_3_2_1 (PB(i-3), PB(i-2), PB(i-1), PB(i), PB(i+1), PB(i+2), PB(i+3));   \
897   }                                                                     \
898   if (i < width) {                                                      \
899     PR(i) = FILT_1_2_3_10 (PR(i-3), PR(i-2), PR(i-1), PR(i));           \
900     PB(i) = FILT_1_2_3_10 (PB(i-3), PB(i-2), PB(i-1), PB(i));           \
901   }                                                                     \
902 }
903 /* 4x vertical downsampling with cositing
904  *
905  * a x O--O--O-  <---- a
906  * b x --------
907  * c x --------
908  * d x --------
909  * e x O--O--O-  <---- (b + 2*c + 3*d + 4*e + 3*f + 2*g + h + 8) >> 16
910  * f x --------
911  * g x --------
912  * h x --------
913  * i x O--O--O-
914  * j x --------
915  */
916 #define MAKE_DOWNSAMPLE_V4_CS(name,type)                                     \
917 static void                                                             \
918 video_chroma_down_v4_cs_##name (GstVideoChromaResample *resample,       \
919     gpointer lines[], gint width)                                       \
920 {                                                                       \
921   /* FIXME */                                                           \
922   if (resample->h_resample) {                                           \
923     resample->h_resample (resample, lines[0], width);                   \
924   }                                                                     \
925 }
926 /* 4x vertical downsampling interlaced with cositing
927  *
928  */
929 #define MAKE_DOWNSAMPLE_VI4_CS(name,type)                                    \
930 static void                                                             \
931 video_chroma_down_vi4_cs_##name (GstVideoChromaResample *resample,      \
932     gpointer lines[], gint width)                                       \
933 {                                                                       \
934   /* FIXME */                                                           \
935   if (resample->h_resample) {                                           \
936     resample->h_resample (resample, lines[0], width);                   \
937   }                                                                     \
938 }
939 
940 MAKE_UPSAMPLE_H4_CS (u16, guint16);
941 MAKE_UPSAMPLE_H4_CS (u8, guint8);
942 MAKE_UPSAMPLE_V4_CS (u16, guint16);
943 MAKE_UPSAMPLE_V4_CS (u8, guint8);
944 MAKE_UPSAMPLE_VI4_CS (u16, guint16);
945 MAKE_UPSAMPLE_VI4_CS (u8, guint8);
946 MAKE_DOWNSAMPLE_H4_CS (u16, guint16);
947 MAKE_DOWNSAMPLE_H4_CS (u8, guint8);
948 MAKE_DOWNSAMPLE_V4_CS (u16, guint16);
949 MAKE_DOWNSAMPLE_V4_CS (u8, guint8);
950 MAKE_DOWNSAMPLE_VI4_CS (u16, guint16);
951 MAKE_DOWNSAMPLE_VI4_CS (u8, guint8);
952 
953 typedef struct
954 {
955   void (*resample) (GstVideoChromaResample * resample, gpointer pixels,
956       gint width);
957 } HorizResampler;
958 
959 static const HorizResampler h_resamplers[] = {
960   {NULL},
961   {video_chroma_up_h2_u8},
962   {video_chroma_down_h2_u8},
963   {video_chroma_up_h2_u16},
964   {video_chroma_down_h2_u16},
965   {video_chroma_up_h2_cs_u8},
966   {video_chroma_down_h2_cs_u8},
967   {video_chroma_up_h2_cs_u16},
968   {video_chroma_down_h2_cs_u16},
969   {video_chroma_up_h4_u8},
970   {video_chroma_down_h4_u8},
971   {video_chroma_up_h4_u16},
972   {video_chroma_down_h4_u16},
973   {video_chroma_up_h4_cs_u8},
974   {video_chroma_down_h4_cs_u8},
975   {video_chroma_up_h4_cs_u16},
976   {video_chroma_down_h4_cs_u16}
977 };
978 
979 typedef struct
980 {
981   void (*resample) (GstVideoChromaResample * resample, gpointer lines[],
982       gint width);
983   guint n_lines;
984   gint offset;
985 } VertResampler;
986 
987 static void
video_chroma_none(GstVideoChromaResample * resample,gpointer lines[],gint width)988 video_chroma_none (GstVideoChromaResample * resample,
989     gpointer lines[], gint width)
990 {
991   if (resample->h_resample)
992     resample->h_resample (resample, lines[0], width);
993 }
994 
995 static const VertResampler v_resamplers[] = {
996   {video_chroma_none, 1, 0},
997   {video_chroma_up_v2_u8, 2, -1},
998   {video_chroma_down_v2_u8, 2, 0},
999   /* 16 bits */
1000   {video_chroma_up_v2_u16, 2, -1},
1001   {video_chroma_down_v2_u16, 2, 0},
1002   /* cosited */
1003   {video_chroma_up_v2_cs_u8, 1, 0},     /* IMPLEMENT ME */
1004   {video_chroma_down_v2_cs_u8, 1, 0},   /* IMPLEMENT ME */
1005   {video_chroma_up_v2_cs_u16, 1, 0},    /* IMPLEMENT ME */
1006   {video_chroma_down_v2_cs_u16, 1, 0},  /* IMPLEMENT ME */
1007   /* 4x */
1008   {video_chroma_up_v4_u8, 4, -2},
1009   {video_chroma_down_v4_u8, 4, 0},
1010   {video_chroma_up_v4_u16, 4, -2},
1011   {video_chroma_down_v4_u16, 4, 0},
1012   {video_chroma_up_v4_cs_u8, 1, 0},     /* IMPLEMENT ME */
1013   {video_chroma_down_v4_cs_u8, 1, 0},   /* IMPLEMENT ME */
1014   {video_chroma_up_v4_cs_u16, 1, 0},    /* IMPLEMENT ME */
1015   {video_chroma_down_v4_cs_u16, 1, 0},  /* IMPLEMENT ME */
1016   /* interlaced */
1017   {video_chroma_up_vi2_u8, 4, -2},
1018   {video_chroma_down_vi2_u8, 1, 0},     /* IMPLEMENT ME */
1019   {video_chroma_up_vi2_u16, 4, -2},
1020   {video_chroma_down_vi2_u16, 1, 0},    /* IMPLEMENT ME */
1021   {video_chroma_up_vi2_cs_u8, 1, 0},    /* IMPLEMENT ME */
1022   {video_chroma_down_vi2_cs_u8, 1, 0},  /* IMPLEMENT ME */
1023   {video_chroma_up_vi2_cs_u16, 1, 0},   /* IMPLEMENT ME */
1024   {video_chroma_down_vi2_cs_u16, 1, 0}, /* IMPLEMENT ME */
1025   {video_chroma_up_vi4_u8, 1, 0},       /* IMPLEMENT ME */
1026   {video_chroma_down_vi4_u8, 1, 0},     /* IMPLEMENT ME */
1027   {video_chroma_up_vi4_u16, 1, 0},      /* IMPLEMENT ME */
1028   {video_chroma_down_vi4_u16, 1, 0},    /* IMPLEMENT ME */
1029   {video_chroma_up_vi4_cs_u8, 1, 0},    /* IMPLEMENT ME */
1030   {video_chroma_down_vi4_cs_u8, 1, 0},  /* IMPLEMENT ME */
1031   {video_chroma_up_vi4_cs_u16, 1, 0},   /* IMPLEMENT ME */
1032   {video_chroma_down_vi4_cs_u16, 1, 0}, /* IMPLEMENT ME */
1033 };
1034 
1035 /**
1036  * gst_video_chroma_resample_new: (skip)
1037  * @method: a #GstVideoChromaMethod
1038  * @site: a #GstVideoChromaSite
1039  * @flags: #GstVideoChromaFlags
1040  * @format: the #GstVideoFormat
1041  * @h_factor: horizontal resampling factor
1042  * @v_factor: vertical resampling factor
1043  *
1044  * Create a new resampler object for the given parameters. When @h_factor or
1045  * @v_factor is > 0, upsampling will be used, otherwise subsampling is
1046  * performed.
1047  *
1048  * Returns: a new #GstVideoChromaResample that should be freed with
1049  *     gst_video_chroma_resample_free() after usage.
1050  */
1051 GstVideoChromaResample *
gst_video_chroma_resample_new(GstVideoChromaMethod method,GstVideoChromaSite site,GstVideoChromaFlags flags,GstVideoFormat format,gint h_factor,gint v_factor)1052 gst_video_chroma_resample_new (GstVideoChromaMethod method,
1053     GstVideoChromaSite site, GstVideoChromaFlags flags,
1054     GstVideoFormat format, gint h_factor, gint v_factor)
1055 {
1056   GstVideoChromaResample *result;
1057   guint cosite, h_index, v_index, bits;
1058 
1059   /* no resampling */
1060   if (h_factor == 0 && v_factor == 0)
1061     return NULL;
1062 
1063   if (format == GST_VIDEO_FORMAT_AYUV)
1064     bits = 8;
1065   else if (format == GST_VIDEO_FORMAT_AYUV64)
1066     bits = 16;
1067   else
1068     return NULL;
1069 
1070   cosite = (site & GST_VIDEO_CHROMA_SITE_H_COSITED ? 1 : 0);
1071   if (h_factor == 0)
1072     h_index = 0;
1073   else
1074     h_index =
1075         ((ABS (h_factor) - 1) * 8) + (cosite ? 4 : 0) + (bits ==
1076         16 ? 2 : 0) + (h_factor < 0 ? 1 : 0) + 1;
1077 
1078   GST_DEBUG ("h_resample %d, factor %d, cosite %d", h_index, h_factor, cosite);
1079 
1080   cosite = (site & GST_VIDEO_CHROMA_SITE_V_COSITED ? 1 : 0);
1081   if (v_factor == 0)
1082     v_index = 0;
1083   else
1084     v_index =
1085         ((ABS (v_factor) - 1) * 8) + (cosite ? 4 : 0) + (bits ==
1086         16 ? 2 : 0) + (v_factor < 0 ? 1 : 0) + 1;
1087 
1088   if (flags & GST_VIDEO_CHROMA_FLAG_INTERLACED)
1089     v_index += 16;
1090 
1091   GST_DEBUG ("v_resample %d, factor %d, cosite %d", v_index, v_factor, cosite);
1092 
1093   result = g_slice_new (GstVideoChromaResample);
1094   result->method = method;
1095   result->site = site;
1096   result->flags = flags;
1097   result->format = format;
1098   result->h_factor = h_factor;
1099   result->v_factor = v_factor;
1100   result->h_resample = h_resamplers[h_index].resample;
1101   result->v_resample = v_resamplers[v_index].resample;
1102   result->n_lines = v_resamplers[v_index].n_lines;
1103   result->offset = v_resamplers[v_index].offset;
1104 
1105   GST_DEBUG ("resample %p, bits %d, n_lines %u, offset %d", result, bits,
1106       result->n_lines, result->offset);
1107 
1108   return result;
1109 }
1110 
1111 /**
1112  * gst_video_chroma_resample_get_info:
1113  * @resample: a #GstVideoChromaResample
1114  * @n_lines: the number of input lines
1115  * @offset: the first line
1116  *
1117  * The resampler must be fed @n_lines at a time. The first line should be
1118  * at @offset.
1119  */
1120 void
gst_video_chroma_resample_get_info(GstVideoChromaResample * resample,guint * n_lines,gint * offset)1121 gst_video_chroma_resample_get_info (GstVideoChromaResample * resample,
1122     guint * n_lines, gint * offset)
1123 {
1124   g_return_if_fail (resample != NULL);
1125 
1126   if (n_lines)
1127     *n_lines = resample->n_lines;
1128   if (offset)
1129     *offset = resample->offset;
1130 }
1131 
1132 /**
1133  * gst_video_chroma_resample_free:
1134  * @resample: a #GstVideoChromaResample
1135  *
1136  * Free @resample
1137  */
1138 void
gst_video_chroma_resample_free(GstVideoChromaResample * resample)1139 gst_video_chroma_resample_free (GstVideoChromaResample * resample)
1140 {
1141   g_return_if_fail (resample != NULL);
1142 
1143   g_slice_free (GstVideoChromaResample, resample);
1144 }
1145 
1146 /**
1147  * gst_video_chroma_resample:
1148  * @resample: a #GstVideoChromaResample
1149  * @lines: pixel lines
1150  * @width: the number of pixels on one line
1151  *
1152  * Perform resampling of @width chroma pixels in @lines.
1153  */
1154 void
gst_video_chroma_resample(GstVideoChromaResample * resample,gpointer lines[],gint width)1155 gst_video_chroma_resample (GstVideoChromaResample * resample,
1156     gpointer lines[], gint width)
1157 {
1158   g_return_if_fail (resample != NULL);
1159 
1160   resample->v_resample (resample, lines, width);
1161 }
1162