Tizen 2.0 Release
[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, int cur_field_idx)
210 {
211   g_assert (self->deinterlace_frame != NULL);
212   self->deinterlace_frame (self, history, history_count, outbuf, cur_field_idx);
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, gint cur_field_idx)
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, *fieldp;
328   guint cur_field_flags = history[cur_field_idx].flags;
329   gint i;
330   gint frame_height = self->parent.frame_height;
331   gint stride = self->parent.row_stride[0];
332
333   g_assert (self->interpolate_scanline_packed != NULL);
334   g_assert (self->copy_scanline_packed != NULL);
335
336   if (cur_field_idx > 0) {
337     fieldp = GST_BUFFER_DATA (history[cur_field_idx - 1].buf);
338   } else {
339     fieldp = NULL;
340   }
341
342   dest = GST_BUFFER_DATA (outbuf);
343   field0 = GST_BUFFER_DATA (history[cur_field_idx].buf);
344
345   g_assert (dm_class->fields_required <= 4);
346
347   if (cur_field_idx + 1 < history_count) {
348     field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf);
349   } else {
350     field1 = NULL;
351   }
352
353   if (cur_field_idx + 2 < history_count) {
354     field2 = GST_BUFFER_DATA (history[cur_field_idx + 2].buf);
355   } else {
356     field2 = NULL;
357   }
358
359 #define CLAMP_LOW(i) (((i)<0) ? (i+2) : (i))
360 #define CLAMP_HI(i) (((i)>=(frame_height)) ? (i-2) : (i))
361 #define LINE(x,i) ((x) + CLAMP_HI(CLAMP_LOW(i)) * (stride))
362 #define LINE2(x,i) ((x) ? LINE(x,i) : NULL)
363
364   for (i = 0; i < frame_height; i++) {
365     memset (&scanlines, 0, sizeof (scanlines));
366     scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
367
368     if (!((i & 1) ^ scanlines.bottom_field)) {
369       /* copying */
370       scanlines.tp = LINE2 (fieldp, i - 1);
371       scanlines.bp = LINE2 (fieldp, i + 1);
372
373       scanlines.tt0 = LINE2 (field0, (i - 2 >= 0) ? i - 2 : i);
374       scanlines.m0 = LINE2 (field0, i);
375       scanlines.bb0 = LINE2 (field0, (i + 2 < frame_height ? i + 2 : i));
376
377       scanlines.t1 = LINE2 (field1, i - 1);
378       scanlines.b1 = LINE2 (field1, i + 1);
379
380       scanlines.tt2 = LINE2 (field2, (i - 2 >= 0) ? i - 2 : i);
381       scanlines.m2 = LINE2 (field2, i);
382       scanlines.bb2 = LINE2 (field2, (i + 2 < frame_height ? i + 2 : i));
383
384       self->copy_scanline_packed (self, LINE (dest, i), &scanlines);
385     } else {
386       /* interpolating */
387       scanlines.ttp = LINE2 (fieldp, (i - 2 >= 0) ? i - 2 : i);
388       scanlines.mp = LINE2 (fieldp, i);
389       scanlines.bbp = LINE2 (fieldp, (i + 2 < frame_height ? i + 2 : i));
390
391       scanlines.t0 = LINE2 (field0, i - 1);
392       scanlines.b0 = LINE2 (field0, i + 1);
393
394       scanlines.tt1 = LINE2 (field1, (i - 2 >= 0) ? i - 2 : i);
395       scanlines.m1 = LINE2 (field1, i);
396       scanlines.bb1 = LINE2 (field1, (i + 2 < frame_height ? i + 2 : i));
397
398       scanlines.t2 = LINE2 (field2, i - 1);
399       scanlines.b2 = LINE2 (field2, i + 1);
400
401       self->interpolate_scanline_packed (self, LINE (dest, i), &scanlines);
402     }
403   }
404 }
405
406 static void
407     gst_deinterlace_simple_method_interpolate_scanline_planar_y
408     (GstDeinterlaceSimpleMethod * self, guint8 * out,
409     const GstDeinterlaceScanlineData * scanlines)
410 {
411   memcpy (out, scanlines->m1, self->parent.row_stride[0]);
412 }
413
414 static void
415 gst_deinterlace_simple_method_copy_scanline_planar_y (GstDeinterlaceSimpleMethod
416     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
417 {
418   memcpy (out, scanlines->m0, self->parent.row_stride[0]);
419 }
420
421 static void
422     gst_deinterlace_simple_method_interpolate_scanline_planar_u
423     (GstDeinterlaceSimpleMethod * self, guint8 * out,
424     const GstDeinterlaceScanlineData * scanlines)
425 {
426   memcpy (out, scanlines->m1, self->parent.row_stride[1]);
427 }
428
429 static void
430 gst_deinterlace_simple_method_copy_scanline_planar_u (GstDeinterlaceSimpleMethod
431     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
432 {
433   memcpy (out, scanlines->m0, self->parent.row_stride[1]);
434 }
435
436 static void
437     gst_deinterlace_simple_method_interpolate_scanline_planar_v
438     (GstDeinterlaceSimpleMethod * self, guint8 * out,
439     const GstDeinterlaceScanlineData * scanlines)
440 {
441   memcpy (out, scanlines->m1, self->parent.row_stride[2]);
442 }
443
444 static void
445 gst_deinterlace_simple_method_copy_scanline_planar_v (GstDeinterlaceSimpleMethod
446     * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
447 {
448   memcpy (out, scanlines->m0, self->parent.row_stride[2]);
449 }
450
451 static void
452     gst_deinterlace_simple_method_deinterlace_frame_planar_plane
453     (GstDeinterlaceSimpleMethod * self, guint8 * dest, const guint8 * field0,
454     const guint8 * field1, const guint8 * field2, const guint8 * fieldp,
455     guint cur_field_flags,
456     gint plane, GstDeinterlaceSimpleMethodFunction copy_scanline,
457     GstDeinterlaceSimpleMethodFunction interpolate_scanline)
458 {
459   GstDeinterlaceScanlineData scanlines;
460   gint i;
461   gint frame_height = self->parent.height[plane];
462   gint stride = self->parent.row_stride[plane];
463
464   g_assert (interpolate_scanline != NULL);
465   g_assert (copy_scanline != NULL);
466
467   for (i = 0; i < frame_height; i++) {
468     memset (&scanlines, 0, sizeof (scanlines));
469     scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
470
471     if (!((i & 1) ^ scanlines.bottom_field)) {
472       /* copying */
473       scanlines.tp = LINE2 (fieldp, i - 1);
474       scanlines.bp = LINE2 (fieldp, i + 1);
475
476       scanlines.tt0 = LINE2 (field0, (i - 2 >= 0) ? i - 2 : i);
477       scanlines.m0 = LINE2 (field0, i);
478       scanlines.bb0 = LINE2 (field0, (i + 2 < frame_height ? i + 2 : i));
479
480       scanlines.t1 = LINE2 (field1, i - 1);
481       scanlines.b1 = LINE2 (field1, i + 1);
482
483       scanlines.tt2 = LINE2 (field2, (i - 2 >= 0) ? i - 2 : i);
484       scanlines.m2 = LINE2 (field2, i);
485       scanlines.bb2 = LINE2 (field2, (i + 2 < frame_height ? i + 2 : i));
486
487       copy_scanline (self, LINE (dest, i), &scanlines);
488     } else {
489       /* interpolating */
490       scanlines.ttp = LINE2 (fieldp, (i - 2 >= 0) ? i - 2 : i);
491       scanlines.mp = LINE2 (fieldp, i);
492       scanlines.bbp = LINE2 (fieldp, (i + 2 < frame_height ? i + 2 : i));
493
494       scanlines.t0 = LINE2 (field0, i - 1);
495       scanlines.b0 = LINE2 (field0, i + 1);
496
497       scanlines.tt1 = LINE2 (field1, (i - 2 >= 0) ? i - 2 : i);
498       scanlines.m1 = LINE2 (field1, i);
499       scanlines.bb1 = LINE2 (field1, (i + 2 < frame_height ? i + 2 : i));
500
501       scanlines.t2 = LINE2 (field2, i - 1);
502       scanlines.b2 = LINE2 (field2, i + 1);
503
504       interpolate_scanline (self, LINE (dest, i), &scanlines);
505     }
506   }
507 }
508
509 static void
510 gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod *
511     method, const GstDeinterlaceField * history, guint history_count,
512     GstBuffer * outbuf, gint cur_field_idx)
513 {
514   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
515   GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
516   guint8 *out;
517   const guint8 *field0, *field1, *field2, *fieldp;
518   guint cur_field_flags = history[cur_field_idx].flags;
519   gint i, offset;
520   GstDeinterlaceSimpleMethodFunction copy_scanline;
521   GstDeinterlaceSimpleMethodFunction interpolate_scanline;
522
523   g_assert (self->interpolate_scanline_planar[0] != NULL);
524   g_assert (self->interpolate_scanline_planar[1] != NULL);
525   g_assert (self->interpolate_scanline_planar[2] != NULL);
526   g_assert (self->copy_scanline_planar[0] != NULL);
527   g_assert (self->copy_scanline_planar[1] != NULL);
528   g_assert (self->copy_scanline_planar[2] != NULL);
529
530   for (i = 0; i < 3; i++) {
531     offset = self->parent.offset[i];
532     copy_scanline = self->copy_scanline_planar[i];
533     interpolate_scanline = self->interpolate_scanline_planar[i];
534
535     out = GST_BUFFER_DATA (outbuf) + offset;
536
537     fieldp = NULL;
538     if (cur_field_idx > 0) {
539       fieldp = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + offset;
540     }
541
542     field0 = GST_BUFFER_DATA (history[cur_field_idx].buf) + offset;
543
544     g_assert (dm_class->fields_required <= 4);
545
546     field1 = NULL;
547     if (cur_field_idx + 1 < history_count) {
548       field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf) + offset;
549     }
550
551     field2 = NULL;
552     if (cur_field_idx + 2 < history_count) {
553       field2 = GST_BUFFER_DATA (history[cur_field_idx + 2].buf) + offset;
554     }
555
556     gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, out,
557         field0, field1, field2, fieldp, cur_field_flags, i, copy_scanline,
558         interpolate_scanline);
559   }
560 }
561
562 static void
563 gst_deinterlace_simple_method_deinterlace_frame_nv12 (GstDeinterlaceMethod *
564     method, const GstDeinterlaceField * history, guint history_count,
565     GstBuffer * outbuf, gint cur_field_idx)
566 {
567   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
568   GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
569   guint8 *out;
570   const guint8 *field0, *field1, *field2, *fieldp;
571   guint cur_field_flags = history[cur_field_idx].flags;
572   gint i, offset;
573
574   g_assert (self->interpolate_scanline_packed != NULL);
575   g_assert (self->copy_scanline_packed != NULL);
576
577   for (i = 0; i < 2; i++) {
578     offset = self->parent.offset[i];
579
580     out = GST_BUFFER_DATA (outbuf) + offset;
581
582     fieldp = NULL;
583     if (cur_field_idx > 0) {
584       fieldp = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + offset;
585     }
586
587     field0 = GST_BUFFER_DATA (history[cur_field_idx].buf) + offset;
588
589     g_assert (dm_class->fields_required <= 4);
590
591     field1 = NULL;
592     if (cur_field_idx + 1 < history_count) {
593       field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf) + offset;
594     }
595
596     field2 = NULL;
597     if (cur_field_idx + 2 < history_count) {
598       field2 = GST_BUFFER_DATA (history[cur_field_idx + 2].buf) + offset;
599     }
600
601     gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, out,
602         field0, field1, field2, fieldp, cur_field_flags, i,
603         self->copy_scanline_packed, self->interpolate_scanline_packed);
604   }
605 }
606
607 static void
608 gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method,
609     GstVideoFormat format, gint width, gint height)
610 {
611   GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
612   GstDeinterlaceSimpleMethodClass *klass =
613       GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS (self);
614
615   GST_DEINTERLACE_METHOD_CLASS
616       (gst_deinterlace_simple_method_parent_class)->setup (method, format,
617       width, height);
618
619   self->interpolate_scanline_packed = NULL;
620   self->copy_scanline_packed = NULL;
621
622   self->interpolate_scanline_planar[0] = NULL;
623   self->interpolate_scanline_planar[1] = NULL;
624   self->interpolate_scanline_planar[2] = NULL;
625   self->copy_scanline_planar[0] = NULL;
626   self->copy_scanline_planar[1] = NULL;
627   self->copy_scanline_planar[2] = NULL;
628
629   if (format == GST_VIDEO_FORMAT_UNKNOWN)
630     return;
631
632   switch (format) {
633     case GST_VIDEO_FORMAT_YUY2:
634       self->interpolate_scanline_packed = klass->interpolate_scanline_yuy2;
635       self->copy_scanline_packed = klass->copy_scanline_yuy2;
636       break;
637     case GST_VIDEO_FORMAT_YVYU:
638       self->interpolate_scanline_packed = klass->interpolate_scanline_yvyu;
639       self->copy_scanline_packed = klass->copy_scanline_yvyu;
640       break;
641     case GST_VIDEO_FORMAT_UYVY:
642       self->interpolate_scanline_packed = klass->interpolate_scanline_uyvy;
643       self->copy_scanline_packed = klass->copy_scanline_uyvy;
644       break;
645     case GST_VIDEO_FORMAT_AYUV:
646       self->interpolate_scanline_packed = klass->interpolate_scanline_ayuv;
647       self->copy_scanline_packed = klass->copy_scanline_ayuv;
648       break;
649     case GST_VIDEO_FORMAT_ARGB:
650     case GST_VIDEO_FORMAT_xRGB:
651       self->interpolate_scanline_packed = klass->interpolate_scanline_argb;
652       self->copy_scanline_packed = klass->copy_scanline_argb;
653       break;
654     case GST_VIDEO_FORMAT_ABGR:
655     case GST_VIDEO_FORMAT_xBGR:
656       self->interpolate_scanline_packed = klass->interpolate_scanline_abgr;
657       self->copy_scanline_packed = klass->copy_scanline_abgr;
658       break;
659     case GST_VIDEO_FORMAT_RGBA:
660     case GST_VIDEO_FORMAT_RGBx:
661       self->interpolate_scanline_packed = klass->interpolate_scanline_rgba;
662       self->copy_scanline_packed = klass->copy_scanline_rgba;
663       break;
664     case GST_VIDEO_FORMAT_BGRA:
665     case GST_VIDEO_FORMAT_BGRx:
666       self->interpolate_scanline_packed = klass->interpolate_scanline_bgra;
667       self->copy_scanline_packed = klass->copy_scanline_bgra;
668       break;
669     case GST_VIDEO_FORMAT_RGB:
670       self->interpolate_scanline_packed = klass->interpolate_scanline_rgb;
671       self->copy_scanline_packed = klass->copy_scanline_rgb;
672       break;
673     case GST_VIDEO_FORMAT_BGR:
674       self->interpolate_scanline_packed = klass->interpolate_scanline_bgr;
675       self->copy_scanline_packed = klass->copy_scanline_bgr;
676       break;
677     case GST_VIDEO_FORMAT_NV12:
678       self->interpolate_scanline_packed = klass->interpolate_scanline_nv12;
679       self->copy_scanline_packed = klass->copy_scanline_nv12;
680       break;
681     case GST_VIDEO_FORMAT_NV21:
682       self->interpolate_scanline_packed = klass->interpolate_scanline_nv21;
683       self->copy_scanline_packed = klass->copy_scanline_nv21;
684       break;
685     case GST_VIDEO_FORMAT_I420:
686     case GST_VIDEO_FORMAT_YV12:
687     case GST_VIDEO_FORMAT_Y444:
688     case GST_VIDEO_FORMAT_Y42B:
689     case GST_VIDEO_FORMAT_Y41B:
690       self->interpolate_scanline_planar[0] =
691           klass->interpolate_scanline_planar_y;
692       self->copy_scanline_planar[0] = klass->copy_scanline_planar_y;
693       self->interpolate_scanline_planar[1] =
694           klass->interpolate_scanline_planar_u;
695       self->copy_scanline_planar[1] = klass->copy_scanline_planar_u;
696       self->interpolate_scanline_planar[2] =
697           klass->interpolate_scanline_planar_v;
698       self->copy_scanline_planar[2] = klass->copy_scanline_planar_v;
699       break;
700     default:
701       break;
702   }
703 }
704
705 static void
706 gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass
707     * klass)
708 {
709   GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass;
710
711   dm_class->deinterlace_frame_ayuv =
712       gst_deinterlace_simple_method_deinterlace_frame_packed;
713   dm_class->deinterlace_frame_yuy2 =
714       gst_deinterlace_simple_method_deinterlace_frame_packed;
715   dm_class->deinterlace_frame_yvyu =
716       gst_deinterlace_simple_method_deinterlace_frame_packed;
717   dm_class->deinterlace_frame_uyvy =
718       gst_deinterlace_simple_method_deinterlace_frame_packed;
719   dm_class->deinterlace_frame_argb =
720       gst_deinterlace_simple_method_deinterlace_frame_packed;
721   dm_class->deinterlace_frame_abgr =
722       gst_deinterlace_simple_method_deinterlace_frame_packed;
723   dm_class->deinterlace_frame_rgba =
724       gst_deinterlace_simple_method_deinterlace_frame_packed;
725   dm_class->deinterlace_frame_bgra =
726       gst_deinterlace_simple_method_deinterlace_frame_packed;
727   dm_class->deinterlace_frame_rgb =
728       gst_deinterlace_simple_method_deinterlace_frame_packed;
729   dm_class->deinterlace_frame_bgr =
730       gst_deinterlace_simple_method_deinterlace_frame_packed;
731   dm_class->deinterlace_frame_i420 =
732       gst_deinterlace_simple_method_deinterlace_frame_planar;
733   dm_class->deinterlace_frame_yv12 =
734       gst_deinterlace_simple_method_deinterlace_frame_planar;
735   dm_class->deinterlace_frame_y444 =
736       gst_deinterlace_simple_method_deinterlace_frame_planar;
737   dm_class->deinterlace_frame_y42b =
738       gst_deinterlace_simple_method_deinterlace_frame_planar;
739   dm_class->deinterlace_frame_y41b =
740       gst_deinterlace_simple_method_deinterlace_frame_planar;
741   dm_class->deinterlace_frame_nv12 =
742       gst_deinterlace_simple_method_deinterlace_frame_nv12;
743   dm_class->deinterlace_frame_nv21 =
744       gst_deinterlace_simple_method_deinterlace_frame_nv12;
745   dm_class->fields_required = 2;
746   dm_class->setup = gst_deinterlace_simple_method_setup;
747   dm_class->supported = gst_deinterlace_simple_method_supported;
748
749   klass->interpolate_scanline_yuy2 =
750       gst_deinterlace_simple_method_interpolate_scanline_packed;
751   klass->copy_scanline_yuy2 =
752       gst_deinterlace_simple_method_copy_scanline_packed;
753   klass->interpolate_scanline_yvyu =
754       gst_deinterlace_simple_method_interpolate_scanline_packed;
755   klass->copy_scanline_yvyu =
756       gst_deinterlace_simple_method_copy_scanline_packed;
757   klass->interpolate_scanline_ayuv =
758       gst_deinterlace_simple_method_interpolate_scanline_packed;
759   klass->copy_scanline_ayuv =
760       gst_deinterlace_simple_method_copy_scanline_packed;
761   klass->interpolate_scanline_uyvy =
762       gst_deinterlace_simple_method_interpolate_scanline_packed;
763   klass->copy_scanline_uyvy =
764       gst_deinterlace_simple_method_copy_scanline_packed;
765   klass->interpolate_scanline_nv12 =
766       gst_deinterlace_simple_method_interpolate_scanline_packed;
767   klass->copy_scanline_nv12 =
768       gst_deinterlace_simple_method_copy_scanline_packed;
769
770   klass->interpolate_scanline_argb =
771       gst_deinterlace_simple_method_interpolate_scanline_packed;
772   klass->copy_scanline_argb =
773       gst_deinterlace_simple_method_copy_scanline_packed;
774   klass->interpolate_scanline_abgr =
775       gst_deinterlace_simple_method_interpolate_scanline_packed;
776   klass->copy_scanline_abgr =
777       gst_deinterlace_simple_method_copy_scanline_packed;
778
779   klass->interpolate_scanline_rgba =
780       gst_deinterlace_simple_method_interpolate_scanline_packed;
781   klass->copy_scanline_rgba =
782       gst_deinterlace_simple_method_copy_scanline_packed;
783   klass->interpolate_scanline_bgra =
784       gst_deinterlace_simple_method_interpolate_scanline_packed;
785   klass->copy_scanline_bgra =
786       gst_deinterlace_simple_method_copy_scanline_packed;
787   klass->interpolate_scanline_rgb =
788       gst_deinterlace_simple_method_interpolate_scanline_packed;
789   klass->copy_scanline_rgb = gst_deinterlace_simple_method_copy_scanline_packed;
790   klass->interpolate_scanline_bgr =
791       gst_deinterlace_simple_method_interpolate_scanline_packed;
792   klass->copy_scanline_bgr = gst_deinterlace_simple_method_copy_scanline_packed;
793
794   klass->interpolate_scanline_planar_y =
795       gst_deinterlace_simple_method_interpolate_scanline_planar_y;
796   klass->copy_scanline_planar_y =
797       gst_deinterlace_simple_method_copy_scanline_planar_y;
798   klass->interpolate_scanline_planar_u =
799       gst_deinterlace_simple_method_interpolate_scanline_planar_u;
800   klass->copy_scanline_planar_u =
801       gst_deinterlace_simple_method_copy_scanline_planar_u;
802   klass->interpolate_scanline_planar_v =
803       gst_deinterlace_simple_method_interpolate_scanline_planar_v;
804   klass->copy_scanline_planar_v =
805       gst_deinterlace_simple_method_copy_scanline_planar_v;
806 }
807
808 static void
809 gst_deinterlace_simple_method_init (GstDeinterlaceSimpleMethod * self)
810 {
811 }