4 * Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
5 * Copyright (C) 2008,2010 Sebastian Dröge <slomo@collabora.co.uk>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 * Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs.
25 * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578
32 #include "greedyhmacros.h"
39 #include "gstdeinterlacemethod.h"
44 #define GST_TYPE_DEINTERLACE_METHOD_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ())
45 #define GST_IS_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
46 #define GST_IS_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
47 #define GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass))
48 #define GST_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyH))
49 #define GST_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass))
50 #define GST_DEINTERLACE_METHOD_GREEDY_H_CAST(obj) ((GstDeinterlaceMethodGreedyH*)(obj))
54 GstDeinterlaceMethod parent;
56 guint max_comb, motion_threshold, motion_sense;
57 } GstDeinterlaceMethodGreedyH;
59 typedef void (*ScanlineFunction) (GstDeinterlaceMethodGreedyH * self,
60 const guint8 * L2, const guint8 * L1, const guint8 * L3, const guint8 * L2P,
61 guint8 * Dest, gint width);
65 GstDeinterlaceMethodClass parent_class;
66 ScanlineFunction scanline_yuy2; /* This is for YVYU too */
67 ScanlineFunction scanline_uyvy;
68 ScanlineFunction scanline_ayuv;
69 ScanlineFunction scanline_planar_y;
70 ScanlineFunction scanline_planar_uv;
71 } GstDeinterlaceMethodGreedyHClass;
74 greedyh_scanline_C_ayuv (GstDeinterlaceMethodGreedyH * self, const guint8 * L1,
75 const guint8 * L2, const guint8 * L3, const guint8 * L2P, guint8 * Dest,
79 guint8 l1, l1_1, l3, l3_1;
81 guint8 avg__1[4] = { 0, };
88 guint8 l2_diff, lp2_diff;
90 guint max_comb = self->max_comb;
91 guint motion_sense = self->motion_sense;
92 guint motion_threshold = self->motion_threshold;
95 for (Pos = 0; Pos < width; Pos++) {
96 for (Comp = 0; Comp < 4; Comp++) {
100 if (Pos == width - 1) {
108 /* Average of L1 and L3 */
115 /* Average of next L1 and next L3 */
116 avg_1 = (l1_1 + l3_1) / 2;
118 /* Calculate average of one pixel forward and previous */
119 avg_s = (avg__1[Comp] + avg_1) / 2;
121 /* Calculate average of center and surrounding pixels */
122 avg_sc = (avg + avg_s) / 2;
127 /* Get best L2/L2P, i.e. least diff from above average */
131 l2_diff = ABS (l2 - avg_sc);
133 lp2_diff = ABS (lp2 - avg_sc);
135 if (l2_diff > lp2_diff)
140 /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */
144 if (max < 256 - max_comb)
154 out = CLAMP (best, min, max);
157 /* Do motion compensation for luma, i.e. how much
158 * the weave pixel differs */
159 mov = ABS (l2 - lp2);
160 if (mov > motion_threshold)
161 mov -= motion_threshold;
165 mov = mov * motion_sense;
169 /* Weighted sum on clipped weave pixel and average */
170 out = (out * (256 - mov) + avg_sc * mov) / 256;
185 greedyh_scanline_C_yuy2 (GstDeinterlaceMethodGreedyH * self, const guint8 * L1,
186 const guint8 * L2, const guint8 * L3, const guint8 * L2P, guint8 * Dest,
190 guint8 l1_l, l1_1_l, l3_l, l3_1_l;
191 guint8 l1_c, l1_1_c, l3_c, l3_1_c;
192 guint8 avg_l, avg_c, avg_l_1, avg_c_1;
193 guint8 avg_l__1 = 0, avg_c__1 = 0;
194 guint8 avg_s_l, avg_s_c;
195 guint8 avg_sc_l, avg_sc_c;
196 guint8 best_l, best_c;
199 guint8 l2_l, l2_c, lp2_l, lp2_c;
200 guint8 l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff;
201 guint8 min_l, min_c, max_l, max_c;
202 guint max_comb = self->max_comb;
203 guint motion_sense = self->motion_sense;
204 guint motion_threshold = self->motion_threshold;
207 for (Pos = 0; Pos < width; Pos++) {
213 if (Pos == width - 1) {
225 /* Average of L1 and L3 */
226 avg_l = (l1_l + l3_l) / 2;
227 avg_c = (l1_c + l3_c) / 2;
234 /* Average of next L1 and next L3 */
235 avg_l_1 = (l1_1_l + l3_1_l) / 2;
236 avg_c_1 = (l1_1_c + l3_1_c) / 2;
238 /* Calculate average of one pixel forward and previous */
239 avg_s_l = (avg_l__1 + avg_l_1) / 2;
240 avg_s_c = (avg_c__1 + avg_c_1) / 2;
242 /* Calculate average of center and surrounding pixels */
243 avg_sc_l = (avg_l + avg_s_l) / 2;
244 avg_sc_c = (avg_c + avg_s_c) / 2;
250 /* Get best L2/L2P, i.e. least diff from above average */
256 l2_l_diff = ABS (l2_l - avg_sc_l);
257 l2_c_diff = ABS (l2_c - avg_sc_c);
259 lp2_l_diff = ABS (lp2_l - avg_sc_l);
260 lp2_c_diff = ABS (lp2_c - avg_sc_c);
262 if (l2_l_diff > lp2_l_diff)
267 if (l2_c_diff > lp2_c_diff)
272 /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */
273 max_l = MAX (l1_l, l3_l);
274 min_l = MIN (l1_l, l3_l);
276 if (max_l < 256 - max_comb)
281 if (min_l > max_comb)
286 max_c = MAX (l1_c, l3_c);
287 min_c = MIN (l1_c, l3_c);
289 if (max_c < 256 - max_comb)
294 if (min_c > max_comb)
299 out_l = CLAMP (best_l, min_l, max_l);
300 out_c = CLAMP (best_c, min_c, max_c);
302 /* Do motion compensation for luma, i.e. how much
303 * the weave pixel differs */
304 mov_l = ABS (l2_l - lp2_l);
305 if (mov_l > motion_threshold)
306 mov_l -= motion_threshold;
310 mov_l = mov_l * motion_sense;
314 /* Weighted sum on clipped weave pixel and average */
315 out_l = (out_l * (256 - mov_l) + avg_sc_l * mov_l) / 256;
329 greedyh_scanline_C_uyvy (GstDeinterlaceMethodGreedyH * self, const guint8 * L1,
330 const guint8 * L2, const guint8 * L3, const guint8 * L2P, guint8 * Dest,
334 guint8 l1_l, l1_1_l, l3_l, l3_1_l;
335 guint8 l1_c, l1_1_c, l3_c, l3_1_c;
336 guint8 avg_l, avg_c, avg_l_1, avg_c_1;
337 guint8 avg_l__1 = 0, avg_c__1 = 0;
338 guint8 avg_s_l, avg_s_c;
339 guint8 avg_sc_l, avg_sc_c;
340 guint8 best_l, best_c;
343 guint8 l2_l, l2_c, lp2_l, lp2_c;
344 guint8 l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff;
345 guint8 min_l, min_c, max_l, max_c;
346 guint max_comb = self->max_comb;
347 guint motion_sense = self->motion_sense;
348 guint motion_threshold = self->motion_threshold;
351 for (Pos = 0; Pos < width; Pos++) {
357 if (Pos == width - 1) {
369 /* Average of L1 and L3 */
370 avg_l = (l1_l + l3_l) / 2;
371 avg_c = (l1_c + l3_c) / 2;
378 /* Average of next L1 and next L3 */
379 avg_l_1 = (l1_1_l + l3_1_l) / 2;
380 avg_c_1 = (l1_1_c + l3_1_c) / 2;
382 /* Calculate average of one pixel forward and previous */
383 avg_s_l = (avg_l__1 + avg_l_1) / 2;
384 avg_s_c = (avg_c__1 + avg_c_1) / 2;
386 /* Calculate average of center and surrounding pixels */
387 avg_sc_l = (avg_l + avg_s_l) / 2;
388 avg_sc_c = (avg_c + avg_s_c) / 2;
394 /* Get best L2/L2P, i.e. least diff from above average */
400 l2_l_diff = ABS (l2_l - avg_sc_l);
401 l2_c_diff = ABS (l2_c - avg_sc_c);
403 lp2_l_diff = ABS (lp2_l - avg_sc_l);
404 lp2_c_diff = ABS (lp2_c - avg_sc_c);
406 if (l2_l_diff > lp2_l_diff)
411 if (l2_c_diff > lp2_c_diff)
416 /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */
417 max_l = MAX (l1_l, l3_l);
418 min_l = MIN (l1_l, l3_l);
420 if (max_l < 256 - max_comb)
425 if (min_l > max_comb)
430 max_c = MAX (l1_c, l3_c);
431 min_c = MIN (l1_c, l3_c);
433 if (max_c < 256 - max_comb)
438 if (min_c > max_comb)
443 out_l = CLAMP (best_l, min_l, max_l);
444 out_c = CLAMP (best_c, min_c, max_c);
446 /* Do motion compensation for luma, i.e. how much
447 * the weave pixel differs */
448 mov_l = ABS (l2_l - lp2_l);
449 if (mov_l > motion_threshold)
450 mov_l -= motion_threshold;
454 mov_l = mov_l * motion_sense;
458 /* Weighted sum on clipped weave pixel and average */
459 out_l = (out_l * (256 - mov_l) + avg_sc_l * mov_l) / 256;
473 greedyh_scanline_C_planar_y (GstDeinterlaceMethodGreedyH * self,
474 const guint8 * L1, const guint8 * L2, const guint8 * L3, const guint8 * L2P,
475 guint8 * Dest, gint width)
478 guint8 l1, l1_1, l3, l3_1;
487 guint8 l2_diff, lp2_diff;
489 guint max_comb = self->max_comb;
490 guint motion_sense = self->motion_sense;
491 guint motion_threshold = self->motion_threshold;
493 for (Pos = 0; Pos < width; Pos++) {
497 if (Pos == width - 1) {
505 /* Average of L1 and L3 */
512 /* Average of next L1 and next L3 */
513 avg_1 = (l1_1 + l3_1) / 2;
515 /* Calculate average of one pixel forward and previous */
516 avg_s = (avg__1 + avg_1) / 2;
518 /* Calculate average of center and surrounding pixels */
519 avg_sc = (avg + avg_s) / 2;
524 /* Get best L2/L2P, i.e. least diff from above average */
528 l2_diff = ABS (l2 - avg_sc);
530 lp2_diff = ABS (lp2 - avg_sc);
532 if (l2_diff > lp2_diff)
537 /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */
541 if (max < 256 - max_comb)
551 out = CLAMP (best, min, max);
553 /* Do motion compensation for luma, i.e. how much
554 * the weave pixel differs */
555 mov = ABS (l2 - lp2);
556 if (mov > motion_threshold)
557 mov -= motion_threshold;
561 mov = mov * motion_sense;
565 /* Weighted sum on clipped weave pixel and average */
566 out = (out * (256 - mov) + avg_sc * mov) / 256;
579 greedyh_scanline_C_planar_uv (GstDeinterlaceMethodGreedyH * self,
580 const guint8 * L1, const guint8 * L2, const guint8 * L3, const guint8 * L2P,
581 guint8 * Dest, gint width)
584 guint8 l1, l1_1, l3, l3_1;
592 guint8 l2_diff, lp2_diff;
594 guint max_comb = self->max_comb;
596 for (Pos = 0; Pos < width; Pos++) {
600 if (Pos == width - 1) {
608 /* Average of L1 and L3 */
615 /* Average of next L1 and next L3 */
616 avg_1 = (l1_1 + l3_1) / 2;
618 /* Calculate average of one pixel forward and previous */
619 avg_s = (avg__1 + avg_1) / 2;
621 /* Calculate average of center and surrounding pixels */
622 avg_sc = (avg + avg_s) / 2;
627 /* Get best L2/L2P, i.e. least diff from above average */
631 l2_diff = ABS (l2 - avg_sc);
633 lp2_diff = ABS (lp2 - avg_sc);
635 if (l2_diff > lp2_diff)
640 /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */
644 if (max < 256 - max_comb)
654 out = CLAMP (best, min, max);
669 #define SIMD_TYPE MMXEXT
670 #define C_FUNCT_YUY2 greedyh_scanline_C_yuy2
671 #define C_FUNCT_UYVY greedyh_scanline_C_uyvy
672 #define C_FUNCT_PLANAR_Y greedyh_scanline_C_planar_y
673 #define C_FUNCT_PLANAR_UV greedyh_scanline_C_planar_uv
674 #define FUNCT_NAME_YUY2 greedyh_scanline_MMXEXT_yuy2
675 #define FUNCT_NAME_UYVY greedyh_scanline_MMXEXT_uyvy
676 #define FUNCT_NAME_PLANAR_Y greedyh_scanline_MMXEXT_planar_y
677 #define FUNCT_NAME_PLANAR_UV greedyh_scanline_MMXEXT_planar_uv
678 #include "greedyh.asm"
681 #undef FUNCT_NAME_YUY2
682 #undef FUNCT_NAME_UYVY
683 #undef FUNCT_NAME_PLANAR_Y
684 #undef FUNCT_NAME_PLANAR_UV
687 #define SIMD_TYPE 3DNOW
688 #define FUNCT_NAME_YUY2 greedyh_scanline_3DNOW_yuy2
689 #define FUNCT_NAME_UYVY greedyh_scanline_3DNOW_uyvy
690 #define FUNCT_NAME_PLANAR_Y greedyh_scanline_3DNOW_planar_y
691 #define FUNCT_NAME_PLANAR_UV greedyh_scanline_3DNOW_planar_uv
692 #include "greedyh.asm"
695 #undef FUNCT_NAME_YUY2
696 #undef FUNCT_NAME_UYVY
697 #undef FUNCT_NAME_PLANAR_Y
698 #undef FUNCT_NAME_PLANAR_UV
701 #define SIMD_TYPE MMX
702 #define FUNCT_NAME_YUY2 greedyh_scanline_MMX_yuy2
703 #define FUNCT_NAME_UYVY greedyh_scanline_MMX_uyvy
704 #define FUNCT_NAME_PLANAR_Y greedyh_scanline_MMX_planar_y
705 #define FUNCT_NAME_PLANAR_UV greedyh_scanline_MMX_planar_uv
706 #include "greedyh.asm"
709 #undef FUNCT_NAME_YUY2
710 #undef FUNCT_NAME_UYVY
711 #undef FUNCT_NAME_PLANAR_Y
712 #undef FUNCT_NAME_PLANAR_UV
714 #undef C_FUNCT_PLANAR_Y
715 #undef C_FUNCT_PLANAR_UV
720 deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method,
721 const GstDeinterlaceField * history, guint history_count,
722 GstBuffer * outbuf, int cur_field_idx)
724 GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method);
725 GstDeinterlaceMethodGreedyHClass *klass =
726 GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
729 gint RowStride = method->row_stride[0];
730 gint FieldHeight = method->frame_height / 2;
731 gint Pitch = method->row_stride[0] * 2;
732 const guint8 *L1; // ptr to Line1, of 3
733 const guint8 *L2; // ptr to Line2, the weave line
734 const guint8 *L3; // ptr to Line3
735 const guint8 *L2P; // ptr to prev Line2
736 guint8 *Dest = GST_BUFFER_DATA (outbuf);
737 ScanlineFunction scanline;
739 if (cur_field_idx + 2 > history_count || cur_field_idx < 1) {
740 GstDeinterlaceMethod *backup_method;
742 backup_method = g_object_new (gst_deinterlace_method_linear_get_type (),
745 gst_deinterlace_method_setup (backup_method, method->format,
746 method->frame_width, method->frame_height);
747 gst_deinterlace_method_deinterlace_frame (backup_method,
748 history, history_count, outbuf, cur_field_idx);
750 g_object_unref (backup_method);
756 switch (method->format) {
757 case GST_VIDEO_FORMAT_YUY2:
758 case GST_VIDEO_FORMAT_YVYU:
759 scanline = klass->scanline_yuy2;
761 case GST_VIDEO_FORMAT_UYVY:
762 scanline = klass->scanline_uyvy;
764 case GST_VIDEO_FORMAT_AYUV:
765 scanline = klass->scanline_ayuv;
768 g_assert_not_reached ();
772 // copy first even line no matter what, and the first odd line if we're
773 // processing an EVEN field. (note diff from other deint rtns.)
775 if (history[cur_field_idx - 1].flags == PICTURE_INTERLACED_BOTTOM) {
778 L1 = GST_BUFFER_DATA (history[cur_field_idx - 2].buf);
779 if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM)
782 L2 = GST_BUFFER_DATA (history[cur_field_idx - 1].buf);
783 if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM)
787 L2P = GST_BUFFER_DATA (history[cur_field_idx - 3].buf);
788 if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM)
791 // copy first even line
792 memcpy (Dest, L1, RowStride);
796 L1 = GST_BUFFER_DATA (history[cur_field_idx - 2].buf);
797 if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM)
800 L2 = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + Pitch;
801 if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM)
805 L2P = GST_BUFFER_DATA (history[cur_field_idx - 3].buf) + Pitch;
806 if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM)
809 // copy first even line
810 memcpy (Dest, L1, RowStride);
812 // then first odd line
813 memcpy (Dest, L1, RowStride);
817 for (Line = 0; Line < (FieldHeight - 1); ++Line) {
818 scanline (self, L1, L2, L3, L2P, Dest, RowStride);
820 memcpy (Dest, L3, RowStride);
830 memcpy (Dest, L2, RowStride);
835 deinterlace_frame_di_greedyh_planar_plane (GstDeinterlaceMethodGreedyH * self,
836 const guint8 * L1, const guint8 * L2, const guint8 * L3, const guint8 * L2P,
837 guint8 * Dest, gint RowStride, gint FieldHeight, gint Pitch, gint InfoIsOdd,
838 ScanlineFunction scanline)
842 // copy first even line no matter what, and the first odd line if we're
843 // processing an EVEN field. (note diff from other deint rtns.)
846 // copy first even line
847 memcpy (Dest, L1, RowStride);
850 // copy first even line
851 memcpy (Dest, L1, RowStride);
853 // then first odd line
854 memcpy (Dest, L1, RowStride);
858 for (Line = 0; Line < (FieldHeight - 1); ++Line) {
859 scanline (self, L1, L2, L3, L2P, Dest, RowStride);
861 memcpy (Dest, L3, RowStride);
871 memcpy (Dest, L2, RowStride);
876 deinterlace_frame_di_greedyh_planar (GstDeinterlaceMethod * method,
877 const GstDeinterlaceField * history, guint history_count,
878 GstBuffer * outbuf, int cur_field_idx)
880 GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method);
881 GstDeinterlaceMethodGreedyHClass *klass =
882 GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
887 const guint8 *L1; // ptr to Line1, of 3
888 const guint8 *L2; // ptr to Line2, the weave line
889 const guint8 *L3; // ptr to Line3
890 const guint8 *L2P; // ptr to prev Line2
894 ScanlineFunction scanline;
896 if (cur_field_idx + 2 > history_count || cur_field_idx < 1) {
897 GstDeinterlaceMethod *backup_method;
899 backup_method = g_object_new (gst_deinterlace_method_linear_get_type (),
902 gst_deinterlace_method_setup (backup_method, method->format,
903 method->frame_width, method->frame_height);
904 gst_deinterlace_method_deinterlace_frame (backup_method,
905 history, history_count, outbuf, cur_field_idx);
907 g_object_unref (backup_method);
913 for (i = 0; i < 3; i++) {
914 Offset = method->offset[i];
916 InfoIsOdd = (history[cur_field_idx - 1].flags == PICTURE_INTERLACED_BOTTOM);
917 RowStride = method->row_stride[i];
918 FieldHeight = method->height[i] / 2;
919 Pitch = method->row_stride[i] * 2;
922 scanline = klass->scanline_planar_y;
924 scanline = klass->scanline_planar_uv;
926 Dest = GST_BUFFER_DATA (outbuf) + Offset;
928 L1 = GST_BUFFER_DATA (history[cur_field_idx - 2].buf) + Offset;
929 if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM)
932 L2 = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + Offset;
933 if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM)
937 L2P = GST_BUFFER_DATA (history[cur_field_idx - 3].buf) + Offset;
938 if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM)
941 deinterlace_frame_di_greedyh_planar_plane (self, L1, L2, L3, L2P, Dest,
942 RowStride, FieldHeight, Pitch, InfoIsOdd, scanline);
946 G_DEFINE_TYPE (GstDeinterlaceMethodGreedyH, gst_deinterlace_method_greedy_h,
947 GST_TYPE_DEINTERLACE_METHOD);
953 PROP_MOTION_THRESHOLD,
958 gst_deinterlace_method_greedy_h_set_property (GObject * object, guint prop_id,
959 const GValue * value, GParamSpec * pspec)
961 GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
965 self->max_comb = g_value_get_uint (value);
967 case PROP_MOTION_THRESHOLD:
968 self->motion_threshold = g_value_get_uint (value);
970 case PROP_MOTION_SENSE:
971 self->motion_sense = g_value_get_uint (value);
974 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
979 gst_deinterlace_method_greedy_h_get_property (GObject * object, guint prop_id,
980 GValue * value, GParamSpec * pspec)
982 GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
986 g_value_set_uint (value, self->max_comb);
988 case PROP_MOTION_THRESHOLD:
989 g_value_set_uint (value, self->motion_threshold);
991 case PROP_MOTION_SENSE:
992 g_value_set_uint (value, self->motion_sense);
995 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1000 gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass *
1003 GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
1004 GObjectClass *gobject_class = (GObjectClass *) klass;
1005 #ifdef BUILD_X86_ASM
1007 orc_target_get_default_flags (orc_target_get_by_name ("mmx"));
1010 gobject_class->set_property = gst_deinterlace_method_greedy_h_set_property;
1011 gobject_class->get_property = gst_deinterlace_method_greedy_h_get_property;
1013 g_object_class_install_property (gobject_class, PROP_MAX_COMB,
1014 g_param_spec_uint ("max-comb",
1016 "Max Comb", 0, 255, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
1019 g_object_class_install_property (gobject_class, PROP_MOTION_THRESHOLD,
1020 g_param_spec_uint ("motion-threshold",
1023 0, 255, 25, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
1026 g_object_class_install_property (gobject_class, PROP_MOTION_SENSE,
1027 g_param_spec_uint ("motion-sense",
1030 0, 255, 30, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
1033 dim_class->fields_required = 4;
1034 dim_class->name = "Motion Adaptive: Advanced Detection";
1035 dim_class->nick = "greedyh";
1036 dim_class->latency = 1;
1038 dim_class->deinterlace_frame_yuy2 = deinterlace_frame_di_greedyh_packed;
1039 dim_class->deinterlace_frame_yvyu = deinterlace_frame_di_greedyh_packed;
1040 dim_class->deinterlace_frame_uyvy = deinterlace_frame_di_greedyh_packed;
1041 dim_class->deinterlace_frame_ayuv = deinterlace_frame_di_greedyh_packed;
1042 dim_class->deinterlace_frame_y444 = deinterlace_frame_di_greedyh_planar;
1043 dim_class->deinterlace_frame_i420 = deinterlace_frame_di_greedyh_planar;
1044 dim_class->deinterlace_frame_yv12 = deinterlace_frame_di_greedyh_planar;
1045 dim_class->deinterlace_frame_y42b = deinterlace_frame_di_greedyh_planar;
1046 dim_class->deinterlace_frame_y41b = deinterlace_frame_di_greedyh_planar;
1048 #ifdef BUILD_X86_ASM
1049 if (cpu_flags & ORC_TARGET_MMX_MMXEXT) {
1050 klass->scanline_yuy2 = greedyh_scanline_MMXEXT_yuy2;
1051 klass->scanline_uyvy = greedyh_scanline_MMXEXT_uyvy;
1052 } else if (cpu_flags & ORC_TARGET_MMX_3DNOW) {
1053 klass->scanline_yuy2 = greedyh_scanline_3DNOW_yuy2;
1054 klass->scanline_uyvy = greedyh_scanline_3DNOW_uyvy;
1055 } else if (cpu_flags & ORC_TARGET_MMX_MMX) {
1056 klass->scanline_yuy2 = greedyh_scanline_MMX_yuy2;
1057 klass->scanline_uyvy = greedyh_scanline_MMX_uyvy;
1059 klass->scanline_yuy2 = greedyh_scanline_C_yuy2;
1060 klass->scanline_uyvy = greedyh_scanline_C_uyvy;
1063 klass->scanline_yuy2 = greedyh_scanline_C_yuy2;
1064 klass->scanline_uyvy = greedyh_scanline_C_uyvy;
1066 /* TODO: MMX implementation of these two */
1067 klass->scanline_ayuv = greedyh_scanline_C_ayuv;
1068 klass->scanline_planar_y = greedyh_scanline_C_planar_y;
1069 klass->scanline_planar_uv = greedyh_scanline_C_planar_uv;
1073 gst_deinterlace_method_greedy_h_init (GstDeinterlaceMethodGreedyH * self)
1076 self->motion_threshold = 25;
1077 self->motion_sense = 30;