docs: get rid of 'Since: 0.10.x' markers
[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., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, 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   GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
110
111   self->vinfo = vinfo;
112
113   self->deinterlace_frame = NULL;
114
115   if (GST_VIDEO_INFO_FORMAT (self->vinfo) == GST_VIDEO_FORMAT_UNKNOWN)
116     return;
117
118   switch (GST_VIDEO_INFO_FORMAT (self->vinfo)) {
119     case GST_VIDEO_FORMAT_YUY2:
120       self->deinterlace_frame = klass->deinterlace_frame_yuy2;
121       break;
122     case GST_VIDEO_FORMAT_YVYU:
123       self->deinterlace_frame = klass->deinterlace_frame_yvyu;
124       break;
125     case GST_VIDEO_FORMAT_UYVY:
126       self->deinterlace_frame = klass->deinterlace_frame_uyvy;
127       break;
128     case GST_VIDEO_FORMAT_I420:
129       self->deinterlace_frame = klass->deinterlace_frame_i420;
130       break;
131     case GST_VIDEO_FORMAT_YV12:
132       self->deinterlace_frame = klass->deinterlace_frame_yv12;
133       break;
134     case GST_VIDEO_FORMAT_Y444:
135       self->deinterlace_frame = klass->deinterlace_frame_y444;
136       break;
137     case GST_VIDEO_FORMAT_Y42B:
138       self->deinterlace_frame = klass->deinterlace_frame_y42b;
139       break;
140     case GST_VIDEO_FORMAT_Y41B:
141       self->deinterlace_frame = klass->deinterlace_frame_y41b;
142       break;
143     case GST_VIDEO_FORMAT_AYUV:
144       self->deinterlace_frame = klass->deinterlace_frame_ayuv;
145       break;
146     case GST_VIDEO_FORMAT_NV12:
147       self->deinterlace_frame = klass->deinterlace_frame_nv12;
148       break;
149     case GST_VIDEO_FORMAT_NV21:
150       self->deinterlace_frame = klass->deinterlace_frame_nv21;
151       break;
152     case GST_VIDEO_FORMAT_ARGB:
153     case GST_VIDEO_FORMAT_xRGB:
154       self->deinterlace_frame = klass->deinterlace_frame_argb;
155       break;
156     case GST_VIDEO_FORMAT_ABGR:
157     case GST_VIDEO_FORMAT_xBGR:
158       self->deinterlace_frame = klass->deinterlace_frame_abgr;
159       break;
160     case GST_VIDEO_FORMAT_RGBA:
161     case GST_VIDEO_FORMAT_RGBx:
162       self->deinterlace_frame = klass->deinterlace_frame_rgba;
163       break;
164     case GST_VIDEO_FORMAT_BGRA:
165     case GST_VIDEO_FORMAT_BGRx:
166       self->deinterlace_frame = klass->deinterlace_frame_bgra;
167       break;
168     case GST_VIDEO_FORMAT_RGB:
169       self->deinterlace_frame = klass->deinterlace_frame_rgb;
170       break;
171     case GST_VIDEO_FORMAT_BGR:
172       self->deinterlace_frame = klass->deinterlace_frame_bgr;
173       break;
174     default:
175       self->deinterlace_frame = NULL;
176       break;
177   }
178 }
179
180 static void
181 gst_deinterlace_method_class_init (GstDeinterlaceMethodClass * klass)
182 {
183   klass->setup = gst_deinterlace_method_setup_impl;
184   klass->supported = gst_deinterlace_method_supported_impl;
185 }
186
187 static void
188 gst_deinterlace_method_init (GstDeinterlaceMethod * self)
189 {
190   self->vinfo = NULL;
191 }
192
193 void
194 gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self,
195     const GstDeinterlaceField * history, guint history_count,
196     GstVideoFrame * outframe, int cur_field_idx)
197 {
198   g_assert (self->deinterlace_frame != NULL);
199   self->deinterlace_frame (self, history, history_count, outframe,
200       cur_field_idx);
201 }
202
203 gint
204 gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self)
205 {
206   GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
207
208   return klass->fields_required;
209 }
210
211 gint
212 gst_deinterlace_method_get_latency (GstDeinterlaceMethod * self)
213 {
214   GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
215
216   return klass->latency;
217 }
218
219 G_DEFINE_ABSTRACT_TYPE (GstDeinterlaceSimpleMethod,
220     gst_deinterlace_simple_method, GST_TYPE_DEINTERLACE_METHOD);
221
222 static gboolean
223 gst_deinterlace_simple_method_supported (GstDeinterlaceMethodClass * mklass,
224     GstVideoFormat format, gint width, gint height)
225 {
226   GstDeinterlaceSimpleMethodClass *klass =
227       GST_DEINTERLACE_SIMPLE_METHOD_CLASS (mklass);
228
229   if (!GST_DEINTERLACE_METHOD_CLASS
230       (gst_deinterlace_simple_method_parent_class)->supported (mklass, format,
231           width, height))
232     return FALSE;
233
234   switch (format) {
235     case GST_VIDEO_FORMAT_ARGB:
236     case GST_VIDEO_FORMAT_xRGB:
237       return (klass->interpolate_scanline_argb != NULL
238           && klass->copy_scanline_argb != NULL);
239     case GST_VIDEO_FORMAT_RGBA:
240     case GST_VIDEO_FORMAT_RGBx:
241       return (klass->interpolate_scanline_rgba != NULL
242           && klass->copy_scanline_rgba != NULL);
243     case GST_VIDEO_FORMAT_ABGR:
244     case GST_VIDEO_FORMAT_xBGR:
245       return (klass->interpolate_scanline_abgr != NULL
246           && klass->copy_scanline_abgr != NULL);
247     case GST_VIDEO_FORMAT_BGRA:
248     case GST_VIDEO_FORMAT_BGRx:
249       return (klass->interpolate_scanline_bgra != NULL
250           && klass->copy_scanline_bgra != NULL);
251     case GST_VIDEO_FORMAT_RGB:
252       return (klass->interpolate_scanline_rgb != NULL
253           && klass->copy_scanline_rgb != NULL);
254     case GST_VIDEO_FORMAT_BGR:
255       return (klass->interpolate_scanline_bgr != NULL
256           && klass->copy_scanline_bgr != NULL);
257     case GST_VIDEO_FORMAT_YUY2:
258       return (klass->interpolate_scanline_yuy2 != NULL
259           && klass->copy_scanline_yuy2 != NULL);
260     case GST_VIDEO_FORMAT_YVYU:
261       return (klass->interpolate_scanline_yvyu != NULL
262           && klass->copy_scanline_yvyu != NULL);
263     case GST_VIDEO_FORMAT_UYVY:
264       return (klass->interpolate_scanline_uyvy != NULL
265           && klass->copy_scanline_uyvy != NULL);
266     case GST_VIDEO_FORMAT_AYUV:
267       return (klass->interpolate_scanline_ayuv != NULL
268           && klass->copy_scanline_ayuv != NULL);
269     case GST_VIDEO_FORMAT_NV12:
270       return (klass->interpolate_scanline_nv12 != NULL
271           && klass->copy_scanline_nv12 != NULL);
272     case GST_VIDEO_FORMAT_NV21:
273       return (klass->interpolate_scanline_nv21 != NULL
274           && klass->copy_scanline_nv21 != NULL);
275     case GST_VIDEO_FORMAT_I420:
276     case GST_VIDEO_FORMAT_YV12:
277     case GST_VIDEO_FORMAT_Y444:
278     case GST_VIDEO_FORMAT_Y42B:
279     case GST_VIDEO_FORMAT_Y41B:
280       return (klass->interpolate_scanline_planar_y != NULL
281           && klass->copy_scanline_planar_y != NULL &&
282           klass->interpolate_scanline_planar_u != NULL
283           && klass->copy_scanline_planar_u != NULL &&
284           klass->interpolate_scanline_planar_v != NULL
285           && klass->copy_scanline_planar_v != NULL);
286     default:
287       return FALSE;
288   }
289 }
290
291 static void
292     gst_deinterlace_simple_method_interpolate_scanline_packed
293     (GstDeinterlaceSimpleMethod * self, guint8 * out,
294     const GstDeinterlaceScanlineData * scanlines, guint stride)
295 {
296   memcpy (out, scanlines->m1, stride);
297 }
298
299 static void
300 gst_deinterlace_simple_method_copy_scanline_packed (GstDeinterlaceSimpleMethod *
301     self, guint8 * out, const GstDeinterlaceScanlineData * scanlines,
302     guint stride)
303 {
304   memcpy (out, scanlines->m0, stride);
305 }
306
307 static void
308 gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod *
309     method, const GstDeinterlaceField * history, guint history_count,
310     GstVideoFrame * outframe, gint cur_field_idx)
311 {
312   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
313   GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
314   GstDeinterlaceScanlineData scanlines;
315   guint cur_field_flags;
316   gint i;
317   gint frame_height, frame_width;
318   GstVideoFrame *framep, *frame0, *frame1, *frame2;
319
320   g_assert (self->interpolate_scanline_packed != NULL);
321   g_assert (self->copy_scanline_packed != NULL);
322
323   frame_height = GST_VIDEO_FRAME_HEIGHT (outframe);
324   frame_width = GST_VIDEO_FRAME_PLANE_STRIDE (outframe, 0);
325
326   frame0 = history[cur_field_idx].frame;
327   frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (frame0, 0));
328   cur_field_flags = history[cur_field_idx].flags;
329
330   framep = (cur_field_idx > 0 ? history[cur_field_idx - 1].frame : NULL);
331   if (framep)
332     frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (framep, 0));
333
334   g_assert (dm_class->fields_required <= 4);
335
336   frame1 =
337       (cur_field_idx + 1 <
338       history_count ? history[cur_field_idx + 1].frame : NULL);
339   if (frame1)
340     frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (frame1, 0));
341
342   frame2 =
343       (cur_field_idx + 2 <
344       history_count ? history[cur_field_idx + 2].frame : NULL);
345   if (frame2)
346     frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (frame2, 0));
347
348 #define CLAMP_LOW(i) (((i)<0) ? (i+2) : (i))
349 #define CLAMP_HI(i) (((i)>=(frame_height)) ? (i-2) : (i))
350 #define LINE(x,i) (((guint8*)GST_VIDEO_FRAME_PLANE_DATA((x),0)) + CLAMP_HI(CLAMP_LOW(i)) * \
351     GST_VIDEO_FRAME_PLANE_STRIDE((x),0))
352 #define LINE2(x,i) ((x) ? LINE(x,i) : NULL)
353
354   for (i = 0; i < frame_height; i++) {
355     memset (&scanlines, 0, sizeof (scanlines));
356     scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
357
358     if (!((i & 1) ^ scanlines.bottom_field)) {
359       /* copying */
360       scanlines.tp = LINE2 (framep, i - 1);
361       scanlines.bp = LINE2 (framep, i + 1);
362
363       scanlines.tt0 = LINE2 (frame0, (i - 2 >= 0) ? i - 2 : i);
364       scanlines.m0 = LINE2 (frame0, i);
365       scanlines.bb0 = LINE2 (frame0, (i + 2 < frame_height ? i + 2 : i));
366
367       scanlines.t1 = LINE2 (frame1, i - 1);
368       scanlines.b1 = LINE2 (frame1, i + 1);
369
370       scanlines.tt2 = LINE2 (frame2, (i - 2 >= 0) ? i - 2 : i);
371       scanlines.m2 = LINE2 (frame2, i);
372       scanlines.bb2 = LINE2 (frame2, (i + 2 < frame_height ? i + 2 : i));
373
374       self->copy_scanline_packed (self, LINE (outframe, i), &scanlines,
375           frame_width);
376     } else {
377       /* interpolating */
378       scanlines.ttp = LINE2 (framep, (i - 2 >= 0) ? i - 2 : i);
379       scanlines.mp = LINE2 (framep, i);
380       scanlines.bbp = LINE2 (framep, (i + 2 < frame_height ? i + 2 : i));
381
382       scanlines.t0 = LINE2 (frame0, i - 1);
383       scanlines.b0 = LINE2 (frame0, i + 1);
384
385       scanlines.tt1 = LINE2 (frame1, (i - 2 >= 0) ? i - 2 : i);
386       scanlines.m1 = LINE2 (frame1, i);
387       scanlines.bb1 = LINE2 (frame1, (i + 2 < frame_height ? i + 2 : i));
388
389       scanlines.t2 = LINE2 (frame2, i - 1);
390       scanlines.b2 = LINE2 (frame2, i + 1);
391
392       self->interpolate_scanline_packed (self, LINE (outframe, i), &scanlines,
393           frame_width);
394     }
395 #undef LINE
396 #undef LINE2
397   }
398 }
399
400 static void
401     gst_deinterlace_simple_method_interpolate_scanline_planar_y
402     (GstDeinterlaceSimpleMethod * self, guint8 * out,
403     const GstDeinterlaceScanlineData * scanlines, guint size)
404 {
405   memcpy (out, scanlines->m1, size);
406 }
407
408 static void
409 gst_deinterlace_simple_method_copy_scanline_planar_y (GstDeinterlaceSimpleMethod
410     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines, guint
411     size)
412 {
413   memcpy (out, scanlines->m0, size);
414 }
415
416 static void
417     gst_deinterlace_simple_method_interpolate_scanline_planar_u
418     (GstDeinterlaceSimpleMethod * self, guint8 * out,
419     const GstDeinterlaceScanlineData * scanlines, guint size)
420 {
421   memcpy (out, scanlines->m1, size);
422 }
423
424 static void
425 gst_deinterlace_simple_method_copy_scanline_planar_u (GstDeinterlaceSimpleMethod
426     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines, guint
427     size)
428 {
429   memcpy (out, scanlines->m0, size);
430 }
431
432 static void
433     gst_deinterlace_simple_method_interpolate_scanline_planar_v
434     (GstDeinterlaceSimpleMethod * self, guint8 * out,
435     const GstDeinterlaceScanlineData * scanlines, guint size)
436 {
437   memcpy (out, scanlines->m1, size);
438 }
439
440 static void
441 gst_deinterlace_simple_method_copy_scanline_planar_v (GstDeinterlaceSimpleMethod
442     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines, guint
443     size)
444 {
445   memcpy (out, scanlines->m0, size);
446 }
447
448 static void
449     gst_deinterlace_simple_method_deinterlace_frame_planar_plane
450     (GstDeinterlaceSimpleMethod * self, GstVideoFrame * dest,
451     const GstVideoFrame * frame0, const GstVideoFrame * frame1,
452     const GstVideoFrame * frame2, const GstVideoFrame * framep,
453     guint cur_field_flags, gint plane,
454     GstDeinterlaceSimpleMethodFunction copy_scanline,
455     GstDeinterlaceSimpleMethodFunction interpolate_scanline)
456 {
457   GstDeinterlaceScanlineData scanlines;
458   gint i;
459   gint frame_height, frame_width;
460
461   frame_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, plane);
462   frame_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, plane) *
463       GST_VIDEO_FRAME_COMP_PSTRIDE (dest, plane);
464
465   g_assert (interpolate_scanline != NULL);
466   g_assert (copy_scanline != NULL);
467
468 #define LINE(x,i) (((guint8*)GST_VIDEO_FRAME_PLANE_DATA((x),plane)) + CLAMP_HI(CLAMP_LOW(i)) * \
469     GST_VIDEO_FRAME_PLANE_STRIDE((x),plane))
470 #define LINE2(x,i) ((x) ? LINE(x,i) : NULL)
471
472   for (i = 0; i < frame_height; i++) {
473     memset (&scanlines, 0, sizeof (scanlines));
474     scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
475
476     if (!((i & 1) ^ scanlines.bottom_field)) {
477       /* copying */
478       scanlines.tp = LINE2 (framep, i - 1);
479       scanlines.bp = LINE2 (framep, i + 1);
480
481       scanlines.tt0 = LINE2 (frame0, (i - 2 >= 0) ? i - 2 : i);
482       scanlines.m0 = LINE2 (frame0, i);
483       scanlines.bb0 = LINE2 (frame0, (i + 2 < frame_height ? i + 2 : i));
484
485       scanlines.t1 = LINE2 (frame1, i - 1);
486       scanlines.b1 = LINE2 (frame1, i + 1);
487
488       scanlines.tt2 = LINE2 (frame2, (i - 2 >= 0) ? i - 2 : i);
489       scanlines.m2 = LINE2 (frame2, i);
490       scanlines.bb2 = LINE2 (frame2, (i + 2 < frame_height ? i + 2 : i));
491
492       copy_scanline (self, LINE (dest, i), &scanlines, frame_width);
493     } else {
494       /* interpolating */
495       scanlines.ttp = LINE2 (framep, (i - 2 >= 0) ? i - 2 : i);
496       scanlines.mp = LINE2 (framep, i);
497       scanlines.bbp = LINE2 (framep, (i + 2 < frame_height ? i + 2 : i));
498
499       scanlines.t0 = LINE2 (frame0, i - 1);
500       scanlines.b0 = LINE2 (frame0, i + 1);
501
502       scanlines.tt1 = LINE2 (frame1, (i - 2 >= 0) ? i - 2 : i);
503       scanlines.m1 = LINE2 (frame1, i);
504       scanlines.bb1 = LINE2 (frame1, (i + 2 < frame_height ? i + 2 : i));
505
506       scanlines.t2 = LINE2 (frame2, i - 1);
507       scanlines.b2 = LINE2 (frame2, i + 1);
508
509       interpolate_scanline (self, LINE (dest, i), &scanlines, frame_width);
510     }
511 #undef LINE
512 #undef LINE2
513   }
514 }
515
516 static void
517 gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod *
518     method, const GstDeinterlaceField * history, guint history_count,
519     GstVideoFrame * outframe, gint cur_field_idx)
520 {
521   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
522   GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
523   const GstVideoFrame *frame0, *frame1, *frame2, *framep;
524   guint cur_field_flags = history[cur_field_idx].flags;
525   gint i;
526   GstDeinterlaceSimpleMethodFunction copy_scanline;
527   GstDeinterlaceSimpleMethodFunction interpolate_scanline;
528
529   g_assert (self->interpolate_scanline_planar[0] != NULL);
530   g_assert (self->interpolate_scanline_planar[1] != NULL);
531   g_assert (self->interpolate_scanline_planar[2] != NULL);
532   g_assert (self->copy_scanline_planar[0] != NULL);
533   g_assert (self->copy_scanline_planar[1] != NULL);
534   g_assert (self->copy_scanline_planar[2] != NULL);
535
536   for (i = 0; i < 3; i++) {
537     copy_scanline = self->copy_scanline_planar[i];
538     interpolate_scanline = self->interpolate_scanline_planar[i];
539
540     framep = (cur_field_idx > 0 ? history[cur_field_idx - 1].frame : NULL);
541
542     frame0 = history[cur_field_idx].frame;
543
544     g_assert (dm_class->fields_required <= 4);
545
546     frame1 =
547         (cur_field_idx + 1 <
548         history_count ? history[cur_field_idx + 1].frame : NULL);
549     frame2 =
550         (cur_field_idx + 2 <
551         history_count ? history[cur_field_idx + 2].frame : NULL);
552
553     gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self,
554         outframe, frame0, frame1, frame2, framep, cur_field_flags, i,
555         copy_scanline, 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   const GstVideoFrame *frame0, *frame1, *frame2, *framep;
567   guint cur_field_flags = history[cur_field_idx].flags;
568   gint i;
569
570   g_assert (self->interpolate_scanline_packed != NULL);
571   g_assert (self->copy_scanline_packed != NULL);
572
573   for (i = 0; i < 2; i++) {
574     framep = (cur_field_idx > 0 ? history[cur_field_idx - 1].frame : NULL);
575
576     frame0 = history[cur_field_idx].frame;
577
578     g_assert (dm_class->fields_required <= 4);
579
580     frame1 =
581         (cur_field_idx + 1 <
582         history_count ? history[cur_field_idx + 1].frame : NULL);
583     frame2 =
584         (cur_field_idx + 2 <
585         history_count ? history[cur_field_idx + 2].frame : NULL);
586
587     gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self,
588         outframe, frame0, frame1, frame2, framep, cur_field_flags, i,
589         self->copy_scanline_packed, self->interpolate_scanline_packed);
590   }
591 }
592
593 static void
594 gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method,
595     GstVideoInfo * vinfo)
596 {
597   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
598   GstDeinterlaceSimpleMethodClass *klass =
599       GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS (self);
600
601   GST_DEINTERLACE_METHOD_CLASS
602       (gst_deinterlace_simple_method_parent_class)->setup (method, vinfo);
603
604   self->interpolate_scanline_packed = NULL;
605   self->copy_scanline_packed = NULL;
606
607   self->interpolate_scanline_planar[0] = NULL;
608   self->interpolate_scanline_planar[1] = NULL;
609   self->interpolate_scanline_planar[2] = NULL;
610   self->copy_scanline_planar[0] = NULL;
611   self->copy_scanline_planar[1] = NULL;
612   self->copy_scanline_planar[2] = NULL;
613
614   if (GST_VIDEO_INFO_FORMAT (vinfo) == GST_VIDEO_FORMAT_UNKNOWN)
615     return;
616
617   switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
618     case GST_VIDEO_FORMAT_YUY2:
619       self->interpolate_scanline_packed = klass->interpolate_scanline_yuy2;
620       self->copy_scanline_packed = klass->copy_scanline_yuy2;
621       break;
622     case GST_VIDEO_FORMAT_YVYU:
623       self->interpolate_scanline_packed = klass->interpolate_scanline_yvyu;
624       self->copy_scanline_packed = klass->copy_scanline_yvyu;
625       break;
626     case GST_VIDEO_FORMAT_UYVY:
627       self->interpolate_scanline_packed = klass->interpolate_scanline_uyvy;
628       self->copy_scanline_packed = klass->copy_scanline_uyvy;
629       break;
630     case GST_VIDEO_FORMAT_AYUV:
631       self->interpolate_scanline_packed = klass->interpolate_scanline_ayuv;
632       self->copy_scanline_packed = klass->copy_scanline_ayuv;
633       break;
634     case GST_VIDEO_FORMAT_ARGB:
635     case GST_VIDEO_FORMAT_xRGB:
636       self->interpolate_scanline_packed = klass->interpolate_scanline_argb;
637       self->copy_scanline_packed = klass->copy_scanline_argb;
638       break;
639     case GST_VIDEO_FORMAT_ABGR:
640     case GST_VIDEO_FORMAT_xBGR:
641       self->interpolate_scanline_packed = klass->interpolate_scanline_abgr;
642       self->copy_scanline_packed = klass->copy_scanline_abgr;
643       break;
644     case GST_VIDEO_FORMAT_RGBA:
645     case GST_VIDEO_FORMAT_RGBx:
646       self->interpolate_scanline_packed = klass->interpolate_scanline_rgba;
647       self->copy_scanline_packed = klass->copy_scanline_rgba;
648       break;
649     case GST_VIDEO_FORMAT_BGRA:
650     case GST_VIDEO_FORMAT_BGRx:
651       self->interpolate_scanline_packed = klass->interpolate_scanline_bgra;
652       self->copy_scanline_packed = klass->copy_scanline_bgra;
653       break;
654     case GST_VIDEO_FORMAT_RGB:
655       self->interpolate_scanline_packed = klass->interpolate_scanline_rgb;
656       self->copy_scanline_packed = klass->copy_scanline_rgb;
657       break;
658     case GST_VIDEO_FORMAT_BGR:
659       self->interpolate_scanline_packed = klass->interpolate_scanline_bgr;
660       self->copy_scanline_packed = klass->copy_scanline_bgr;
661       break;
662     case GST_VIDEO_FORMAT_NV12:
663       self->interpolate_scanline_packed = klass->interpolate_scanline_nv12;
664       self->copy_scanline_packed = klass->copy_scanline_nv12;
665       break;
666     case GST_VIDEO_FORMAT_NV21:
667       self->interpolate_scanline_packed = klass->interpolate_scanline_nv21;
668       self->copy_scanline_packed = klass->copy_scanline_nv21;
669       break;
670     case GST_VIDEO_FORMAT_I420:
671     case GST_VIDEO_FORMAT_YV12:
672     case GST_VIDEO_FORMAT_Y444:
673     case GST_VIDEO_FORMAT_Y42B:
674     case GST_VIDEO_FORMAT_Y41B:
675       self->interpolate_scanline_planar[0] =
676           klass->interpolate_scanline_planar_y;
677       self->copy_scanline_planar[0] = klass->copy_scanline_planar_y;
678       self->interpolate_scanline_planar[1] =
679           klass->interpolate_scanline_planar_u;
680       self->copy_scanline_planar[1] = klass->copy_scanline_planar_u;
681       self->interpolate_scanline_planar[2] =
682           klass->interpolate_scanline_planar_v;
683       self->copy_scanline_planar[2] = klass->copy_scanline_planar_v;
684       break;
685     default:
686       break;
687   }
688 }
689
690 static void
691 gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass
692     * klass)
693 {
694   GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass;
695
696   dm_class->deinterlace_frame_ayuv =
697       gst_deinterlace_simple_method_deinterlace_frame_packed;
698   dm_class->deinterlace_frame_yuy2 =
699       gst_deinterlace_simple_method_deinterlace_frame_packed;
700   dm_class->deinterlace_frame_yvyu =
701       gst_deinterlace_simple_method_deinterlace_frame_packed;
702   dm_class->deinterlace_frame_uyvy =
703       gst_deinterlace_simple_method_deinterlace_frame_packed;
704   dm_class->deinterlace_frame_argb =
705       gst_deinterlace_simple_method_deinterlace_frame_packed;
706   dm_class->deinterlace_frame_abgr =
707       gst_deinterlace_simple_method_deinterlace_frame_packed;
708   dm_class->deinterlace_frame_rgba =
709       gst_deinterlace_simple_method_deinterlace_frame_packed;
710   dm_class->deinterlace_frame_bgra =
711       gst_deinterlace_simple_method_deinterlace_frame_packed;
712   dm_class->deinterlace_frame_rgb =
713       gst_deinterlace_simple_method_deinterlace_frame_packed;
714   dm_class->deinterlace_frame_bgr =
715       gst_deinterlace_simple_method_deinterlace_frame_packed;
716   dm_class->deinterlace_frame_i420 =
717       gst_deinterlace_simple_method_deinterlace_frame_planar;
718   dm_class->deinterlace_frame_yv12 =
719       gst_deinterlace_simple_method_deinterlace_frame_planar;
720   dm_class->deinterlace_frame_y444 =
721       gst_deinterlace_simple_method_deinterlace_frame_planar;
722   dm_class->deinterlace_frame_y42b =
723       gst_deinterlace_simple_method_deinterlace_frame_planar;
724   dm_class->deinterlace_frame_y41b =
725       gst_deinterlace_simple_method_deinterlace_frame_planar;
726   dm_class->deinterlace_frame_nv12 =
727       gst_deinterlace_simple_method_deinterlace_frame_nv12;
728   dm_class->deinterlace_frame_nv21 =
729       gst_deinterlace_simple_method_deinterlace_frame_nv12;
730   dm_class->fields_required = 2;
731   dm_class->setup = gst_deinterlace_simple_method_setup;
732   dm_class->supported = gst_deinterlace_simple_method_supported;
733
734   klass->interpolate_scanline_yuy2 =
735       gst_deinterlace_simple_method_interpolate_scanline_packed;
736   klass->copy_scanline_yuy2 =
737       gst_deinterlace_simple_method_copy_scanline_packed;
738   klass->interpolate_scanline_yvyu =
739       gst_deinterlace_simple_method_interpolate_scanline_packed;
740   klass->copy_scanline_yvyu =
741       gst_deinterlace_simple_method_copy_scanline_packed;
742   klass->interpolate_scanline_ayuv =
743       gst_deinterlace_simple_method_interpolate_scanline_packed;
744   klass->copy_scanline_ayuv =
745       gst_deinterlace_simple_method_copy_scanline_packed;
746   klass->interpolate_scanline_uyvy =
747       gst_deinterlace_simple_method_interpolate_scanline_packed;
748   klass->copy_scanline_uyvy =
749       gst_deinterlace_simple_method_copy_scanline_packed;
750   klass->interpolate_scanline_nv12 =
751       gst_deinterlace_simple_method_interpolate_scanline_packed;
752   klass->copy_scanline_nv12 =
753       gst_deinterlace_simple_method_copy_scanline_packed;
754
755   klass->interpolate_scanline_argb =
756       gst_deinterlace_simple_method_interpolate_scanline_packed;
757   klass->copy_scanline_argb =
758       gst_deinterlace_simple_method_copy_scanline_packed;
759   klass->interpolate_scanline_abgr =
760       gst_deinterlace_simple_method_interpolate_scanline_packed;
761   klass->copy_scanline_abgr =
762       gst_deinterlace_simple_method_copy_scanline_packed;
763
764   klass->interpolate_scanline_rgba =
765       gst_deinterlace_simple_method_interpolate_scanline_packed;
766   klass->copy_scanline_rgba =
767       gst_deinterlace_simple_method_copy_scanline_packed;
768   klass->interpolate_scanline_bgra =
769       gst_deinterlace_simple_method_interpolate_scanline_packed;
770   klass->copy_scanline_bgra =
771       gst_deinterlace_simple_method_copy_scanline_packed;
772   klass->interpolate_scanline_rgb =
773       gst_deinterlace_simple_method_interpolate_scanline_packed;
774   klass->copy_scanline_rgb = gst_deinterlace_simple_method_copy_scanline_packed;
775   klass->interpolate_scanline_bgr =
776       gst_deinterlace_simple_method_interpolate_scanline_packed;
777   klass->copy_scanline_bgr = gst_deinterlace_simple_method_copy_scanline_packed;
778
779   klass->interpolate_scanline_planar_y =
780       gst_deinterlace_simple_method_interpolate_scanline_planar_y;
781   klass->copy_scanline_planar_y =
782       gst_deinterlace_simple_method_copy_scanline_planar_y;
783   klass->interpolate_scanline_planar_u =
784       gst_deinterlace_simple_method_interpolate_scanline_planar_u;
785   klass->copy_scanline_planar_u =
786       gst_deinterlace_simple_method_copy_scanline_planar_u;
787   klass->interpolate_scanline_planar_v =
788       gst_deinterlace_simple_method_interpolate_scanline_planar_v;
789   klass->copy_scanline_planar_v =
790       gst_deinterlace_simple_method_copy_scanline_planar_v;
791 }
792
793 static void
794 gst_deinterlace_simple_method_init (GstDeinterlaceSimpleMethod * self)
795 {
796 }