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