deinterlace: support filter in getcaps
[platform/upstream/gst-plugins-good.git] / gst / deinterlace / gstdeinterlacemethod.c
1 /*
2  * GStreamer
3  * Copyright (C) 2008-2010 Sebastian Dröge <slomo@collabora.co.uk>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <string.h>
26
27 #include "gstdeinterlacemethod.h"
28
29 G_DEFINE_ABSTRACT_TYPE (GstDeinterlaceMethod, gst_deinterlace_method,
30     GST_TYPE_OBJECT);
31
32 gboolean
33 gst_deinterlace_method_supported (GType type, GstVideoFormat format, gint width,
34     gint height)
35 {
36   GstDeinterlaceMethodClass *klass =
37       GST_DEINTERLACE_METHOD_CLASS (g_type_class_ref (type));
38   gboolean ret;
39
40   if (format == GST_VIDEO_FORMAT_UNKNOWN)
41     ret = TRUE;
42   else
43     ret = klass->supported (klass, format, width, height);
44   g_type_class_unref (klass);
45
46   return ret;
47 }
48
49 static gboolean
50 gst_deinterlace_method_supported_impl (GstDeinterlaceMethodClass * klass,
51     GstVideoFormat format, gint width, gint height)
52 {
53   switch (format) {
54     case GST_VIDEO_FORMAT_YUY2:
55       return (klass->deinterlace_frame_yuy2 != NULL);
56     case GST_VIDEO_FORMAT_YVYU:
57       return (klass->deinterlace_frame_yvyu != NULL);
58     case GST_VIDEO_FORMAT_UYVY:
59       return (klass->deinterlace_frame_uyvy != NULL);
60     case GST_VIDEO_FORMAT_I420:
61       return (klass->deinterlace_frame_i420 != NULL);
62     case GST_VIDEO_FORMAT_YV12:
63       return (klass->deinterlace_frame_yv12 != NULL);
64     case GST_VIDEO_FORMAT_Y444:
65       return (klass->deinterlace_frame_y444 != NULL);
66     case GST_VIDEO_FORMAT_Y42B:
67       return (klass->deinterlace_frame_y42b != NULL);
68     case GST_VIDEO_FORMAT_Y41B:
69       return (klass->deinterlace_frame_y41b != NULL);
70     case GST_VIDEO_FORMAT_AYUV:
71       return (klass->deinterlace_frame_ayuv != NULL);
72     case GST_VIDEO_FORMAT_NV12:
73       return (klass->deinterlace_frame_nv12 != NULL);
74     case GST_VIDEO_FORMAT_NV21:
75       return (klass->deinterlace_frame_nv21 != NULL);
76     case GST_VIDEO_FORMAT_ARGB:
77     case GST_VIDEO_FORMAT_xRGB:
78       return (klass->deinterlace_frame_argb != NULL);
79     case GST_VIDEO_FORMAT_ABGR:
80     case GST_VIDEO_FORMAT_xBGR:
81       return (klass->deinterlace_frame_abgr != NULL);
82     case GST_VIDEO_FORMAT_RGBA:
83     case GST_VIDEO_FORMAT_RGBx:
84       return (klass->deinterlace_frame_rgba != NULL);
85     case GST_VIDEO_FORMAT_BGRA:
86     case GST_VIDEO_FORMAT_BGRx:
87       return (klass->deinterlace_frame_bgra != NULL);
88     case GST_VIDEO_FORMAT_RGB:
89       return (klass->deinterlace_frame_rgb != NULL);
90     case GST_VIDEO_FORMAT_BGR:
91       return (klass->deinterlace_frame_bgr != NULL);
92     default:
93       return FALSE;
94   }
95 }
96
97 void
98 gst_deinterlace_method_setup (GstDeinterlaceMethod * self, GstVideoInfo * vinfo)
99 {
100   GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
101
102   klass->setup (self, vinfo);
103 }
104
105 static void
106 gst_deinterlace_method_setup_impl (GstDeinterlaceMethod * self,
107     GstVideoInfo * vinfo)
108 {
109   gint i;
110   GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
111
112   self->vinfo = vinfo;
113
114   self->deinterlace_frame = NULL;
115
116   if (GST_VIDEO_INFO_FORMAT (self->vinfo) == GST_VIDEO_FORMAT_UNKNOWN)
117     return;
118
119   for (i = 0; i < 4; i++) {
120     self->width[i] = GST_VIDEO_INFO_COMP_WIDTH (vinfo, i);
121     self->height[i] = GST_VIDEO_INFO_COMP_HEIGHT (vinfo, i);
122     self->offset[i] = GST_VIDEO_INFO_COMP_OFFSET (vinfo, i);
123     self->row_stride[i] = GST_VIDEO_INFO_COMP_STRIDE (vinfo, i);
124     self->pixel_stride[i] = GST_VIDEO_INFO_COMP_PSTRIDE (vinfo, i);
125   }
126
127   switch (GST_VIDEO_INFO_FORMAT (self->vinfo)) {
128     case GST_VIDEO_FORMAT_YUY2:
129       self->deinterlace_frame = klass->deinterlace_frame_yuy2;
130       break;
131     case GST_VIDEO_FORMAT_YVYU:
132       self->deinterlace_frame = klass->deinterlace_frame_yvyu;
133       break;
134     case GST_VIDEO_FORMAT_UYVY:
135       self->deinterlace_frame = klass->deinterlace_frame_uyvy;
136       break;
137     case GST_VIDEO_FORMAT_I420:
138       self->deinterlace_frame = klass->deinterlace_frame_i420;
139       break;
140     case GST_VIDEO_FORMAT_YV12:
141       self->deinterlace_frame = klass->deinterlace_frame_yv12;
142       break;
143     case GST_VIDEO_FORMAT_Y444:
144       self->deinterlace_frame = klass->deinterlace_frame_y444;
145       break;
146     case GST_VIDEO_FORMAT_Y42B:
147       self->deinterlace_frame = klass->deinterlace_frame_y42b;
148       break;
149     case GST_VIDEO_FORMAT_Y41B:
150       self->deinterlace_frame = klass->deinterlace_frame_y41b;
151       break;
152     case GST_VIDEO_FORMAT_AYUV:
153       self->deinterlace_frame = klass->deinterlace_frame_ayuv;
154       break;
155     case GST_VIDEO_FORMAT_NV12:
156       self->deinterlace_frame = klass->deinterlace_frame_nv12;
157       break;
158     case GST_VIDEO_FORMAT_NV21:
159       self->deinterlace_frame = klass->deinterlace_frame_nv21;
160       break;
161     case GST_VIDEO_FORMAT_ARGB:
162     case GST_VIDEO_FORMAT_xRGB:
163       self->deinterlace_frame = klass->deinterlace_frame_argb;
164       break;
165     case GST_VIDEO_FORMAT_ABGR:
166     case GST_VIDEO_FORMAT_xBGR:
167       self->deinterlace_frame = klass->deinterlace_frame_abgr;
168       break;
169     case GST_VIDEO_FORMAT_RGBA:
170     case GST_VIDEO_FORMAT_RGBx:
171       self->deinterlace_frame = klass->deinterlace_frame_rgba;
172       break;
173     case GST_VIDEO_FORMAT_BGRA:
174     case GST_VIDEO_FORMAT_BGRx:
175       self->deinterlace_frame = klass->deinterlace_frame_bgra;
176       break;
177     case GST_VIDEO_FORMAT_RGB:
178       self->deinterlace_frame = klass->deinterlace_frame_rgb;
179       break;
180     case GST_VIDEO_FORMAT_BGR:
181       self->deinterlace_frame = klass->deinterlace_frame_bgr;
182       break;
183     default:
184       self->deinterlace_frame = NULL;
185       break;
186   }
187 }
188
189 static void
190 gst_deinterlace_method_class_init (GstDeinterlaceMethodClass * klass)
191 {
192   klass->setup = gst_deinterlace_method_setup_impl;
193   klass->supported = gst_deinterlace_method_supported_impl;
194 }
195
196 static void
197 gst_deinterlace_method_init (GstDeinterlaceMethod * self)
198 {
199   self->vinfo = NULL;
200 }
201
202 void
203 gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self,
204     const GstDeinterlaceField * history, guint history_count,
205     GstVideoFrame * outframe, int cur_field_idx)
206 {
207   g_assert (self->deinterlace_frame != NULL);
208   self->deinterlace_frame (self, history, history_count, outframe,
209       cur_field_idx);
210 }
211
212 gint
213 gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self)
214 {
215   GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
216
217   return klass->fields_required;
218 }
219
220 gint
221 gst_deinterlace_method_get_latency (GstDeinterlaceMethod * self)
222 {
223   GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
224
225   return klass->latency;
226 }
227
228 G_DEFINE_ABSTRACT_TYPE (GstDeinterlaceSimpleMethod,
229     gst_deinterlace_simple_method, GST_TYPE_DEINTERLACE_METHOD);
230
231 static gboolean
232 gst_deinterlace_simple_method_supported (GstDeinterlaceMethodClass * mklass,
233     GstVideoFormat format, gint width, gint height)
234 {
235   GstDeinterlaceSimpleMethodClass *klass =
236       GST_DEINTERLACE_SIMPLE_METHOD_CLASS (mklass);
237
238   if (!GST_DEINTERLACE_METHOD_CLASS
239       (gst_deinterlace_simple_method_parent_class)->supported (mklass, format,
240           width, height))
241     return FALSE;
242
243   switch (format) {
244     case GST_VIDEO_FORMAT_ARGB:
245     case GST_VIDEO_FORMAT_xRGB:
246       return (klass->interpolate_scanline_argb != NULL
247           && klass->copy_scanline_argb != NULL);
248     case GST_VIDEO_FORMAT_RGBA:
249     case GST_VIDEO_FORMAT_RGBx:
250       return (klass->interpolate_scanline_rgba != NULL
251           && klass->copy_scanline_rgba != NULL);
252     case GST_VIDEO_FORMAT_ABGR:
253     case GST_VIDEO_FORMAT_xBGR:
254       return (klass->interpolate_scanline_abgr != NULL
255           && klass->copy_scanline_abgr != NULL);
256     case GST_VIDEO_FORMAT_BGRA:
257     case GST_VIDEO_FORMAT_BGRx:
258       return (klass->interpolate_scanline_bgra != NULL
259           && klass->copy_scanline_bgra != NULL);
260     case GST_VIDEO_FORMAT_RGB:
261       return (klass->interpolate_scanline_rgb != NULL
262           && klass->copy_scanline_rgb != NULL);
263     case GST_VIDEO_FORMAT_BGR:
264       return (klass->interpolate_scanline_bgr != NULL
265           && klass->copy_scanline_bgr != NULL);
266     case GST_VIDEO_FORMAT_YUY2:
267       return (klass->interpolate_scanline_yuy2 != NULL
268           && klass->copy_scanline_yuy2 != NULL);
269     case GST_VIDEO_FORMAT_YVYU:
270       return (klass->interpolate_scanline_yvyu != NULL
271           && klass->copy_scanline_yvyu != NULL);
272     case GST_VIDEO_FORMAT_UYVY:
273       return (klass->interpolate_scanline_uyvy != NULL
274           && klass->copy_scanline_uyvy != NULL);
275     case GST_VIDEO_FORMAT_AYUV:
276       return (klass->interpolate_scanline_ayuv != NULL
277           && klass->copy_scanline_ayuv != NULL);
278     case GST_VIDEO_FORMAT_NV12:
279       return (klass->interpolate_scanline_nv12 != NULL
280           && klass->copy_scanline_nv12 != NULL);
281     case GST_VIDEO_FORMAT_NV21:
282       return (klass->interpolate_scanline_nv21 != NULL
283           && klass->copy_scanline_nv21 != NULL);
284     case GST_VIDEO_FORMAT_I420:
285     case GST_VIDEO_FORMAT_YV12:
286     case GST_VIDEO_FORMAT_Y444:
287     case GST_VIDEO_FORMAT_Y42B:
288     case GST_VIDEO_FORMAT_Y41B:
289       return (klass->interpolate_scanline_planar_y != NULL
290           && klass->copy_scanline_planar_y != NULL &&
291           klass->interpolate_scanline_planar_u != NULL
292           && klass->copy_scanline_planar_u != NULL &&
293           klass->interpolate_scanline_planar_v != NULL
294           && klass->copy_scanline_planar_v != NULL);
295     default:
296       return FALSE;
297   }
298 }
299
300 static void
301     gst_deinterlace_simple_method_interpolate_scanline_packed
302     (GstDeinterlaceSimpleMethod * self, guint8 * out,
303     const GstDeinterlaceScanlineData * scanlines)
304 {
305   memcpy (out, scanlines->m1, self->parent.row_stride[0]);
306 }
307
308 static void
309 gst_deinterlace_simple_method_copy_scanline_packed (GstDeinterlaceSimpleMethod *
310     self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
311 {
312   memcpy (out, scanlines->m0, self->parent.row_stride[0]);
313 }
314
315 static void
316 gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod *
317     method, const GstDeinterlaceField * history, guint history_count,
318     GstVideoFrame * outframe, gint cur_field_idx)
319 {
320   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
321   GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
322   GstDeinterlaceScanlineData scanlines;
323   guint8 *dest;
324   const guint8 *field0, *field1, *field2, *fieldp;
325   guint cur_field_flags = history[cur_field_idx].flags;
326   gint i;
327   gint frame_height = GST_VIDEO_INFO_HEIGHT (self->parent.vinfo);
328   gint stride = self->parent.row_stride[0];
329
330   g_assert (self->interpolate_scanline_packed != NULL);
331   g_assert (self->copy_scanline_packed != NULL);
332
333   if (cur_field_idx > 0) {
334     fieldp = GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx - 1].frame, 0);
335   } else {
336     fieldp = NULL;
337   }
338
339   dest = GST_VIDEO_FRAME_COMP_DATA (outframe, 0);
340
341   field0 = GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx].frame, 0);
342
343   g_assert (dm_class->fields_required <= 4);
344
345   if (cur_field_idx + 1 < history_count) {
346     field1 = GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx + 1].frame, 0);
347   } else {
348     field1 = NULL;
349   }
350
351   if (cur_field_idx + 2 < history_count) {
352     field2 = GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx + 2].frame, 0);
353   } else {
354     field2 = NULL;
355   }
356
357 #define CLAMP_LOW(i) (((i)<0) ? (i+2) : (i))
358 #define CLAMP_HI(i) (((i)>=(frame_height)) ? (i-2) : (i))
359 #define LINE(x,i) ((x) + CLAMP_HI(CLAMP_LOW(i)) * (stride))
360 #define LINE2(x,i) ((x) ? LINE(x,i) : NULL)
361
362   for (i = 0; i < frame_height; i++) {
363     memset (&scanlines, 0, sizeof (scanlines));
364     scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
365
366     if (!((i & 1) ^ scanlines.bottom_field)) {
367       /* copying */
368       scanlines.tp = LINE2 (fieldp, i - 1);
369       scanlines.bp = LINE2 (fieldp, i + 1);
370
371       scanlines.tt0 = LINE2 (field0, (i - 2 >= 0) ? i - 2 : i);
372       scanlines.m0 = LINE2 (field0, i);
373       scanlines.bb0 = LINE2 (field0, (i + 2 < frame_height ? i + 2 : i));
374
375       scanlines.t1 = LINE2 (field1, i - 1);
376       scanlines.b1 = LINE2 (field1, i + 1);
377
378       scanlines.tt2 = LINE2 (field2, (i - 2 >= 0) ? i - 2 : i);
379       scanlines.m2 = LINE2 (field2, i);
380       scanlines.bb2 = LINE2 (field2, (i + 2 < frame_height ? i + 2 : i));
381
382       self->copy_scanline_packed (self, LINE (dest, i), &scanlines);
383     } else {
384       /* interpolating */
385       scanlines.ttp = LINE2 (fieldp, (i - 2 >= 0) ? i - 2 : i);
386       scanlines.mp = LINE2 (fieldp, i);
387       scanlines.bbp = LINE2 (fieldp, (i + 2 < frame_height ? i + 2 : i));
388
389       scanlines.t0 = LINE2 (field0, i - 1);
390       scanlines.b0 = LINE2 (field0, i + 1);
391
392       scanlines.tt1 = LINE2 (field1, (i - 2 >= 0) ? i - 2 : i);
393       scanlines.m1 = LINE2 (field1, i);
394       scanlines.bb1 = LINE2 (field1, (i + 2 < frame_height ? i + 2 : i));
395
396       scanlines.t2 = LINE2 (field2, i - 1);
397       scanlines.b2 = LINE2 (field2, i + 1);
398
399       self->interpolate_scanline_packed (self, LINE (dest, i), &scanlines);
400     }
401   }
402 }
403
404 static void
405     gst_deinterlace_simple_method_interpolate_scanline_planar_y
406     (GstDeinterlaceSimpleMethod * self, guint8 * out,
407     const GstDeinterlaceScanlineData * scanlines)
408 {
409   memcpy (out, scanlines->m1, self->parent.row_stride[0]);
410 }
411
412 static void
413 gst_deinterlace_simple_method_copy_scanline_planar_y (GstDeinterlaceSimpleMethod
414     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
415 {
416   memcpy (out, scanlines->m0, self->parent.row_stride[0]);
417 }
418
419 static void
420     gst_deinterlace_simple_method_interpolate_scanline_planar_u
421     (GstDeinterlaceSimpleMethod * self, guint8 * out,
422     const GstDeinterlaceScanlineData * scanlines)
423 {
424   memcpy (out, scanlines->m1, self->parent.row_stride[1]);
425 }
426
427 static void
428 gst_deinterlace_simple_method_copy_scanline_planar_u (GstDeinterlaceSimpleMethod
429     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
430 {
431   memcpy (out, scanlines->m0, self->parent.row_stride[1]);
432 }
433
434 static void
435     gst_deinterlace_simple_method_interpolate_scanline_planar_v
436     (GstDeinterlaceSimpleMethod * self, guint8 * out,
437     const GstDeinterlaceScanlineData * scanlines)
438 {
439   memcpy (out, scanlines->m1, self->parent.row_stride[2]);
440 }
441
442 static void
443 gst_deinterlace_simple_method_copy_scanline_planar_v (GstDeinterlaceSimpleMethod
444     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
445 {
446   memcpy (out, scanlines->m0, self->parent.row_stride[2]);
447 }
448
449 static void
450     gst_deinterlace_simple_method_deinterlace_frame_planar_plane
451     (GstDeinterlaceSimpleMethod * self, guint8 * dest, const guint8 * field0,
452     const guint8 * field1, const guint8 * field2, const guint8 * fieldp,
453     guint cur_field_flags,
454     gint plane, GstDeinterlaceSimpleMethodFunction copy_scanline,
455     GstDeinterlaceSimpleMethodFunction interpolate_scanline)
456 {
457   GstDeinterlaceScanlineData scanlines;
458   gint i;
459   gint frame_height = self->parent.height[plane];
460   gint stride = self->parent.row_stride[plane];
461
462   g_assert (interpolate_scanline != NULL);
463   g_assert (copy_scanline != NULL);
464
465   for (i = 0; i < frame_height; i++) {
466     memset (&scanlines, 0, sizeof (scanlines));
467     scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
468
469     if (!((i & 1) ^ scanlines.bottom_field)) {
470       /* copying */
471       scanlines.tp = LINE2 (fieldp, i - 1);
472       scanlines.bp = LINE2 (fieldp, i + 1);
473
474       scanlines.tt0 = LINE2 (field0, (i - 2 >= 0) ? i - 2 : i);
475       scanlines.m0 = LINE2 (field0, i);
476       scanlines.bb0 = LINE2 (field0, (i + 2 < frame_height ? i + 2 : i));
477
478       scanlines.t1 = LINE2 (field1, i - 1);
479       scanlines.b1 = LINE2 (field1, i + 1);
480
481       scanlines.tt2 = LINE2 (field2, (i - 2 >= 0) ? i - 2 : i);
482       scanlines.m2 = LINE2 (field2, i);
483       scanlines.bb2 = LINE2 (field2, (i + 2 < frame_height ? i + 2 : i));
484
485       copy_scanline (self, LINE (dest, i), &scanlines);
486     } else {
487       /* interpolating */
488       scanlines.ttp = LINE2 (fieldp, (i - 2 >= 0) ? i - 2 : i);
489       scanlines.mp = LINE2 (fieldp, i);
490       scanlines.bbp = LINE2 (fieldp, (i + 2 < frame_height ? i + 2 : i));
491
492       scanlines.t0 = LINE2 (field0, i - 1);
493       scanlines.b0 = LINE2 (field0, i + 1);
494
495       scanlines.tt1 = LINE2 (field1, (i - 2 >= 0) ? i - 2 : i);
496       scanlines.m1 = LINE2 (field1, i);
497       scanlines.bb1 = LINE2 (field1, (i + 2 < frame_height ? i + 2 : i));
498
499       scanlines.t2 = LINE2 (field2, i - 1);
500       scanlines.b2 = LINE2 (field2, i + 1);
501
502       interpolate_scanline (self, LINE (dest, i), &scanlines);
503     }
504   }
505 }
506
507 static void
508 gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod *
509     method, const GstDeinterlaceField * history, guint history_count,
510     GstVideoFrame * outframe, gint cur_field_idx)
511 {
512   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
513   GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
514   guint8 *out;
515   const guint8 *field0, *field1, *field2, *fieldp;
516   guint cur_field_flags = history[cur_field_idx].flags;
517   gint i;
518   GstDeinterlaceSimpleMethodFunction copy_scanline;
519   GstDeinterlaceSimpleMethodFunction interpolate_scanline;
520
521   g_assert (self->interpolate_scanline_planar[0] != NULL);
522   g_assert (self->interpolate_scanline_planar[1] != NULL);
523   g_assert (self->interpolate_scanline_planar[2] != NULL);
524   g_assert (self->copy_scanline_planar[0] != NULL);
525   g_assert (self->copy_scanline_planar[1] != NULL);
526   g_assert (self->copy_scanline_planar[2] != NULL);
527
528   for (i = 0; i < 3; i++) {
529     copy_scanline = self->copy_scanline_planar[i];
530     interpolate_scanline = self->interpolate_scanline_planar[i];
531
532     out = GST_VIDEO_FRAME_PLANE_DATA (outframe, i);
533
534     fieldp = NULL;
535     if (cur_field_idx > 0) {
536       fieldp = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx - 1].frame, i);
537     }
538
539     field0 = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx].frame, i);
540
541     g_assert (dm_class->fields_required <= 4);
542
543     field1 = NULL;
544     if (cur_field_idx + 1 < history_count) {
545       field1 = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx + 1].frame, i);
546     }
547
548     field2 = NULL;
549     if (cur_field_idx + 2 < history_count) {
550       field2 = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx + 2].frame, i);
551     }
552
553     gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, out,
554         field0, field1, field2, fieldp, cur_field_flags, i, copy_scanline,
555         interpolate_scanline);
556   }
557 }
558
559 static void
560 gst_deinterlace_simple_method_deinterlace_frame_nv12 (GstDeinterlaceMethod *
561     method, const GstDeinterlaceField * history, guint history_count,
562     GstVideoFrame * outframe, gint cur_field_idx)
563 {
564   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
565   GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
566   guint8 *out;
567   const guint8 *field0, *field1, *field2, *fieldp;
568   guint cur_field_flags = history[cur_field_idx].flags;
569   gint i;
570
571   g_assert (self->interpolate_scanline_packed != NULL);
572   g_assert (self->copy_scanline_packed != NULL);
573
574   for (i = 0; i < 2; i++) {
575     out = GST_VIDEO_FRAME_PLANE_DATA (outframe, i);
576
577     fieldp = NULL;
578     if (cur_field_idx > 0) {
579       fieldp = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx - 1].frame, i);
580     }
581
582     field0 = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx].frame, i);
583
584     g_assert (dm_class->fields_required <= 4);
585
586     field1 = NULL;
587     if (cur_field_idx + 1 < history_count) {
588       field1 = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx + 1].frame, i);
589     }
590
591     field2 = NULL;
592     if (cur_field_idx + 2 < history_count) {
593       field2 = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx + 2].frame, i);
594     }
595
596     gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, out,
597         field0, field1, field2, fieldp, cur_field_flags, i,
598         self->copy_scanline_packed, self->interpolate_scanline_packed);
599   }
600 }
601
602 static void
603 gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method,
604     GstVideoInfo * vinfo)
605 {
606   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
607   GstDeinterlaceSimpleMethodClass *klass =
608       GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS (self);
609
610   GST_DEINTERLACE_METHOD_CLASS
611       (gst_deinterlace_simple_method_parent_class)->setup (method, vinfo);
612
613   self->interpolate_scanline_packed = NULL;
614   self->copy_scanline_packed = NULL;
615
616   self->interpolate_scanline_planar[0] = NULL;
617   self->interpolate_scanline_planar[1] = NULL;
618   self->interpolate_scanline_planar[2] = NULL;
619   self->copy_scanline_planar[0] = NULL;
620   self->copy_scanline_planar[1] = NULL;
621   self->copy_scanline_planar[2] = NULL;
622
623   if (GST_VIDEO_INFO_FORMAT (vinfo) == GST_VIDEO_FORMAT_UNKNOWN)
624     return;
625
626   switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
627     case GST_VIDEO_FORMAT_YUY2:
628       self->interpolate_scanline_packed = klass->interpolate_scanline_yuy2;
629       self->copy_scanline_packed = klass->copy_scanline_yuy2;
630       break;
631     case GST_VIDEO_FORMAT_YVYU:
632       self->interpolate_scanline_packed = klass->interpolate_scanline_yvyu;
633       self->copy_scanline_packed = klass->copy_scanline_yvyu;
634       break;
635     case GST_VIDEO_FORMAT_UYVY:
636       self->interpolate_scanline_packed = klass->interpolate_scanline_uyvy;
637       self->copy_scanline_packed = klass->copy_scanline_uyvy;
638       break;
639     case GST_VIDEO_FORMAT_AYUV:
640       self->interpolate_scanline_packed = klass->interpolate_scanline_ayuv;
641       self->copy_scanline_packed = klass->copy_scanline_ayuv;
642       break;
643     case GST_VIDEO_FORMAT_ARGB:
644     case GST_VIDEO_FORMAT_xRGB:
645       self->interpolate_scanline_packed = klass->interpolate_scanline_argb;
646       self->copy_scanline_packed = klass->copy_scanline_argb;
647       break;
648     case GST_VIDEO_FORMAT_ABGR:
649     case GST_VIDEO_FORMAT_xBGR:
650       self->interpolate_scanline_packed = klass->interpolate_scanline_abgr;
651       self->copy_scanline_packed = klass->copy_scanline_abgr;
652       break;
653     case GST_VIDEO_FORMAT_RGBA:
654     case GST_VIDEO_FORMAT_RGBx:
655       self->interpolate_scanline_packed = klass->interpolate_scanline_rgba;
656       self->copy_scanline_packed = klass->copy_scanline_rgba;
657       break;
658     case GST_VIDEO_FORMAT_BGRA:
659     case GST_VIDEO_FORMAT_BGRx:
660       self->interpolate_scanline_packed = klass->interpolate_scanline_bgra;
661       self->copy_scanline_packed = klass->copy_scanline_bgra;
662       break;
663     case GST_VIDEO_FORMAT_RGB:
664       self->interpolate_scanline_packed = klass->interpolate_scanline_rgb;
665       self->copy_scanline_packed = klass->copy_scanline_rgb;
666       break;
667     case GST_VIDEO_FORMAT_BGR:
668       self->interpolate_scanline_packed = klass->interpolate_scanline_bgr;
669       self->copy_scanline_packed = klass->copy_scanline_bgr;
670       break;
671     case GST_VIDEO_FORMAT_NV12:
672       self->interpolate_scanline_packed = klass->interpolate_scanline_nv12;
673       self->copy_scanline_packed = klass->copy_scanline_nv12;
674       break;
675     case GST_VIDEO_FORMAT_NV21:
676       self->interpolate_scanline_packed = klass->interpolate_scanline_nv21;
677       self->copy_scanline_packed = klass->copy_scanline_nv21;
678       break;
679     case GST_VIDEO_FORMAT_I420:
680     case GST_VIDEO_FORMAT_YV12:
681     case GST_VIDEO_FORMAT_Y444:
682     case GST_VIDEO_FORMAT_Y42B:
683     case GST_VIDEO_FORMAT_Y41B:
684       self->interpolate_scanline_planar[0] =
685           klass->interpolate_scanline_planar_y;
686       self->copy_scanline_planar[0] = klass->copy_scanline_planar_y;
687       self->interpolate_scanline_planar[1] =
688           klass->interpolate_scanline_planar_u;
689       self->copy_scanline_planar[1] = klass->copy_scanline_planar_u;
690       self->interpolate_scanline_planar[2] =
691           klass->interpolate_scanline_planar_v;
692       self->copy_scanline_planar[2] = klass->copy_scanline_planar_v;
693       break;
694     default:
695       break;
696   }
697 }
698
699 static void
700 gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass
701     * klass)
702 {
703   GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass;
704
705   dm_class->deinterlace_frame_ayuv =
706       gst_deinterlace_simple_method_deinterlace_frame_packed;
707   dm_class->deinterlace_frame_yuy2 =
708       gst_deinterlace_simple_method_deinterlace_frame_packed;
709   dm_class->deinterlace_frame_yvyu =
710       gst_deinterlace_simple_method_deinterlace_frame_packed;
711   dm_class->deinterlace_frame_uyvy =
712       gst_deinterlace_simple_method_deinterlace_frame_packed;
713   dm_class->deinterlace_frame_argb =
714       gst_deinterlace_simple_method_deinterlace_frame_packed;
715   dm_class->deinterlace_frame_abgr =
716       gst_deinterlace_simple_method_deinterlace_frame_packed;
717   dm_class->deinterlace_frame_rgba =
718       gst_deinterlace_simple_method_deinterlace_frame_packed;
719   dm_class->deinterlace_frame_bgra =
720       gst_deinterlace_simple_method_deinterlace_frame_packed;
721   dm_class->deinterlace_frame_rgb =
722       gst_deinterlace_simple_method_deinterlace_frame_packed;
723   dm_class->deinterlace_frame_bgr =
724       gst_deinterlace_simple_method_deinterlace_frame_packed;
725   dm_class->deinterlace_frame_i420 =
726       gst_deinterlace_simple_method_deinterlace_frame_planar;
727   dm_class->deinterlace_frame_yv12 =
728       gst_deinterlace_simple_method_deinterlace_frame_planar;
729   dm_class->deinterlace_frame_y444 =
730       gst_deinterlace_simple_method_deinterlace_frame_planar;
731   dm_class->deinterlace_frame_y42b =
732       gst_deinterlace_simple_method_deinterlace_frame_planar;
733   dm_class->deinterlace_frame_y41b =
734       gst_deinterlace_simple_method_deinterlace_frame_planar;
735   dm_class->deinterlace_frame_nv12 =
736       gst_deinterlace_simple_method_deinterlace_frame_nv12;
737   dm_class->deinterlace_frame_nv21 =
738       gst_deinterlace_simple_method_deinterlace_frame_nv12;
739   dm_class->fields_required = 2;
740   dm_class->setup = gst_deinterlace_simple_method_setup;
741   dm_class->supported = gst_deinterlace_simple_method_supported;
742
743   klass->interpolate_scanline_yuy2 =
744       gst_deinterlace_simple_method_interpolate_scanline_packed;
745   klass->copy_scanline_yuy2 =
746       gst_deinterlace_simple_method_copy_scanline_packed;
747   klass->interpolate_scanline_yvyu =
748       gst_deinterlace_simple_method_interpolate_scanline_packed;
749   klass->copy_scanline_yvyu =
750       gst_deinterlace_simple_method_copy_scanline_packed;
751   klass->interpolate_scanline_ayuv =
752       gst_deinterlace_simple_method_interpolate_scanline_packed;
753   klass->copy_scanline_ayuv =
754       gst_deinterlace_simple_method_copy_scanline_packed;
755   klass->interpolate_scanline_uyvy =
756       gst_deinterlace_simple_method_interpolate_scanline_packed;
757   klass->copy_scanline_uyvy =
758       gst_deinterlace_simple_method_copy_scanline_packed;
759   klass->interpolate_scanline_nv12 =
760       gst_deinterlace_simple_method_interpolate_scanline_packed;
761   klass->copy_scanline_nv12 =
762       gst_deinterlace_simple_method_copy_scanline_packed;
763
764   klass->interpolate_scanline_argb =
765       gst_deinterlace_simple_method_interpolate_scanline_packed;
766   klass->copy_scanline_argb =
767       gst_deinterlace_simple_method_copy_scanline_packed;
768   klass->interpolate_scanline_abgr =
769       gst_deinterlace_simple_method_interpolate_scanline_packed;
770   klass->copy_scanline_abgr =
771       gst_deinterlace_simple_method_copy_scanline_packed;
772
773   klass->interpolate_scanline_rgba =
774       gst_deinterlace_simple_method_interpolate_scanline_packed;
775   klass->copy_scanline_rgba =
776       gst_deinterlace_simple_method_copy_scanline_packed;
777   klass->interpolate_scanline_bgra =
778       gst_deinterlace_simple_method_interpolate_scanline_packed;
779   klass->copy_scanline_bgra =
780       gst_deinterlace_simple_method_copy_scanline_packed;
781   klass->interpolate_scanline_rgb =
782       gst_deinterlace_simple_method_interpolate_scanline_packed;
783   klass->copy_scanline_rgb = gst_deinterlace_simple_method_copy_scanline_packed;
784   klass->interpolate_scanline_bgr =
785       gst_deinterlace_simple_method_interpolate_scanline_packed;
786   klass->copy_scanline_bgr = gst_deinterlace_simple_method_copy_scanline_packed;
787
788   klass->interpolate_scanline_planar_y =
789       gst_deinterlace_simple_method_interpolate_scanline_planar_y;
790   klass->copy_scanline_planar_y =
791       gst_deinterlace_simple_method_copy_scanline_planar_y;
792   klass->interpolate_scanline_planar_u =
793       gst_deinterlace_simple_method_interpolate_scanline_planar_u;
794   klass->copy_scanline_planar_u =
795       gst_deinterlace_simple_method_copy_scanline_planar_u;
796   klass->interpolate_scanline_planar_v =
797       gst_deinterlace_simple_method_interpolate_scanline_planar_v;
798   klass->copy_scanline_planar_v =
799       gst_deinterlace_simple_method_copy_scanline_planar_v;
800 }
801
802 static void
803 gst_deinterlace_simple_method_init (GstDeinterlaceSimpleMethod * self)
804 {
805 }