Use new gst_element_class_set_static_metadata()
[platform/upstream/gstreamer.git] / gst / deinterlace / gstdeinterlace.c
1 /*
2  * GStreamer
3  * Copyright (C) 2005 Martin Eikermann <meiker@upb.de>
4  * Copyright (C) 2008-2010 Sebastian Dröge <slomo@collabora.co.uk>
5  * Copyright (C) 2011 Robert Swain <robert.swain@collabora.co.uk>
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 /**
24  * SECTION:element-deinterlace
25  *
26  * deinterlace deinterlaces interlaced video frames to progressive video frames.
27  * For this different algorithms can be selected which will be described later.
28  *
29  * <refsect2>
30  * <title>Example launch line</title>
31  * |[
32  * gst-launch -v filesrc location=/path/to/file ! decodebin2 ! ffmpegcolorspace ! deinterlace ! ffmpegcolorspace ! autovideosink
33  * ]| This pipeline deinterlaces a video file with the default deinterlacing options.
34  * </refsect2>
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include "gstdeinterlace.h"
42 #include "tvtime/plugins.h"
43
44 #include <string.h>
45
46 #if HAVE_ORC
47 #include <orc/orc.h>
48 #endif
49
50 GST_DEBUG_CATEGORY_STATIC (deinterlace_debug);
51 #define GST_CAT_DEFAULT (deinterlace_debug)
52
53 /* Properties */
54
55 #define DEFAULT_MODE            GST_DEINTERLACE_MODE_AUTO
56 #define DEFAULT_METHOD          GST_DEINTERLACE_LINEAR
57 #define DEFAULT_FIELDS          GST_DEINTERLACE_ALL
58 #define DEFAULT_FIELD_LAYOUT    GST_DEINTERLACE_LAYOUT_AUTO
59 #define DEFAULT_LOCKING         GST_DEINTERLACE_LOCKING_NONE
60 #define DEFAULT_IGNORE_OBSCURE  TRUE
61 #define DEFAULT_DROP_ORPHANS    TRUE
62
63 enum
64 {
65   PROP_0,
66   PROP_MODE,
67   PROP_METHOD,
68   PROP_FIELDS,
69   PROP_FIELD_LAYOUT,
70   PROP_LOCKING,
71   PROP_IGNORE_OBSCURE,
72   PROP_DROP_ORPHANS,
73   PROP_LAST
74 };
75
76 #define GST_DEINTERLACE_BUFFER_STATE_P    (1<<0)
77 #define GST_DEINTERLACE_BUFFER_STATE_I    (1<<1)
78 #define GST_DEINTERLACE_BUFFER_STATE_TC_B (1<<2)
79 #define GST_DEINTERLACE_BUFFER_STATE_TC_T (1<<3)
80 #define GST_DEINTERLACE_BUFFER_STATE_TC_P (1<<4)
81 #define GST_DEINTERLACE_BUFFER_STATE_TC_M (1<<5)
82 #define GST_DEINTERLACE_BUFFER_STATE_DROP (1<<6)
83
84 #define GST_ONE \
85   (GST_DEINTERLACE_BUFFER_STATE_TC_T | GST_DEINTERLACE_BUFFER_STATE_TC_B)
86 #define GST_PRG \
87   (GST_DEINTERLACE_BUFFER_STATE_P | GST_DEINTERLACE_BUFFER_STATE_TC_P)
88 #define GST_INT \
89   (GST_DEINTERLACE_BUFFER_STATE_I | GST_DEINTERLACE_BUFFER_STATE_TC_M)
90 #define GST_DRP (GST_DEINTERLACE_BUFFER_STATE_DROP)
91
92 #define GST_DEINTERLACE_OBSCURE_THRESHOLD 5
93
94 static const TelecinePattern telecine_patterns[] = {
95   /* 60i -> 60p or 50i -> 50p (NOTE THE WEIRD RATIOS) */
96   {"1:1", 1, 2, 1, {GST_ONE,}},
97   /* 60i -> 30p or 50i -> 25p */
98   {"2:2", 1, 1, 1, {GST_INT,}},
99   /* 60i telecine -> 24p */
100   {"2:3", 5, 4, 5, {GST_PRG, GST_PRG, GST_ONE, GST_ONE, GST_PRG,}},
101   {"3:2:2:3", 5, 4, 5, {GST_PRG, GST_ONE, GST_INT, GST_ONE, GST_PRG,}},
102   {"2:3:3:2", 5, 4, 5, {GST_PRG, GST_PRG, GST_DRP, GST_PRG, GST_PRG,}},
103
104   /* The following patterns are obscure and are ignored if ignore-obscure is
105    * set to true. If any patterns are added above this line, check and edit
106    * GST_DEINTERLACE_OBSCURE_THRESHOLD */
107
108   /* 50i Euro pulldown -> 24p */
109   {"2-11:3", 25, 24, 25, {GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_PRG,
110               GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_PRG,
111               GST_PRG, GST_PRG, GST_ONE, GST_INT, GST_INT,
112               GST_INT, GST_INT, GST_INT, GST_INT, GST_INT,
113           GST_INT, GST_INT, GST_INT, GST_ONE, GST_PRG,}},
114   /* 60i (NTSC 30000/1001) -> 16p (16000/1001) */
115   {"3:4-3", 15, 8, 15, {GST_PRG, GST_DRP, GST_PRG, GST_DRP, GST_PRG,
116               GST_DRP, GST_PRG, GST_DRP, GST_PRG, GST_DRP,
117           GST_PRG, GST_DRP, GST_PRG, GST_DRP, GST_PRG,}},
118   /* 50i (PAL) -> 16p */
119   {"3-7:4", 25, 16, 25, {GST_PRG, GST_DRP, GST_PRG, GST_PRG, GST_DRP,
120               GST_PRG, GST_PRG, GST_DRP, GST_PRG, GST_PRG,
121               GST_DRP, GST_PRG, GST_DRP, GST_PRG, GST_PRG,
122               GST_DRP, GST_PRG, GST_PRG, GST_DRP, GST_PRG,
123           GST_PRG, GST_DRP, GST_PRG, GST_PRG, GST_DRP,}},
124   /* NTSC 60i -> 18p */
125   {"3:3:4", 5, 3, 5, {GST_PRG, GST_DRP, GST_PRG, GST_DRP, GST_PRG,}},
126   /* NTSC 60i -> 20p */
127   {"3:3", 3, 2, 3, {GST_PRG, GST_DRP, GST_PRG,}},
128   /* NTSC 60i -> 27.5 */
129   {"3:2-4", 11, 10, 11, {GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_PRG,
130               GST_PRG, GST_ONE, GST_INT, GST_INT, GST_INT,
131           GST_ONE,}},
132   /* PAL 50i -> 27.5 */
133   {"1:2-4", 9, 9, 10, {GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_INT,
134           GST_INT, GST_INT, GST_INT, GST_INT,}},
135 };
136
137 static const GEnumValue methods_types[] = {
138   {GST_DEINTERLACE_TOMSMOCOMP, "Motion Adaptive: Motion Search",
139       "tomsmocomp"},
140   {GST_DEINTERLACE_GREEDY_H, "Motion Adaptive: Advanced Detection",
141       "greedyh"},
142   {GST_DEINTERLACE_GREEDY_L, "Motion Adaptive: Simple Detection", "greedyl"},
143   {GST_DEINTERLACE_VFIR, "Blur Vertical", "vfir"},
144   {GST_DEINTERLACE_LINEAR, "Television: Full resolution", "linear"},
145   {GST_DEINTERLACE_LINEAR_BLEND, "Blur: Temporal (Do Not Use)",
146       "linearblend"},
147   {GST_DEINTERLACE_SCALER_BOB, "Double lines", "scalerbob"},
148   {GST_DEINTERLACE_WEAVE, "Weave (Do Not Use)", "weave"},
149   {GST_DEINTERLACE_WEAVE_TFF, "Progressive: Top Field First (Do Not Use)",
150       "weavetff"},
151   {GST_DEINTERLACE_WEAVE_BFF, "Progressive: Bottom Field First (Do Not Use)",
152       "weavebff"},
153   {0, NULL, NULL},
154 };
155
156 static const GEnumValue locking_types[] = {
157   {GST_DEINTERLACE_LOCKING_NONE,
158       "No pattern locking", "none"},
159   {GST_DEINTERLACE_LOCKING_AUTO,
160         "Choose passive/active locking depending on whether upstream is live",
161       "auto"},
162   {GST_DEINTERLACE_LOCKING_ACTIVE,
163         "Block until pattern-locked. Use accurate timestamp interpolation within a pattern repeat.",
164       "active"},
165   {GST_DEINTERLACE_LOCKING_PASSIVE,
166         "Do not block. Use naïve timestamp adjustment until pattern-locked based on state history.",
167       "passive"},
168   {0, NULL, NULL},
169 };
170
171
172 #define GST_TYPE_DEINTERLACE_METHODS (gst_deinterlace_methods_get_type ())
173 static GType
174 gst_deinterlace_methods_get_type (void)
175 {
176   static GType deinterlace_methods_type = 0;
177
178   if (!deinterlace_methods_type) {
179     deinterlace_methods_type =
180         g_enum_register_static ("GstDeinterlaceMethods", methods_types);
181   }
182   return deinterlace_methods_type;
183 }
184
185 #define GST_TYPE_DEINTERLACE_FIELDS (gst_deinterlace_fields_get_type ())
186 static GType
187 gst_deinterlace_fields_get_type (void)
188 {
189   static GType deinterlace_fields_type = 0;
190
191   static const GEnumValue fields_types[] = {
192     {GST_DEINTERLACE_ALL, "All fields", "all"},
193     {GST_DEINTERLACE_TF, "Top fields only", "top"},
194     {GST_DEINTERLACE_BF, "Bottom fields only", "bottom"},
195     {0, NULL, NULL},
196   };
197
198   if (!deinterlace_fields_type) {
199     deinterlace_fields_type =
200         g_enum_register_static ("GstDeinterlaceFields", fields_types);
201   }
202   return deinterlace_fields_type;
203 }
204
205 #define GST_TYPE_DEINTERLACE_FIELD_LAYOUT (gst_deinterlace_field_layout_get_type ())
206 static GType
207 gst_deinterlace_field_layout_get_type (void)
208 {
209   static GType deinterlace_field_layout_type = 0;
210
211   static const GEnumValue field_layout_types[] = {
212     {GST_DEINTERLACE_LAYOUT_AUTO, "Auto detection", "auto"},
213     {GST_DEINTERLACE_LAYOUT_TFF, "Top field first", "tff"},
214     {GST_DEINTERLACE_LAYOUT_BFF, "Bottom field first", "bff"},
215     {0, NULL, NULL},
216   };
217
218   if (!deinterlace_field_layout_type) {
219     deinterlace_field_layout_type =
220         g_enum_register_static ("GstDeinterlaceFieldLayout",
221         field_layout_types);
222   }
223   return deinterlace_field_layout_type;
224 }
225
226 #define GST_TYPE_DEINTERLACE_MODES (gst_deinterlace_modes_get_type ())
227 static GType
228 gst_deinterlace_modes_get_type (void)
229 {
230   static GType deinterlace_modes_type = 0;
231
232   static const GEnumValue modes_types[] = {
233     {GST_DEINTERLACE_MODE_AUTO, "Auto detection", "auto"},
234     {GST_DEINTERLACE_MODE_INTERLACED, "Force deinterlacing", "interlaced"},
235     {GST_DEINTERLACE_MODE_DISABLED, "Run in passthrough mode", "disabled"},
236     {0, NULL, NULL},
237   };
238
239   if (!deinterlace_modes_type) {
240     deinterlace_modes_type =
241         g_enum_register_static ("GstDeinterlaceModes", modes_types);
242   }
243   return deinterlace_modes_type;
244 }
245
246 #define GST_TYPE_DEINTERLACE_LOCKING (gst_deinterlace_locking_get_type ())
247 static GType
248 gst_deinterlace_locking_get_type (void)
249 {
250   static GType deinterlace_locking_type = 0;
251
252   if (!deinterlace_locking_type) {
253     deinterlace_locking_type =
254         g_enum_register_static ("GstDeinterlaceLocking", locking_types);
255   }
256
257   return deinterlace_locking_type;
258 }
259
260
261 #define DEINTERLACE_CAPS \
262     GST_VIDEO_CAPS_YUV ("{ AYUV, Y444, YUY2, YVYU, UYVY, Y42B, I420, YV12, Y41B, NV12, NV21 }") ";" \
263     GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_ABGR ";" \
264     GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA ";" \
265     GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" \
266     GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" \
267     GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR
268
269 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
270     GST_PAD_SRC,
271     GST_PAD_ALWAYS,
272     GST_STATIC_CAPS (DEINTERLACE_CAPS)
273     );
274
275 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
276     GST_PAD_SINK,
277     GST_PAD_ALWAYS,
278     GST_STATIC_CAPS (DEINTERLACE_CAPS)
279     );
280
281 static void gst_deinterlace_finalize (GObject * self);
282 static void gst_deinterlace_set_property (GObject * self, guint prop_id,
283     const GValue * value, GParamSpec * pspec);
284 static void gst_deinterlace_get_property (GObject * self, guint prop_id,
285     GValue * value, GParamSpec * pspec);
286
287 static GstCaps *gst_deinterlace_getcaps (GstPad * pad);
288 static gboolean gst_deinterlace_setcaps (GstPad * pad, GstCaps * caps);
289 static gboolean gst_deinterlace_sink_event (GstPad * pad, GstEvent * event);
290 static gboolean gst_deinterlace_sink_query (GstPad * pad, GstQuery * query);
291 static GstFlowReturn gst_deinterlace_chain (GstPad * pad, GstBuffer * buffer);
292 static GstFlowReturn gst_deinterlace_alloc_buffer (GstPad * pad, guint64 offset,
293     guint size, GstCaps * caps, GstBuffer ** buf);
294 static GstStateChangeReturn gst_deinterlace_change_state (GstElement * element,
295     GstStateChange transition);
296
297 static gboolean gst_deinterlace_src_event (GstPad * pad, GstEvent * event);
298 static gboolean gst_deinterlace_src_query (GstPad * pad, GstQuery * query);
299 static const GstQueryType *gst_deinterlace_src_query_types (GstPad * pad);
300
301 static GstFlowReturn gst_deinterlace_output_frame (GstDeinterlace * self,
302     gboolean flushing);
303 static void gst_deinterlace_reset (GstDeinterlace * self);
304 static void gst_deinterlace_update_qos (GstDeinterlace * self,
305     gdouble proportion, GstClockTimeDiff diff, GstClockTime time);
306 static void gst_deinterlace_reset_qos (GstDeinterlace * self);
307 static void gst_deinterlace_read_qos (GstDeinterlace * self,
308     gdouble * proportion, GstClockTime * time);
309
310 static void gst_deinterlace_child_proxy_interface_init (gpointer g_iface,
311     gpointer iface_data);
312
313 static void
314 _do_init (GType object_type)
315 {
316   const GInterfaceInfo child_proxy_interface_info = {
317     (GInterfaceInitFunc) gst_deinterlace_child_proxy_interface_init,
318     NULL,                       /* interface_finalize */
319     NULL                        /* interface_data */
320   };
321
322   g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
323       &child_proxy_interface_info);
324 }
325
326 GST_BOILERPLATE_FULL (GstDeinterlace, gst_deinterlace, GstElement,
327     GST_TYPE_ELEMENT, _do_init);
328
329 static const struct
330 {
331   GType (*get_type) (void);
332 } _method_types[] = {
333   {
334   gst_deinterlace_method_tomsmocomp_get_type}, {
335   gst_deinterlace_method_greedy_h_get_type}, {
336   gst_deinterlace_method_greedy_l_get_type}, {
337   gst_deinterlace_method_vfir_get_type}, {
338   gst_deinterlace_method_linear_get_type}, {
339   gst_deinterlace_method_linear_blend_get_type}, {
340   gst_deinterlace_method_scaler_bob_get_type}, {
341   gst_deinterlace_method_weave_get_type}, {
342   gst_deinterlace_method_weave_tff_get_type}, {
343   gst_deinterlace_method_weave_bff_get_type}
344 };
345
346 static void
347 gst_deinterlace_set_method (GstDeinterlace * self, GstDeinterlaceMethods method)
348 {
349   GType method_type;
350
351   GST_DEBUG_OBJECT (self, "Setting new method %d", method);
352
353   if (self->method) {
354     if (self->method_id == method &&
355         gst_deinterlace_method_supported (G_TYPE_FROM_INSTANCE (self->method),
356             self->format, self->width, self->height)) {
357       GST_DEBUG_OBJECT (self, "Reusing current method");
358       return;
359     }
360
361     gst_child_proxy_child_removed (GST_OBJECT (self),
362         GST_OBJECT (self->method));
363     gst_object_unparent (GST_OBJECT (self->method));
364     self->method = NULL;
365   }
366
367   method_type =
368       _method_types[method].get_type !=
369       NULL ? _method_types[method].get_type () : G_TYPE_INVALID;
370   if (method_type == G_TYPE_INVALID
371       || !gst_deinterlace_method_supported (method_type, self->format,
372           self->width, self->height)) {
373     GType tmp;
374     gint i;
375
376     method_type = G_TYPE_INVALID;
377
378     GST_WARNING_OBJECT (self, "Method doesn't support requested format");
379     for (i = 0; i < G_N_ELEMENTS (_method_types); i++) {
380       if (_method_types[i].get_type == NULL)
381         continue;
382       tmp = _method_types[i].get_type ();
383       if (gst_deinterlace_method_supported (tmp, self->format, self->width,
384               self->height)) {
385         GST_DEBUG_OBJECT (self, "Using method %d", i);
386         method_type = tmp;
387         method = i;
388         break;
389       }
390     }
391     /* If we get here we must have invalid caps! */
392     g_assert (method_type != G_TYPE_INVALID);
393   }
394
395   self->method = g_object_new (method_type, "name", "method", NULL);
396   self->method_id = method;
397
398   gst_object_set_parent (GST_OBJECT (self->method), GST_OBJECT (self));
399   gst_child_proxy_child_added (GST_OBJECT (self), GST_OBJECT (self->method));
400
401   if (self->method)
402     gst_deinterlace_method_setup (self->method, self->format, self->width,
403         self->height);
404 }
405
406 static gboolean
407 gst_deinterlace_clip_buffer (GstDeinterlace * self, GstBuffer * buffer)
408 {
409   gboolean ret = TRUE;
410   GstClockTime start, stop;
411   gint64 cstart, cstop;
412
413   GST_DEBUG_OBJECT (self,
414       "Clipping buffer to the current segment: %" GST_TIME_FORMAT " -- %"
415       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
416       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
417   GST_DEBUG_OBJECT (self, "Current segment: %" GST_SEGMENT_FORMAT,
418       &self->segment);
419
420   if (G_UNLIKELY (self->segment.format != GST_FORMAT_TIME))
421     goto beach;
422   if (G_UNLIKELY (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)))
423     goto beach;
424
425   start = GST_BUFFER_TIMESTAMP (buffer);
426   stop = start + GST_BUFFER_DURATION (buffer);
427
428   if (!(ret = gst_segment_clip (&self->segment, GST_FORMAT_TIME,
429               start, stop, &cstart, &cstop)))
430     goto beach;
431
432   GST_BUFFER_TIMESTAMP (buffer) = cstart;
433   if (GST_CLOCK_TIME_IS_VALID (cstop))
434     GST_BUFFER_DURATION (buffer) = cstop - cstart;
435
436 beach:
437   if (ret)
438     GST_DEBUG_OBJECT (self,
439         "Clipped buffer to the current segment: %" GST_TIME_FORMAT " -- %"
440         GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
441         GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
442   else
443     GST_DEBUG_OBJECT (self, "Buffer outside the current segment -- dropping");
444
445   return ret;
446 }
447
448 static void
449 gst_deinterlace_base_init (gpointer klass)
450 {
451   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
452
453   gst_element_class_add_pad_template (element_class,
454       gst_static_pad_template_get (&src_templ));
455   gst_element_class_add_pad_template (element_class,
456       gst_static_pad_template_get (&sink_templ));
457
458   gst_element_class_set_static_metadata (element_class,
459       "Deinterlacer",
460       "Filter/Effect/Video/Deinterlace",
461       "Deinterlace Methods ported from DScaler/TvTime",
462       "Martin Eikermann <meiker@upb.de>, "
463       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
464 }
465
466 static void
467 gst_deinterlace_class_init (GstDeinterlaceClass * klass)
468 {
469   GObjectClass *gobject_class = (GObjectClass *) klass;
470
471   GstElementClass *element_class = (GstElementClass *) klass;
472
473   gobject_class->set_property = gst_deinterlace_set_property;
474   gobject_class->get_property = gst_deinterlace_get_property;
475   gobject_class->finalize = gst_deinterlace_finalize;
476
477   /**
478    * GstDeinterlace:mode
479    * 
480    * This selects whether the deinterlacing methods should
481    * always be applied or if they should only be applied
482    * on content that has the "interlaced" flag on the caps.
483    *
484    */
485   g_object_class_install_property (gobject_class, PROP_MODE,
486       g_param_spec_enum ("mode",
487           "Mode",
488           "Deinterlace Mode",
489           GST_TYPE_DEINTERLACE_MODES,
490           DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
491       );
492
493   /**
494    * GstDeinterlace:method
495    * 
496    * Selects the different deinterlacing algorithms that can be used.
497    * These provide different quality and CPU usage.
498    *
499    * Some methods provide parameters which can be set by getting
500    * the "method" child via the #GstChildProxy interface and
501    * setting the appropiate properties on it.
502    *
503    * <itemizedlist>
504    * <listitem>
505    * <para>
506    * tomsmocomp
507    * Motion Adaptive: Motion Search
508    * </para>
509    * </listitem>
510    * <listitem>
511    * <para>
512    * greedyh
513    * Motion Adaptive: Advanced Detection
514    * </para>
515    * </listitem>
516    * <listitem>
517    * <para>
518    * greedyl
519    * Motion Adaptive: Simple Detection
520    * </para>
521    * </listitem>
522    * <listitem>
523    * <para>
524    * vfir
525    * Blur vertical
526    * </para>
527    * </listitem>
528    * <listitem>
529    * <para>
530    * linear
531    * Linear interpolation
532    * </para>
533    * </listitem>
534    * <listitem>
535    * <para>
536    * linearblend
537    * Linear interpolation in time domain.  Any motion causes significant
538    * ghosting, so this method should not be used.
539    * </para>
540    * </listitem>
541    * <listitem>
542    * <para>
543    * scalerbob
544    * Double lines
545    * </para>
546    * </listitem>
547    * <listitem>
548    * <para>
549    * weave
550    * Weave.  Bad quality, do not use.
551    * </para>
552    * </listitem>
553    * <listitem>
554    * <para>
555    * weavetff
556    * Progressive: Top Field First.  Bad quality, do not use.
557    * </para>
558    * </listitem>
559    * <listitem>
560    * <para>
561    * weavebff
562    * Progressive: Bottom Field First.  Bad quality, do not use.
563    * </para>
564    * </listitem>
565    * </itemizedlist>
566    */
567   g_object_class_install_property (gobject_class, PROP_METHOD,
568       g_param_spec_enum ("method",
569           "Method",
570           "Deinterlace Method",
571           GST_TYPE_DEINTERLACE_METHODS,
572           DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
573       );
574
575   /**
576    * GstDeinterlace:fields
577    *
578    * This selects which fields should be output. If "all" is selected
579    * the output framerate will be double.
580    *
581    */
582   g_object_class_install_property (gobject_class, PROP_FIELDS,
583       g_param_spec_enum ("fields",
584           "fields",
585           "Fields to use for deinterlacing",
586           GST_TYPE_DEINTERLACE_FIELDS,
587           DEFAULT_FIELDS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
588       );
589
590   /**
591    * GstDeinterlace:layout
592    *
593    * This selects which fields is the first in time.
594    *
595    */
596   g_object_class_install_property (gobject_class, PROP_FIELD_LAYOUT,
597       g_param_spec_enum ("tff",
598           "tff",
599           "Deinterlace top field first",
600           GST_TYPE_DEINTERLACE_FIELD_LAYOUT,
601           DEFAULT_FIELD_LAYOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
602       );
603
604   /**
605    * GstDeinterlace:locking
606    *
607    * This selects which approach to pattern locking is used which affects
608    * processing latency and accuracy of timestamp adjustment for telecine
609    * streams.
610    *
611    * Since: 0.10.31
612    *
613    */
614   g_object_class_install_property (gobject_class, PROP_LOCKING,
615       g_param_spec_enum ("locking", "locking", "Pattern locking mode",
616           GST_TYPE_DEINTERLACE_LOCKING, DEFAULT_LOCKING,
617           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
618
619   /**
620    * GstDeinterlace:ignore-obscure
621    *
622    * This selects whether to ignore obscure/rare telecine patterns.
623    * NTSC 2:3 pulldown variants are the only really common patterns.
624    *
625    * Since: 0.10.31
626    *
627    */
628   g_object_class_install_property (gobject_class, PROP_IGNORE_OBSCURE,
629       g_param_spec_boolean ("ignore-obscure", "ignore-obscure",
630           "Ignore obscure telecine patterns (only consider P, I and 2:3 "
631           "variants).", DEFAULT_IGNORE_OBSCURE,
632           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
633
634   /**
635    * GstDeinterlace:drop-orphans
636    *
637    * This selects whether to drop orphan fields at the beginning of telecine
638    * patterns in active locking mode.
639    *
640    * Since: 0.10.31
641    *
642    */
643   g_object_class_install_property (gobject_class, PROP_DROP_ORPHANS,
644       g_param_spec_boolean ("drop-orphans", "drop-orphans",
645           "Drop orphan fields at the beginning of telecine patterns in "
646           "active locking mode.", DEFAULT_DROP_ORPHANS,
647           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
648
649   element_class->change_state =
650       GST_DEBUG_FUNCPTR (gst_deinterlace_change_state);
651 }
652
653 static GstObject *
654 gst_deinterlace_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
655     guint index)
656 {
657   GstDeinterlace *self = GST_DEINTERLACE (child_proxy);
658
659   g_return_val_if_fail (index == 0, NULL);
660
661   return gst_object_ref (self->method);
662 }
663
664 static guint
665 gst_deinterlace_child_proxy_get_children_count (GstChildProxy * child_proxy)
666 {
667   GstDeinterlace *self = GST_DEINTERLACE (child_proxy);
668
669   return ((self->method) ? 1 : 0);
670 }
671
672 static void
673 gst_deinterlace_child_proxy_interface_init (gpointer g_iface,
674     gpointer iface_data)
675 {
676   GstChildProxyInterface *iface = g_iface;
677
678   iface->get_child_by_index = gst_deinterlace_child_proxy_get_child_by_index;
679   iface->get_children_count = gst_deinterlace_child_proxy_get_children_count;
680 }
681
682 static void
683 gst_deinterlace_init (GstDeinterlace * self, GstDeinterlaceClass * klass)
684 {
685   self->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
686   gst_pad_set_chain_function (self->sinkpad,
687       GST_DEBUG_FUNCPTR (gst_deinterlace_chain));
688   gst_pad_set_event_function (self->sinkpad,
689       GST_DEBUG_FUNCPTR (gst_deinterlace_sink_event));
690   gst_pad_set_setcaps_function (self->sinkpad,
691       GST_DEBUG_FUNCPTR (gst_deinterlace_setcaps));
692   gst_pad_set_getcaps_function (self->sinkpad,
693       GST_DEBUG_FUNCPTR (gst_deinterlace_getcaps));
694   gst_pad_set_query_function (self->sinkpad,
695       GST_DEBUG_FUNCPTR (gst_deinterlace_sink_query));
696   gst_pad_set_bufferalloc_function (self->sinkpad,
697       GST_DEBUG_FUNCPTR (gst_deinterlace_alloc_buffer));
698   gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
699
700   self->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
701   gst_pad_set_event_function (self->srcpad,
702       GST_DEBUG_FUNCPTR (gst_deinterlace_src_event));
703   gst_pad_set_query_type_function (self->srcpad,
704       GST_DEBUG_FUNCPTR (gst_deinterlace_src_query_types));
705   gst_pad_set_query_function (self->srcpad,
706       GST_DEBUG_FUNCPTR (gst_deinterlace_src_query));
707   gst_pad_set_getcaps_function (self->srcpad,
708       GST_DEBUG_FUNCPTR (gst_deinterlace_getcaps));
709   gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
710
711   self->mode = DEFAULT_MODE;
712   self->user_set_method_id = DEFAULT_METHOD;
713   gst_deinterlace_set_method (self, self->user_set_method_id);
714   self->fields = DEFAULT_FIELDS;
715   self->field_layout = DEFAULT_FIELD_LAYOUT;
716   self->locking = DEFAULT_LOCKING;
717   self->ignore_obscure = DEFAULT_IGNORE_OBSCURE;
718   self->drop_orphans = DEFAULT_DROP_ORPHANS;
719
720   self->low_latency = -1;
721   self->pattern = -1;
722   self->pattern_phase = -1;
723   self->pattern_count = 0;
724   self->output_count = 0;
725   self->pattern_base_ts = GST_CLOCK_TIME_NONE;
726   self->pattern_buf_dur = GST_CLOCK_TIME_NONE;
727   self->still_frame_mode = FALSE;
728
729   gst_deinterlace_reset (self);
730 }
731
732 static void
733 gst_deinterlace_reset_history (GstDeinterlace * self, gboolean drop_all)
734 {
735   gint i;
736
737   if (!drop_all) {
738     GST_DEBUG_OBJECT (self, "Flushing history (count %d)", self->history_count);
739     while (self->history_count > 0) {
740       if (gst_deinterlace_output_frame (self, TRUE) != GST_FLOW_OK) {
741         /* Encountered error, or flushing -> skip and drop all remaining */
742         drop_all = TRUE;
743         break;
744       }
745     }
746   }
747   if (drop_all) {
748     GST_DEBUG_OBJECT (self, "Resetting history (count %d)",
749         self->history_count);
750
751     for (i = 0; i < self->history_count; i++) {
752       if (self->field_history[i].buf) {
753         gst_buffer_unref (self->field_history[i].buf);
754         self->field_history[i].buf = NULL;
755       }
756     }
757   }
758   memset (self->field_history, 0,
759       GST_DEINTERLACE_MAX_FIELD_HISTORY * sizeof (GstDeinterlaceField));
760   self->history_count = 0;
761   memset (self->buf_states, 0,
762       GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY *
763       sizeof (GstDeinterlaceBufferState));
764   self->state_count = 0;
765   self->pattern_lock = FALSE;
766   self->pattern_refresh = TRUE;
767   self->cur_field_idx = -1;
768
769   if (!self->still_frame_mode && self->last_buffer) {
770     gst_buffer_unref (self->last_buffer);
771     self->last_buffer = NULL;
772   }
773 }
774
775 static void
776 gst_deinterlace_update_passthrough (GstDeinterlace * self)
777 {
778   self->passthrough = (self->mode == GST_DEINTERLACE_MODE_DISABLED
779       || (!self->interlaced && self->mode != GST_DEINTERLACE_MODE_INTERLACED));
780   GST_DEBUG_OBJECT (self, "Passthrough: %d", self->passthrough);
781 }
782
783 static void
784 gst_deinterlace_reset (GstDeinterlace * self)
785 {
786   GST_DEBUG_OBJECT (self, "Resetting internal state");
787
788   self->format = GST_VIDEO_FORMAT_UNKNOWN;
789   self->width = 0;
790   self->height = 0;
791   self->frame_size = 0;
792   self->fps_n = self->fps_d = 0;
793   self->passthrough = FALSE;
794
795   self->reconfigure = FALSE;
796   if (self->new_mode != -1)
797     self->mode = self->new_mode;
798   if (self->new_fields != -1)
799     self->fields = self->new_fields;
800   self->new_mode = -1;
801   self->new_fields = -1;
802
803   gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
804
805   if (self->request_caps)
806     gst_caps_unref (self->request_caps);
807   self->request_caps = NULL;
808
809   gst_deinterlace_reset_history (self, TRUE);
810
811   gst_deinterlace_reset_qos (self);
812
813   self->need_more = FALSE;
814   self->have_eos = FALSE;
815 }
816
817 static void
818 gst_deinterlace_set_property (GObject * object, guint prop_id,
819     const GValue * value, GParamSpec * pspec)
820 {
821   GstDeinterlace *self;
822
823   g_return_if_fail (GST_IS_DEINTERLACE (object));
824   self = GST_DEINTERLACE (object);
825
826   switch (prop_id) {
827     case PROP_MODE:{
828       gint new_mode;
829
830       GST_OBJECT_LOCK (self);
831       new_mode = g_value_get_enum (value);
832       if (self->mode != new_mode && GST_PAD_CAPS (self->srcpad)) {
833         self->reconfigure = TRUE;
834         self->new_mode = new_mode;
835       } else {
836         self->mode = new_mode;
837         gst_deinterlace_update_passthrough (self);
838       }
839       GST_OBJECT_UNLOCK (self);
840       break;
841     }
842     case PROP_METHOD:
843       self->user_set_method_id = g_value_get_enum (value);
844       gst_deinterlace_set_method (self, self->user_set_method_id);
845       break;
846     case PROP_FIELDS:{
847       gint new_fields;
848
849       GST_OBJECT_LOCK (self);
850       new_fields = g_value_get_enum (value);
851       if (self->fields != new_fields && GST_PAD_CAPS (self->srcpad)) {
852         self->reconfigure = TRUE;
853         self->new_fields = new_fields;
854       } else {
855         self->fields = new_fields;
856       }
857       GST_OBJECT_UNLOCK (self);
858       break;
859     }
860     case PROP_FIELD_LAYOUT:
861       self->field_layout = g_value_get_enum (value);
862       break;
863     case PROP_LOCKING:
864       self->locking = g_value_get_enum (value);
865       break;
866     case PROP_IGNORE_OBSCURE:
867       self->ignore_obscure = g_value_get_boolean (value);
868       break;
869     case PROP_DROP_ORPHANS:
870       self->drop_orphans = g_value_get_boolean (value);
871       break;
872     default:
873       G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
874   }
875
876 }
877
878 static void
879 gst_deinterlace_get_property (GObject * object, guint prop_id,
880     GValue * value, GParamSpec * pspec)
881 {
882   GstDeinterlace *self;
883
884   g_return_if_fail (GST_IS_DEINTERLACE (object));
885   self = GST_DEINTERLACE (object);
886
887   switch (prop_id) {
888     case PROP_MODE:
889       g_value_set_enum (value, self->mode);
890       break;
891     case PROP_METHOD:
892       g_value_set_enum (value, self->user_set_method_id);
893       break;
894     case PROP_FIELDS:
895       g_value_set_enum (value, self->fields);
896       break;
897     case PROP_FIELD_LAYOUT:
898       g_value_set_enum (value, self->field_layout);
899       break;
900     case PROP_LOCKING:
901       g_value_set_enum (value, self->locking);
902       break;
903     case PROP_IGNORE_OBSCURE:
904       g_value_set_boolean (value, self->ignore_obscure);
905       break;
906     case PROP_DROP_ORPHANS:
907       g_value_set_boolean (value, self->drop_orphans);
908       break;
909     default:
910       G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
911   }
912 }
913
914 static void
915 gst_deinterlace_finalize (GObject * object)
916 {
917   GstDeinterlace *self = GST_DEINTERLACE (object);
918
919   gst_deinterlace_reset (self);
920
921   if (self->method) {
922     gst_object_unparent (GST_OBJECT (self->method));
923     self->method = NULL;
924   }
925
926   G_OBJECT_CLASS (parent_class)->finalize (object);
927 }
928
929 static void
930 gst_deinterlace_update_pattern_timestamps (GstDeinterlace * self)
931 {
932   gint state_idx;
933   if (self->low_latency) {
934     /* in low-latency mode the buffer state history contains old buffer
935      * states as well as the current one and perhaps some future ones.
936      * the current buffer's state is given by the number of field pairs
937      * rounded up, minus 1. the below is equivalent */
938     state_idx = (self->history_count - 1) >> 1;
939   } else {
940     /* in high-latency mode state_count - 1 is the current buffer's state */
941     state_idx = self->state_count - 1;
942   }
943
944   self->pattern_base_ts = self->buf_states[state_idx].timestamp;
945   self->pattern_buf_dur =
946       (self->buf_states[state_idx].duration *
947       telecine_patterns[self->pattern].ratio_d) /
948       telecine_patterns[self->pattern].ratio_n;
949   GST_DEBUG_OBJECT (self,
950       "Starting a new pattern repeat with base ts %" GST_TIME_FORMAT
951       " and dur %" GST_TIME_FORMAT, GST_TIME_ARGS (self->pattern_base_ts),
952       GST_TIME_ARGS (self->pattern_buf_dur));
953 }
954
955 static GstBuffer *
956 gst_deinterlace_pop_history (GstDeinterlace * self)
957 {
958   GstBuffer *buffer;
959
960   g_return_val_if_fail (self->history_count > 0, NULL);
961
962   GST_DEBUG_OBJECT (self, "Pop last history buffer -- current history size %d",
963       self->history_count);
964
965   buffer = self->field_history[self->history_count - 1].buf;
966
967   self->history_count--;
968   if (self->locking != GST_DEINTERLACE_LOCKING_NONE && (!self->history_count
969           || GST_BUFFER_DATA (buffer) !=
970           GST_BUFFER_DATA (self->field_history[self->history_count - 1].buf))) {
971     if (!self->low_latency)
972       self->state_count--;
973     if (self->pattern_lock) {
974       self->pattern_count++;
975       if (self->pattern != -1
976           && self->pattern_count >= telecine_patterns[self->pattern].length) {
977         self->pattern_count = 0;
978         self->output_count = 0;
979         gst_deinterlace_update_pattern_timestamps (self);
980       }
981     }
982   }
983
984   GST_DEBUG_OBJECT (self, "Returning buffer: %p %" GST_TIME_FORMAT
985       " with duration %" GST_TIME_FORMAT " and size %u", buffer,
986       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
987       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)), GST_BUFFER_SIZE (buffer));
988
989   return buffer;
990 }
991
992 typedef enum
993 {
994   GST_DEINTERLACE_PROGRESSIVE,
995   GST_DEINTERLACE_INTERLACED,
996   GST_DEINTERLACE_TELECINE,
997 } GstDeinterlaceInterlacingMethod;
998
999 static GstDeinterlaceInterlacingMethod
1000 gst_deinterlace_get_interlacing_method (const GstCaps * caps)
1001 {
1002   GstDeinterlaceInterlacingMethod method = 0;
1003   gboolean interlaced;
1004
1005   /* check interlaced cap, defaulting to FALSE */
1006   if (!gst_structure_get_boolean (gst_caps_get_structure (caps, 0),
1007           "interlaced", &interlaced))
1008     interlaced = FALSE;
1009
1010   method =
1011       interlaced ? GST_DEINTERLACE_INTERLACED : GST_DEINTERLACE_PROGRESSIVE;
1012
1013   if (method == GST_DEINTERLACE_INTERLACED) {
1014     const gchar *temp =
1015         gst_structure_get_string (gst_caps_get_structure (caps, 0),
1016         "interlacing-method");
1017     if (temp && g_str_equal (temp, "telecine"))
1018       method = GST_DEINTERLACE_TELECINE;
1019   }
1020
1021   return method;
1022 }
1023
1024 static void
1025 gst_deinterlace_get_buffer_state (GstDeinterlace * self, GstBuffer * buffer,
1026     guint8 * state, GstDeinterlaceInterlacingMethod * i_method)
1027 {
1028   GstDeinterlaceInterlacingMethod interlacing_method;
1029
1030   if (!(i_method || state))
1031     return;
1032
1033   interlacing_method =
1034       gst_deinterlace_get_interlacing_method (GST_BUFFER_CAPS (buffer));
1035
1036   if (state) {
1037     if (interlacing_method == GST_DEINTERLACE_TELECINE) {
1038       if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_RFF)) {
1039         *state = GST_DEINTERLACE_BUFFER_STATE_DROP;
1040       } else if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_ONEFIELD)) {
1041         /* tc top if tff, tc bottom otherwise */
1042         if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_TFF)) {
1043           *state = GST_DEINTERLACE_BUFFER_STATE_TC_T;
1044         } else {
1045           *state = GST_DEINTERLACE_BUFFER_STATE_TC_B;
1046         }
1047       } else if (GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_PROGRESSIVE)) {
1048         *state = GST_DEINTERLACE_BUFFER_STATE_TC_P;
1049       } else {
1050         *state = GST_DEINTERLACE_BUFFER_STATE_TC_M;
1051       }
1052     } else {
1053       if (interlacing_method == GST_DEINTERLACE_INTERLACED) {
1054         *state = GST_DEINTERLACE_BUFFER_STATE_I;
1055       } else {
1056         *state = GST_DEINTERLACE_BUFFER_STATE_P;
1057       }
1058     }
1059   }
1060
1061   if (i_method)
1062     *i_method = interlacing_method;
1063 }
1064
1065 static void
1066 gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer)
1067 {
1068   int i = 1;
1069   GstClockTime timestamp;
1070   GstDeinterlaceFieldLayout field_layout = self->field_layout;
1071   gboolean repeated = GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_RFF);
1072   gboolean tff = GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_TFF);
1073   gboolean onefield =
1074       GST_BUFFER_FLAG_IS_SET (buffer, GST_VIDEO_BUFFER_ONEFIELD);
1075   GstBuffer *field1, *field2;
1076   guint fields_to_push = (onefield) ? 1 : (!repeated) ? 2 : 3;
1077   gint field1_flags, field2_flags;
1078   GstDeinterlaceInterlacingMethod interlacing_method;
1079   guint8 buf_state;
1080
1081   g_return_if_fail (self->history_count <
1082       GST_DEINTERLACE_MAX_FIELD_HISTORY - fields_to_push);
1083
1084   gst_deinterlace_get_buffer_state (self, buffer, &buf_state,
1085       &interlacing_method);
1086
1087   GST_DEBUG_OBJECT (self,
1088       "Pushing new buffer to the history: ptr %p at %" GST_TIME_FORMAT
1089       " with duration %" GST_TIME_FORMAT
1090       ", size %u, state %u, interlacing method %s", GST_BUFFER_DATA (buffer),
1091       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1092       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)), GST_BUFFER_SIZE (buffer),
1093       buf_state,
1094       interlacing_method ==
1095       GST_DEINTERLACE_TELECINE ? "TC" : interlacing_method ==
1096       GST_DEINTERLACE_INTERLACED ? "I" : "P");
1097
1098   /* move up for new state */
1099   memmove (&self->buf_states[1], &self->buf_states[0],
1100       (GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY - 1) *
1101       sizeof (GstDeinterlaceBufferState));
1102   self->buf_states[0].state = buf_state;
1103   self->buf_states[0].timestamp = GST_BUFFER_TIMESTAMP (buffer);
1104   self->buf_states[0].duration = GST_BUFFER_DURATION (buffer);
1105   if (self->state_count < GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY)
1106     self->state_count++;
1107
1108   if (buf_state == GST_DEINTERLACE_BUFFER_STATE_DROP) {
1109     GST_DEBUG_OBJECT (self,
1110         "Buffer contains only unneeded repeated fields, dropping and not"
1111         "adding to field history");
1112     gst_buffer_unref (buffer);
1113     return;
1114   }
1115
1116   /* telecine does not make use of repeated fields */
1117   if (interlacing_method == GST_DEINTERLACE_TELECINE)
1118     repeated = FALSE;
1119
1120   for (i = GST_DEINTERLACE_MAX_FIELD_HISTORY - 1; i >= fields_to_push; i--) {
1121     self->field_history[i].buf = self->field_history[i - fields_to_push].buf;
1122     self->field_history[i].flags =
1123         self->field_history[i - fields_to_push].flags;
1124   }
1125
1126   if (field_layout == GST_DEINTERLACE_LAYOUT_AUTO) {
1127     if (!self->interlaced) {
1128       GST_WARNING_OBJECT (self, "Can't detect field layout -- assuming TFF");
1129       field_layout = GST_DEINTERLACE_LAYOUT_TFF;
1130     } else if (tff) {
1131       field_layout = GST_DEINTERLACE_LAYOUT_TFF;
1132     } else {
1133       field_layout = GST_DEINTERLACE_LAYOUT_BFF;
1134     }
1135   }
1136
1137   if (field_layout == GST_DEINTERLACE_LAYOUT_TFF) {
1138     GST_DEBUG_OBJECT (self, "Top field first");
1139     field1 = gst_buffer_make_metadata_writable (gst_buffer_ref (buffer));
1140     field1_flags = PICTURE_INTERLACED_TOP;
1141     field2 = gst_buffer_make_metadata_writable (gst_buffer_ref (buffer));
1142     field2_flags = PICTURE_INTERLACED_BOTTOM;
1143   } else {
1144     GST_DEBUG_OBJECT (self, "Bottom field first");
1145     field1 = gst_buffer_make_metadata_writable (gst_buffer_ref (buffer));
1146     field1_flags = PICTURE_INTERLACED_BOTTOM;
1147     field2 = gst_buffer_make_metadata_writable (gst_buffer_ref (buffer));
1148     field2_flags = PICTURE_INTERLACED_TOP;
1149   }
1150
1151   if (interlacing_method != GST_DEINTERLACE_TELECINE) {
1152     /* Timestamps are assigned to the field buffers under the assumption that
1153        the timestamp of the buffer equals the first fields timestamp */
1154
1155     timestamp = GST_BUFFER_TIMESTAMP (buffer);
1156     GST_BUFFER_TIMESTAMP (field1) = timestamp;
1157     GST_BUFFER_TIMESTAMP (field2) = timestamp + self->field_duration;
1158     if (repeated)
1159       GST_BUFFER_TIMESTAMP (field2) += self->field_duration;
1160   }
1161
1162   if (repeated) {
1163     self->field_history[2].buf = field1;
1164     self->field_history[2].flags = field1_flags;
1165
1166     self->field_history[1].buf = field2;
1167     self->field_history[1].flags = field2_flags;
1168
1169     self->field_history[0].buf =
1170         gst_buffer_make_metadata_writable (gst_buffer_ref (field1));
1171     GST_BUFFER_TIMESTAMP (self->field_history[0].buf) +=
1172         2 * self->field_duration;
1173     self->field_history[0].flags = field1_flags;
1174   } else if (!onefield) {
1175     self->field_history[1].buf = field1;
1176     self->field_history[1].flags = field1_flags;
1177
1178     self->field_history[0].buf = field2;
1179     self->field_history[0].flags = field2_flags;
1180   } else {                      /* onefield */
1181     self->field_history[0].buf = field1;
1182     self->field_history[0].flags = field1_flags;
1183     gst_buffer_unref (field2);
1184   }
1185
1186   self->history_count += fields_to_push;
1187   self->cur_field_idx += fields_to_push;
1188
1189   GST_DEBUG_OBJECT (self, "Pushed buffer -- current history size %d, index %d",
1190       self->history_count, self->cur_field_idx);
1191
1192   if (self->last_buffer)
1193     gst_buffer_unref (self->last_buffer);
1194   self->last_buffer = buffer;
1195 }
1196
1197 static void
1198 gst_deinterlace_update_qos (GstDeinterlace * self, gdouble proportion,
1199     GstClockTimeDiff diff, GstClockTime timestamp)
1200 {
1201   GST_DEBUG_OBJECT (self,
1202       "Updating QoS: proportion %lf, diff %s%" GST_TIME_FORMAT ", timestamp %"
1203       GST_TIME_FORMAT, proportion, (diff < 0) ? "-" : "",
1204       GST_TIME_ARGS (ABS (diff)), GST_TIME_ARGS (timestamp));
1205
1206   GST_OBJECT_LOCK (self);
1207   self->proportion = proportion;
1208   if (G_LIKELY (timestamp != GST_CLOCK_TIME_NONE)) {
1209     if (G_UNLIKELY (diff > 0))
1210       self->earliest_time =
1211           timestamp + 2 * diff + ((self->fields ==
1212               GST_DEINTERLACE_ALL) ? self->field_duration : 2 *
1213           self->field_duration);
1214     else
1215       self->earliest_time = timestamp + diff;
1216   } else {
1217     self->earliest_time = GST_CLOCK_TIME_NONE;
1218   }
1219   GST_OBJECT_UNLOCK (self);
1220 }
1221
1222 static void
1223 gst_deinterlace_reset_qos (GstDeinterlace * self)
1224 {
1225   gst_deinterlace_update_qos (self, 0.5, 0, GST_CLOCK_TIME_NONE);
1226 }
1227
1228 static void
1229 gst_deinterlace_read_qos (GstDeinterlace * self, gdouble * proportion,
1230     GstClockTime * time)
1231 {
1232   GST_OBJECT_LOCK (self);
1233   *proportion = self->proportion;
1234   *time = self->earliest_time;
1235   GST_OBJECT_UNLOCK (self);
1236 }
1237
1238 /* Perform qos calculations before processing the next frame. Returns TRUE if
1239  * the frame should be processed, FALSE if the frame can be dropped entirely */
1240 static gboolean
1241 gst_deinterlace_do_qos (GstDeinterlace * self, GstClockTime timestamp)
1242 {
1243   GstClockTime qostime, earliest_time;
1244   gdouble proportion;
1245
1246   /* no timestamp, can't do QoS => process frame */
1247   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
1248     GST_LOG_OBJECT (self, "invalid timestamp, can't do QoS, process frame");
1249     return TRUE;
1250   }
1251
1252   /* get latest QoS observation values */
1253   gst_deinterlace_read_qos (self, &proportion, &earliest_time);
1254
1255   /* skip qos if we have no observation (yet) => process frame */
1256   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
1257     GST_LOG_OBJECT (self, "no observation yet, process frame");
1258     return TRUE;
1259   }
1260
1261   /* qos is done on running time */
1262   qostime = gst_segment_to_running_time (&self->segment, GST_FORMAT_TIME,
1263       timestamp);
1264
1265   /* see how our next timestamp relates to the latest qos timestamp */
1266   GST_LOG_OBJECT (self, "qostime %" GST_TIME_FORMAT ", earliest %"
1267       GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
1268
1269   if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
1270     GST_DEBUG_OBJECT (self, "we are late, drop frame");
1271     return FALSE;
1272   }
1273
1274   GST_LOG_OBJECT (self, "process frame");
1275   return TRUE;
1276 }
1277
1278 static gboolean
1279 gst_deinterlace_fix_timestamps (GstDeinterlace * self,
1280     GstDeinterlaceField * field1, GstDeinterlaceField * field2)
1281 {
1282   GstDeinterlaceField *field3, *field4;
1283   GstDeinterlaceInterlacingMethod interlacing_method;
1284
1285   if (self->pattern_lock && self->pattern > -1) {
1286     /* accurate pattern-locked timestamp adjustment */
1287     if (!self->pattern_count)
1288       gst_deinterlace_update_pattern_timestamps (self);
1289
1290     GST_BUFFER_TIMESTAMP (field1->buf) =
1291         self->pattern_base_ts + self->output_count * self->pattern_buf_dur;
1292     GST_BUFFER_DURATION (field1->buf) = self->pattern_buf_dur;
1293     self->output_count++;
1294   } else {
1295     /* naive (but low-latency) timestamp adjustment based on subsequent
1296      * fields/buffers */
1297     if (field2
1298         && GST_BUFFER_DATA (field1->buf) != GST_BUFFER_DATA (field2->buf)) {
1299       if (GST_BUFFER_TIMESTAMP (field1->buf) +
1300           GST_BUFFER_DURATION (field1->buf) ==
1301           GST_BUFFER_TIMESTAMP (field2->buf)) {
1302         GST_BUFFER_TIMESTAMP (field1->buf) =
1303             GST_BUFFER_TIMESTAMP (field2->buf) =
1304             (GST_BUFFER_TIMESTAMP (field1->buf) +
1305             GST_BUFFER_TIMESTAMP (field2->buf)) / 2;
1306       } else {
1307         GST_BUFFER_TIMESTAMP (field2->buf) = GST_BUFFER_TIMESTAMP (field1->buf);
1308       }
1309     }
1310
1311     if (self->history_count < 3) {
1312       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need 3)",
1313           self->history_count);
1314       return FALSE;
1315     }
1316
1317     field3 = &self->field_history[self->history_count - 3];
1318     interlacing_method =
1319         gst_deinterlace_get_interlacing_method (GST_BUFFER_CAPS (field3->buf));
1320     if (interlacing_method == GST_DEINTERLACE_TELECINE) {
1321       if (self->history_count < 4) {
1322         GST_DEBUG_OBJECT (self, "Need more fields (have %d, need 4)",
1323             self->history_count);
1324         return FALSE;
1325       }
1326
1327       field4 = &self->field_history[self->history_count - 4];
1328       if (GST_BUFFER_DATA (field3->buf) != GST_BUFFER_DATA (field4->buf)) {
1329         /* telecine fields in separate buffers */
1330         GST_BUFFER_TIMESTAMP (field3->buf) =
1331             (GST_BUFFER_TIMESTAMP (field3->buf) +
1332             GST_BUFFER_TIMESTAMP (field4->buf)) / 2;
1333       }
1334     }
1335
1336     GST_BUFFER_DURATION (field1->buf) =
1337         GST_BUFFER_TIMESTAMP (field3->buf) - GST_BUFFER_TIMESTAMP (field1->buf);
1338   }
1339
1340   GST_DEBUG_OBJECT (self,
1341       "Field 1 adjusted to ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
1342       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1->buf)),
1343       GST_TIME_ARGS (GST_BUFFER_DURATION (field1->buf)));
1344   return TRUE;
1345 }
1346
1347 static void
1348 gst_deinterlace_get_pattern_lock (GstDeinterlace * self, gboolean * flush_one)
1349 {
1350   /* loop over all possible patterns and all possible phases
1351    * giving each a score. the highest score gets the lock */
1352   /* the score is calculated as the number of matched buffers in the
1353    * sequence starting at the phase offset with those from the history
1354    * then the longest duration pattern match is taken. if there is more than
1355    * one pattern matching all buffers, we take the longest pattern of those.
1356    * matches to complete patterns are preferred. if no non-trivial pattern is
1357    * matched, trivial patterns are tested. */
1358   gint i, j, k, score, pattern, phase;
1359   const gint state_count = self->state_count;
1360   const gint n_required = self->ignore_obscure ?
1361       GST_DEINTERLACE_OBSCURE_THRESHOLD :
1362       GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY;
1363
1364   /* set unknown pattern as this is used in logic outside this function */
1365   self->pattern = -1;
1366
1367   /* wait for more buffers */
1368   if (!self->have_eos && state_count < n_required) {
1369     GST_DEBUG_OBJECT (self, "Need more buffers in state history - %d/%d",
1370         state_count, n_required);
1371     return;
1372   }
1373
1374   score = pattern = phase = -1;
1375
1376   /* loop over all patterns */
1377   for (i = 0; i < G_N_ELEMENTS (telecine_patterns); i++) {
1378     const guint8 length = telecine_patterns[i].length;
1379
1380     if (self->ignore_obscure && i >= GST_DEINTERLACE_OBSCURE_THRESHOLD)
1381       break;
1382
1383     if (state_count < length)
1384       continue;
1385
1386     /* loop over all phases */
1387     for (j = 0; j < length; j++) {
1388       /* low-latency mode looks at past buffers, high latency at future buffers */
1389       const gint state_idx = (self->low_latency ? length : state_count) - 1;
1390       /* loop over history, breaking on differing buffer states */
1391       for (k = 0; k < length && k < state_count; k++) {
1392         const guint8 hist = self->buf_states[state_idx - k].state;
1393         const guint8 patt = telecine_patterns[i].states[(j + k) % length];
1394         if (!(hist & patt))
1395           break;
1396       }
1397
1398       /* make complete matches more signficant */
1399       if (k == length)
1400         k += GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY;
1401
1402       /* take as new best pattern if the number of matched buffers is more than
1403        * for other patterns */
1404       if (k > score) {
1405         score = k;
1406         pattern = i;
1407         phase = j;
1408         if (self->low_latency) {
1409           /* state_idx + 1 is the number of buffers yet to be pushed out
1410            * so length - state_idx - 1 is the number of old buffers in the
1411            * pattern */
1412           phase = (phase + length - state_idx - 1) % length;
1413         }
1414       }
1415     }
1416   }
1417
1418   GST_DEBUG_OBJECT (self,
1419       "Final pattern match result: pa %d, ph %d, l %d, s %d", pattern, phase,
1420       telecine_patterns[pattern].length, score);
1421   self->pattern = pattern;
1422   self->pattern_phase = phase;
1423   self->pattern_count = 0;
1424   self->output_count = 0;
1425   self->pattern_lock = TRUE;
1426
1427   /* check for the case that the first field of the pattern is an orphan */
1428   if (pattern > 1
1429       && telecine_patterns[pattern].states[phase] & (GST_ONE | GST_INT)) {
1430     gint i = phase, field_count = 0;
1431     guint8 state = telecine_patterns[pattern].states[i];
1432
1433     do {
1434       if (state & GST_ONE) {
1435         field_count++;
1436       } else if (!(state & GST_DRP)) {
1437         field_count += 2;
1438       }
1439       i++;
1440       i %= telecine_patterns[pattern].length;
1441       state = telecine_patterns[pattern].states[i];
1442     } while (!(state & GST_PRG));
1443
1444     /* if field_count is odd, we have an orphan field at the beginning of the
1445      * sequence
1446      * note - don't do this in low-latency mode as we are somewhere within the
1447      * pattern already */
1448     if (!self->low_latency && (*flush_one = field_count & 1)) {
1449       GST_DEBUG_OBJECT (self, "Orphan field detected at the beginning of the "
1450           "pattern - it will be deinterlaced.");
1451     }
1452   }
1453 }
1454
1455 static GstFlowReturn
1456 gst_deinterlace_output_frame (GstDeinterlace * self, gboolean flushing)
1457 {
1458   GstClockTime timestamp;
1459   GstFlowReturn ret;
1460   gint fields_required;
1461   GstBuffer *buf, *outbuf;
1462   GstDeinterlaceField *field1, *field2;
1463   GstDeinterlaceInterlacingMethod interlacing_method;
1464   guint8 buf_state;
1465   gboolean hl_no_lock;          /* indicates high latency timestamp adjustment but no pattern lock (could be ONEF or I) */
1466   gboolean same_buffer;         /* are field1 and field2 in the same buffer? */
1467   gboolean flush_one;           /* used for flushing one field when in high latency mode and not locked */
1468   TelecinePattern pattern;
1469   guint8 phase, count;
1470   const GstDeinterlaceLocking locking = self->locking;
1471
1472 restart:
1473   ret = GST_FLOW_OK;
1474   fields_required = 0;
1475   hl_no_lock = FALSE;
1476   same_buffer = FALSE;
1477   flush_one = FALSE;
1478   self->need_more = FALSE;
1479   phase = self->pattern_phase;
1480   count = self->pattern_count;
1481
1482   if (!self->history_count) {
1483     GST_DEBUG_OBJECT (self, "History is empty, waiting for more buffers!");
1484     goto need_more;
1485   }
1486
1487   field1 = &self->field_history[self->history_count - 1];
1488
1489   if (locking != GST_DEINTERLACE_LOCKING_NONE) {
1490     if (!self->state_count) {
1491       GST_ERROR_OBJECT (self,
1492           "BROKEN! Fields in history + no states should not happen!");
1493       return GST_FLOW_ERROR;
1494     }
1495
1496     gst_deinterlace_get_buffer_state (self, field1->buf, &buf_state,
1497         &interlacing_method);
1498
1499     if (self->pattern != -1)
1500       pattern = telecine_patterns[self->pattern];
1501
1502     /* patterns 0 and 1 are interlaced, the rest are telecine */
1503     if (self->pattern > 1)
1504       interlacing_method = GST_DEINTERLACE_TELECINE;
1505
1506     if (self->pattern == -1 || self->pattern_refresh
1507         || !(buf_state & pattern.states[(phase + count) % pattern.length])) {
1508       /* no pattern, pattern refresh set or unexpected buffer state */
1509       self->pattern_lock = FALSE;
1510       self->pattern_refresh = TRUE;
1511
1512       /* refresh pattern lock */
1513       gst_deinterlace_get_pattern_lock (self, &flush_one);
1514
1515       if (self->pattern != -1) {
1516         /* locked onto a valid pattern so refresh complete */
1517         GST_DEBUG_OBJECT (self, "Pattern locked! %s starting at %d",
1518             telecine_patterns[self->pattern].nick, self->pattern_phase);
1519         self->pattern_refresh = FALSE;
1520       } else if (!self->low_latency) {
1521         if (!self->pattern_lock) {
1522           goto need_more;
1523         } else {
1524           hl_no_lock = TRUE;
1525         }
1526       }
1527
1528       /* setcaps on sink and src pads */
1529       gst_deinterlace_setcaps (self->sinkpad, GST_PAD_CAPS (self->sinkpad));
1530
1531       if (flush_one && self->drop_orphans) {
1532         GST_DEBUG_OBJECT (self, "Dropping orphan first field");
1533         self->cur_field_idx--;
1534         gst_buffer_unref (gst_deinterlace_pop_history (self));
1535         goto restart;
1536       }
1537     }
1538   } else {
1539     gst_deinterlace_get_buffer_state (self, field1->buf, NULL,
1540         &interlacing_method);
1541   }
1542
1543   same_buffer = self->history_count >= 2
1544       && (GST_BUFFER_DATA (field1->buf) ==
1545       GST_BUFFER_DATA (self->field_history[self->history_count - 2].buf));
1546
1547   if ((flushing && self->history_count == 1) || (flush_one
1548           && !self->drop_orphans) || (hl_no_lock && (self->history_count == 1
1549               || !same_buffer))) {
1550     GST_DEBUG_OBJECT (self, "Flushing one field using linear method");
1551     gst_deinterlace_set_method (self, GST_DEINTERLACE_LINEAR);
1552     fields_required = gst_deinterlace_method_get_fields_required (self->method);
1553   } else if (interlacing_method == GST_DEINTERLACE_TELECINE
1554       && (self->low_latency > 0 || self->pattern != -1 || (hl_no_lock
1555               && same_buffer
1556               && GST_BUFFER_FLAG_IS_SET (field1->buf,
1557                   GST_VIDEO_BUFFER_PROGRESSIVE)))) {
1558     /* telecined - we reconstruct frames by weaving pairs of fields */
1559     fields_required = 2;
1560     if (!flushing && self->history_count < fields_required) {
1561       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1562           self->history_count, self->cur_field_idx + fields_required);
1563       goto need_more;
1564     }
1565
1566     field2 = &self->field_history[self->history_count - 2];
1567     if (!gst_deinterlace_fix_timestamps (self, field1, field2) && !flushing)
1568       goto need_more;
1569
1570     if (same_buffer) {
1571       /* telecine progressive */
1572       GstBuffer *field1_buf;
1573
1574       GST_DEBUG_OBJECT (self,
1575           "Frame type: Telecine Progressive; pushing buffer as a frame");
1576       /* pop and push */
1577       self->cur_field_idx--;
1578       field1_buf = gst_deinterlace_pop_history (self);
1579       /* field2 is the same buffer as field1, but we need to remove it from
1580        * the history anyway */
1581       self->cur_field_idx--;
1582       gst_buffer_unref (gst_deinterlace_pop_history (self));
1583       /* set the caps from the src pad on the buffer as they should be correct */
1584       gst_buffer_set_caps (field1_buf, GST_PAD_CAPS (self->srcpad));
1585       GST_DEBUG_OBJECT (self,
1586           "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1587           GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1_buf)),
1588           GST_TIME_ARGS (GST_BUFFER_DURATION (field1_buf)),
1589           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1_buf) +
1590               GST_BUFFER_DURATION (field1_buf)));
1591       return gst_pad_push (self->srcpad, field1_buf);
1592     } else {
1593       /* telecine fields in separate buffers */
1594
1595       /* check field1 and field2 buffer caps and flags are corresponding */
1596       if (field1->flags == field2->flags) {
1597         /* ERROR - fields are of same parity - what should be done here?
1598          * perhaps deinterlace the tip field and start again? */
1599         GST_ERROR_OBJECT (self, "Telecine mixed with fields of same parity!");
1600       }
1601       GST_DEBUG_OBJECT (self,
1602           "Frame type: Telecine Mixed; weaving tip two fields into a frame");
1603       /* set method to WEAVE */
1604       gst_deinterlace_set_method (self, GST_DEINTERLACE_WEAVE);
1605     }
1606   } else if (interlacing_method == GST_DEINTERLACE_INTERLACED || (hl_no_lock
1607           && interlacing_method == GST_DEINTERLACE_TELECINE && same_buffer
1608           && !GST_BUFFER_FLAG_IS_SET (field1->buf,
1609               GST_VIDEO_BUFFER_PROGRESSIVE))) {
1610     gst_deinterlace_set_method (self, self->user_set_method_id);
1611     fields_required = gst_deinterlace_method_get_fields_required (self->method);
1612     if (flushing && self->history_count < fields_required) {
1613       /* note: we already checked for flushing with history count == 1 above
1614        * so we must have 2 or more fields in here */
1615       gst_deinterlace_set_method (self, GST_DEINTERLACE_VFIR);
1616       fields_required =
1617           gst_deinterlace_method_get_fields_required (self->method);
1618       GST_DEBUG_OBJECT (self, "Flushing field(s) using %s method",
1619           methods_types[self->method_id].value_nick);
1620     }
1621
1622     /* Not enough fields in the history */
1623     if (!flushing && self->history_count < fields_required) {
1624       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1625           self->history_count, self->cur_field_idx + fields_required);
1626       goto need_more;
1627     }
1628
1629     GST_DEBUG_OBJECT (self,
1630         "Frame type: Interlaced; deinterlacing using %s method",
1631         methods_types[self->method_id].value_nick);
1632   } else {
1633     GstBuffer *field1_buf;
1634
1635     /* progressive */
1636     fields_required = 2;
1637
1638     /* Not enough fields in the history */
1639     if (!flushing && self->history_count < fields_required) {
1640       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1641           self->history_count, self->cur_field_idx + fields_required);
1642       goto need_more;
1643     }
1644
1645     field2 = &self->field_history[self->history_count - 2];
1646     if (GST_BUFFER_DATA (field1->buf) != GST_BUFFER_DATA (field2->buf)) {
1647       /* ERROR - next two fields in field history are not one progressive buffer - weave? */
1648       GST_ERROR_OBJECT (self,
1649           "Progressive buffer but two fields at tip aren't in the same buffer!");
1650     }
1651
1652     GST_DEBUG_OBJECT (self,
1653         "Frame type: Progressive; pushing buffer as a frame");
1654     /* pop and push */
1655     self->cur_field_idx--;
1656     field1_buf = gst_deinterlace_pop_history (self);
1657     /* field2 is the same buffer as field1, but we need to remove it from the
1658      * history anyway */
1659     self->cur_field_idx--;
1660     gst_buffer_unref (gst_deinterlace_pop_history (self));
1661     GST_DEBUG_OBJECT (self,
1662         "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1663         GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1_buf)),
1664         GST_TIME_ARGS (GST_BUFFER_DURATION (field1_buf)),
1665         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1_buf) +
1666             GST_BUFFER_DURATION (field1_buf)));
1667     return gst_pad_push (self->srcpad, field1_buf);
1668   }
1669
1670   if (!flushing && self->cur_field_idx < 1) {
1671     goto need_more;
1672   }
1673
1674   if (self->fields == GST_DEINTERLACE_ALL
1675       || interlacing_method == GST_DEINTERLACE_TELECINE)
1676     GST_DEBUG_OBJECT (self, "All fields");
1677   else if (self->fields == GST_DEINTERLACE_TF)
1678     GST_DEBUG_OBJECT (self, "Top fields");
1679   else if (self->fields == GST_DEINTERLACE_BF)
1680     GST_DEBUG_OBJECT (self, "Bottom fields");
1681
1682   if ((self->field_history[self->cur_field_idx].flags == PICTURE_INTERLACED_TOP
1683           && (self->fields == GST_DEINTERLACE_TF
1684               || interlacing_method == GST_DEINTERLACE_TELECINE))
1685       || self->fields == GST_DEINTERLACE_ALL) {
1686     GST_DEBUG_OBJECT (self, "deinterlacing top field");
1687
1688     /* create new buffer */
1689     ret =
1690         gst_pad_alloc_buffer (self->srcpad, GST_BUFFER_OFFSET_NONE,
1691         self->frame_size, GST_PAD_CAPS (self->srcpad), &outbuf);
1692     if (ret != GST_FLOW_OK)
1693       return ret;
1694
1695     if (GST_PAD_CAPS (self->srcpad) != GST_BUFFER_CAPS (outbuf) &&
1696         !gst_caps_is_equal (GST_PAD_CAPS (self->srcpad),
1697             GST_BUFFER_CAPS (outbuf))) {
1698       gst_caps_replace (&self->request_caps, GST_BUFFER_CAPS (outbuf));
1699       GST_DEBUG_OBJECT (self, "Upstream wants new caps %" GST_PTR_FORMAT,
1700           self->request_caps);
1701
1702       gst_buffer_unref (outbuf);
1703       outbuf = gst_buffer_try_new_and_alloc (self->frame_size);
1704
1705       if (!outbuf)
1706         return GST_FLOW_ERROR;
1707
1708       gst_buffer_set_caps (outbuf, GST_PAD_CAPS (self->srcpad));
1709     }
1710
1711     g_return_val_if_fail (self->history_count >=
1712         1 + gst_deinterlace_method_get_latency (self->method), GST_FLOW_ERROR);
1713
1714     buf =
1715         self->field_history[self->history_count - 1 -
1716         gst_deinterlace_method_get_latency (self->method)].buf;
1717
1718     if (interlacing_method != GST_DEINTERLACE_TELECINE) {
1719       timestamp = GST_BUFFER_TIMESTAMP (buf);
1720
1721       GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1722       if (self->fields == GST_DEINTERLACE_ALL)
1723         GST_BUFFER_DURATION (outbuf) = self->field_duration;
1724       else
1725         GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration;
1726     } else {
1727       GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
1728       GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
1729     }
1730
1731     /* Check if we need to drop the frame because of QoS */
1732     if (!gst_deinterlace_do_qos (self, GST_BUFFER_TIMESTAMP (buf))) {
1733       self->cur_field_idx--;
1734       gst_buffer_unref (gst_deinterlace_pop_history (self));
1735       gst_buffer_unref (outbuf);
1736       outbuf = NULL;
1737       ret = GST_FLOW_OK;
1738     } else {
1739       if (self->cur_field_idx < 0 && flushing) {
1740         if (self->history_count == 1) {
1741           gst_buffer_unref (gst_deinterlace_pop_history (self));
1742           goto need_more;
1743         }
1744         self->cur_field_idx++;
1745       }
1746       if (self->cur_field_idx < 0) {
1747         goto need_more;
1748       }
1749       if (!flushing && self->cur_field_idx < 1) {
1750         goto need_more;
1751       }
1752
1753       /* do magic calculus */
1754       gst_deinterlace_method_deinterlace_frame (self->method,
1755           self->field_history, self->history_count, outbuf,
1756           self->cur_field_idx);
1757
1758       self->cur_field_idx--;
1759       if (self->cur_field_idx + 1 +
1760           gst_deinterlace_method_get_latency (self->method)
1761           < self->history_count || flushing) {
1762         gst_buffer_unref (gst_deinterlace_pop_history (self));
1763       }
1764
1765       if (gst_deinterlace_clip_buffer (self, outbuf)) {
1766         GST_DEBUG_OBJECT (self,
1767             "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1768             GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1769             GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
1770             GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
1771                 GST_BUFFER_DURATION (outbuf)));
1772         ret = gst_pad_push (self->srcpad, outbuf);
1773       } else {
1774         ret = GST_FLOW_OK;
1775         gst_buffer_unref (outbuf);
1776       }
1777
1778       outbuf = NULL;
1779       if (ret != GST_FLOW_OK)
1780         return ret;
1781       if (interlacing_method == GST_DEINTERLACE_TELECINE
1782           && self->method_id == GST_DEINTERLACE_WEAVE) {
1783         /* pop off the second field */
1784         GST_DEBUG_OBJECT (self, "Removing unused field (count: %d)",
1785             self->history_count);
1786         self->cur_field_idx--;
1787         gst_buffer_unref (gst_deinterlace_pop_history (self));
1788         interlacing_method = GST_DEINTERLACE_INTERLACED;
1789         return ret;
1790       }
1791     }
1792
1793     if (flush_one && !self->drop_orphans) {
1794       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
1795       goto restart;
1796     }
1797   }
1798   /* no calculation done: remove excess field */
1799   else if (self->field_history[self->cur_field_idx].flags ==
1800       PICTURE_INTERLACED_TOP && (self->fields == GST_DEINTERLACE_BF
1801           && interlacing_method != GST_DEINTERLACE_TELECINE)) {
1802     GST_DEBUG_OBJECT (self, "Removing unused top field");
1803     self->cur_field_idx--;
1804     gst_buffer_unref (gst_deinterlace_pop_history (self));
1805
1806     if (flush_one && !self->drop_orphans) {
1807       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
1808       goto restart;
1809     }
1810   }
1811
1812   if (self->history_count < fields_required)
1813     return ret;
1814
1815   if (self->cur_field_idx < 0)
1816     return ret;
1817
1818   if (!flushing && self->cur_field_idx < 1) {
1819     return ret;
1820   }
1821
1822   /* deinterlace bottom_field */
1823   if ((self->field_history[self->cur_field_idx].flags ==
1824           PICTURE_INTERLACED_BOTTOM && (self->fields == GST_DEINTERLACE_BF
1825               || interlacing_method == GST_DEINTERLACE_TELECINE))
1826       || self->fields == GST_DEINTERLACE_ALL) {
1827     GST_DEBUG_OBJECT (self, "deinterlacing bottom field");
1828
1829     /* create new buffer */
1830     ret =
1831         gst_pad_alloc_buffer (self->srcpad, GST_BUFFER_OFFSET_NONE,
1832         self->frame_size, GST_PAD_CAPS (self->srcpad), &outbuf);
1833     if (ret != GST_FLOW_OK)
1834       return ret;
1835
1836     if (GST_PAD_CAPS (self->srcpad) != GST_BUFFER_CAPS (outbuf) &&
1837         !gst_caps_is_equal (GST_PAD_CAPS (self->srcpad),
1838             GST_BUFFER_CAPS (outbuf))) {
1839       gst_caps_replace (&self->request_caps, GST_BUFFER_CAPS (outbuf));
1840       GST_DEBUG_OBJECT (self, "Upstream wants new caps %" GST_PTR_FORMAT,
1841           self->request_caps);
1842
1843       gst_buffer_unref (outbuf);
1844       outbuf = gst_buffer_try_new_and_alloc (self->frame_size);
1845
1846       if (!outbuf)
1847         return GST_FLOW_ERROR;
1848
1849       gst_buffer_set_caps (outbuf, GST_PAD_CAPS (self->srcpad));
1850     }
1851
1852     g_return_val_if_fail (self->history_count - 1 -
1853         gst_deinterlace_method_get_latency (self->method) >= 0, GST_FLOW_ERROR);
1854
1855     buf =
1856         self->field_history[self->history_count - 1 -
1857         gst_deinterlace_method_get_latency (self->method)].buf;
1858     if (interlacing_method != GST_DEINTERLACE_TELECINE) {
1859       timestamp = GST_BUFFER_TIMESTAMP (buf);
1860
1861       GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1862       if (self->fields == GST_DEINTERLACE_ALL)
1863         GST_BUFFER_DURATION (outbuf) = self->field_duration;
1864       else
1865         GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration;
1866     } else {
1867       GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
1868       GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
1869     }
1870
1871     /* Check if we need to drop the frame because of QoS */
1872     if (!gst_deinterlace_do_qos (self, GST_BUFFER_TIMESTAMP (buf))) {
1873       self->cur_field_idx--;
1874       gst_buffer_unref (gst_deinterlace_pop_history (self));
1875       gst_buffer_unref (outbuf);
1876       outbuf = NULL;
1877       ret = GST_FLOW_OK;
1878     } else {
1879       /* do magic calculus */
1880       gst_deinterlace_method_deinterlace_frame (self->method,
1881           self->field_history, self->history_count, outbuf,
1882           self->cur_field_idx);
1883
1884       self->cur_field_idx--;
1885       if (self->cur_field_idx + 1 +
1886           gst_deinterlace_method_get_latency (self->method)
1887           < self->history_count) {
1888         gst_buffer_unref (gst_deinterlace_pop_history (self));
1889       }
1890
1891       if (gst_deinterlace_clip_buffer (self, outbuf)) {
1892         GST_DEBUG_OBJECT (self,
1893             "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1894             GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1895             GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
1896             GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
1897                 GST_BUFFER_DURATION (outbuf)));
1898         ret = gst_pad_push (self->srcpad, outbuf);
1899       } else {
1900         ret = GST_FLOW_OK;
1901         gst_buffer_unref (outbuf);
1902       }
1903
1904       outbuf = NULL;
1905       if (ret != GST_FLOW_OK)
1906         return ret;
1907       if (interlacing_method == GST_DEINTERLACE_TELECINE
1908           && self->method_id == GST_DEINTERLACE_WEAVE) {
1909         /* pop off the second field */
1910         GST_DEBUG_OBJECT (self, "Removing unused field (count: %d)",
1911             self->history_count);
1912         self->cur_field_idx--;
1913         gst_buffer_unref (gst_deinterlace_pop_history (self));
1914         interlacing_method = GST_DEINTERLACE_INTERLACED;
1915         return ret;
1916       }
1917     }
1918
1919     if (flush_one && !self->drop_orphans) {
1920       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
1921       goto restart;
1922     }
1923   }
1924   /* no calculation done: remove excess field */
1925   else if (self->field_history[self->cur_field_idx].flags ==
1926       PICTURE_INTERLACED_BOTTOM && (self->fields == GST_DEINTERLACE_TF
1927           && interlacing_method != GST_DEINTERLACE_TELECINE)) {
1928     GST_DEBUG_OBJECT (self, "Removing unused bottom field");
1929     self->cur_field_idx--;
1930     gst_buffer_unref (gst_deinterlace_pop_history (self));
1931
1932     if (flush_one && !self->drop_orphans) {
1933       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
1934       goto restart;
1935     }
1936   }
1937
1938   return ret;
1939
1940 need_more:
1941   self->need_more = TRUE;
1942   return ret;
1943 }
1944
1945 static gboolean
1946 gst_deinterlace_get_latency (GstDeinterlace * self)
1947 {
1948   if (self->locking == GST_DEINTERLACE_LOCKING_AUTO) {
1949     gboolean res;
1950     GstQuery *query;
1951
1952     query = gst_query_new_latency ();
1953     if ((res = gst_pad_peer_query (self->sinkpad, query))) {
1954       gboolean is_live;
1955       /* if upstream is live, we use low-latency passive locking mode
1956        * else high-latency active locking mode */
1957       gst_query_parse_latency (query, &is_live, NULL, NULL);
1958       GST_DEBUG_OBJECT (self, "Latency query indicates stream is %s",
1959           is_live ? "live - using passive locking" :
1960           "not live - using active locking");
1961       gst_query_unref (query);
1962       return is_live;
1963     } else {
1964       /* conservatively use passive locking if the query fails */
1965       GST_WARNING_OBJECT (self,
1966           "Latency query failed - fall back to using passive locking");
1967       gst_query_unref (query);
1968       return TRUE;
1969     }
1970   } else {
1971     return self->locking - 2;
1972   }
1973 }
1974
1975 static GstFlowReturn
1976 gst_deinterlace_chain (GstPad * pad, GstBuffer * buf)
1977 {
1978   GstDeinterlace *self = GST_DEINTERLACE (GST_PAD_PARENT (pad));
1979   GstFlowReturn ret = GST_FLOW_OK;
1980
1981   GST_OBJECT_LOCK (self);
1982   if (self->reconfigure) {
1983     if (self->new_fields != -1)
1984       self->fields = self->new_fields;
1985     if (self->new_mode != -1)
1986       self->mode = self->new_mode;
1987     self->new_mode = -1;
1988     self->new_fields = -1;
1989
1990     self->reconfigure = FALSE;
1991     GST_OBJECT_UNLOCK (self);
1992     if (GST_PAD_CAPS (self->srcpad))
1993       gst_deinterlace_setcaps (self->sinkpad, GST_PAD_CAPS (self->sinkpad));
1994   } else {
1995     GST_OBJECT_UNLOCK (self);
1996   }
1997
1998   GST_DEBUG_OBJECT (self,
1999       "[IN] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2000       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
2001       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
2002       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)));
2003
2004   if (self->still_frame_mode || self->passthrough) {
2005     GST_DEBUG_OBJECT (self,
2006         "Frame type: Progressive?; pushing buffer using pass-through");
2007     GST_DEBUG_OBJECT (self,
2008         "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2009         GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
2010         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
2011         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)));
2012
2013     return gst_pad_push (self->srcpad, buf);
2014   }
2015
2016   if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
2017     GST_DEBUG_OBJECT (self, "DISCONT buffer, resetting history");
2018     gst_deinterlace_reset_history (self, FALSE);
2019   }
2020
2021   gst_deinterlace_push_history (self, buf);
2022   buf = NULL;
2023
2024   do {
2025     ret = gst_deinterlace_output_frame (self, FALSE);
2026   } while (!self->need_more && self->history_count > 0 && ret == GST_FLOW_OK);
2027
2028   return ret;
2029 }
2030
2031 static gint
2032 gst_greatest_common_divisor (gint a, gint b)
2033 {
2034   while (b != 0) {
2035     int temp = a;
2036
2037     a = b;
2038     b = temp % b;
2039   }
2040
2041   return ABS (a);
2042 }
2043
2044 static gboolean
2045 gst_fraction_double (gint * n_out, gint * d_out, gboolean half)
2046 {
2047   gint n, d, gcd;
2048
2049   n = *n_out;
2050   d = *d_out;
2051
2052   if (d == 0)
2053     return FALSE;
2054
2055   if (n == 0 || (n == G_MAXINT && d == 1))
2056     return TRUE;
2057
2058   gcd = gst_greatest_common_divisor (n, d);
2059   n /= gcd;
2060   d /= gcd;
2061
2062   if (!half) {
2063     if (G_MAXINT / 2 >= ABS (n)) {
2064       n *= 2;
2065     } else if (d >= 2) {
2066       d /= 2;
2067     } else {
2068       return FALSE;
2069     }
2070   } else {
2071     if (G_MAXINT / 2 >= ABS (d)) {
2072       d *= 2;
2073     } else if (n >= 2) {
2074       n /= 2;
2075     } else {
2076       return FALSE;
2077     }
2078   }
2079
2080   *n_out = n;
2081   *d_out = d;
2082
2083   return TRUE;
2084 }
2085
2086 static GstCaps *
2087 gst_deinterlace_getcaps (GstPad * pad)
2088 {
2089   GstCaps *ret;
2090   GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad));
2091   GstPad *otherpad;
2092   gint len;
2093   const GstCaps *ourcaps;
2094   GstCaps *peercaps;
2095
2096   otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad;
2097
2098   ourcaps = gst_pad_get_pad_template_caps (pad);
2099   peercaps = gst_pad_peer_get_caps (otherpad);
2100
2101   if (peercaps) {
2102     GST_DEBUG_OBJECT (pad, "Peer has caps %" GST_PTR_FORMAT, peercaps);
2103     ret = gst_caps_intersect (ourcaps, peercaps);
2104     gst_caps_unref (peercaps);
2105   } else {
2106     ret = gst_caps_copy (ourcaps);
2107   }
2108
2109   for (len = gst_caps_get_size (ret); len > 0; len--) {
2110     GstStructure *s = gst_caps_get_structure (ret, len - 1);
2111
2112     if (pad == self->sinkpad || self->passthrough)
2113       gst_structure_remove_field (s, "interlaced");
2114     else
2115       gst_structure_set (s, "interlaced", G_TYPE_BOOLEAN, FALSE, NULL);
2116
2117     if (!self->passthrough && self->fields == GST_DEINTERLACE_ALL) {
2118       const GValue *val;
2119
2120       val = gst_structure_get_value (s, "framerate");
2121       if (!val)
2122         continue;
2123
2124       if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) {
2125         gint n, d;
2126
2127         n = gst_value_get_fraction_numerator (val);
2128         d = gst_value_get_fraction_denominator (val);
2129
2130         if (!gst_fraction_double (&n, &d, pad != self->srcpad)) {
2131           goto error;
2132         }
2133
2134         gst_structure_set (s, "framerate", GST_TYPE_FRACTION, n, d, NULL);
2135       } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) {
2136         const GValue *min, *max;
2137         GValue nrange = { 0, }, nmin = {
2138         0,}, nmax = {
2139         0,};
2140         gint n, d;
2141
2142         g_value_init (&nrange, GST_TYPE_FRACTION_RANGE);
2143         g_value_init (&nmin, GST_TYPE_FRACTION);
2144         g_value_init (&nmax, GST_TYPE_FRACTION);
2145
2146         min = gst_value_get_fraction_range_min (val);
2147         max = gst_value_get_fraction_range_max (val);
2148
2149         n = gst_value_get_fraction_numerator (min);
2150         d = gst_value_get_fraction_denominator (min);
2151
2152         if (!gst_fraction_double (&n, &d, pad != self->srcpad)) {
2153           g_value_unset (&nrange);
2154           g_value_unset (&nmax);
2155           g_value_unset (&nmin);
2156           goto error;
2157         }
2158
2159         gst_value_set_fraction (&nmin, n, d);
2160
2161         n = gst_value_get_fraction_numerator (max);
2162         d = gst_value_get_fraction_denominator (max);
2163
2164         if (!gst_fraction_double (&n, &d, pad != self->srcpad)) {
2165           g_value_unset (&nrange);
2166           g_value_unset (&nmax);
2167           g_value_unset (&nmin);
2168           goto error;
2169         }
2170
2171         gst_value_set_fraction (&nmax, n, d);
2172         gst_value_set_fraction_range (&nrange, &nmin, &nmax);
2173
2174         gst_structure_set_value (s, "framerate", &nrange);
2175
2176         g_value_unset (&nmin);
2177         g_value_unset (&nmax);
2178         g_value_unset (&nrange);
2179       } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) {
2180         const GValue *lval;
2181         GValue nlist = { 0, };
2182         GValue nval = { 0, };
2183         gint i;
2184
2185         g_value_init (&nlist, GST_TYPE_LIST);
2186         for (i = gst_value_list_get_size (val); i > 0; i--) {
2187           gint n, d;
2188
2189           lval = gst_value_list_get_value (val, i);
2190
2191           if (G_VALUE_TYPE (lval) != GST_TYPE_FRACTION)
2192             continue;
2193
2194           n = gst_value_get_fraction_numerator (lval);
2195           d = gst_value_get_fraction_denominator (lval);
2196
2197           /* Double/Half the framerate but if this fails simply
2198            * skip this value from the list */
2199           if (!gst_fraction_double (&n, &d, pad != self->srcpad)) {
2200             continue;
2201           }
2202
2203           g_value_init (&nval, GST_TYPE_FRACTION);
2204
2205           gst_value_set_fraction (&nval, n, d);
2206           gst_value_list_append_value (&nlist, &nval);
2207           g_value_unset (&nval);
2208         }
2209         gst_structure_set_value (s, "framerate", &nlist);
2210         g_value_unset (&nlist);
2211       }
2212     }
2213   }
2214
2215   GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, ret);
2216
2217   gst_object_unref (self);
2218
2219   return ret;
2220
2221 error:
2222   GST_ERROR_OBJECT (pad, "Unable to transform peer caps");
2223   gst_caps_unref (ret);
2224   return NULL;
2225 }
2226
2227 static gboolean
2228 gst_deinterlace_setcaps (GstPad * pad, GstCaps * caps)
2229 {
2230   gboolean res = TRUE;
2231   GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad));
2232   GstCaps *srccaps;
2233   GstDeinterlaceInterlacingMethod interlacing_method;
2234
2235   if (self->locking != GST_DEINTERLACE_LOCKING_NONE) {
2236     if (self->low_latency == -1)
2237       self->low_latency = gst_deinterlace_get_latency (self);
2238
2239     if (self->pattern_lock) {
2240       /* refresh has been successful - we have a lock now */
2241       self->pattern_refresh = FALSE;
2242     } else {
2243       /* if we were not refreshing (!pattern_refresh) the caps have changed
2244        * so we need to refresh and we don't have a lock anymore
2245        * otherwise we have pattern_fresh and !pattern_lock anyway */
2246       self->pattern_refresh = TRUE;
2247       self->pattern_lock = FALSE;
2248     }
2249   }
2250
2251   res =
2252       gst_video_format_parse_caps (caps, &self->format, &self->width,
2253       &self->height);
2254   res &= gst_video_parse_caps_framerate (caps, &self->fps_n, &self->fps_d);
2255   if (pad == self->sinkpad)
2256     res &= gst_video_format_parse_caps_interlaced (caps, &self->interlaced);
2257   if (!res)
2258     goto invalid_caps;
2259
2260   gst_deinterlace_update_passthrough (self);
2261
2262   interlacing_method = gst_deinterlace_get_interlacing_method (caps);
2263
2264   if (self->pattern_lock) {
2265     srccaps = gst_caps_copy (caps);
2266     if (self->pattern != -1
2267         && G_UNLIKELY (!gst_util_fraction_multiply (self->fps_n, self->fps_d,
2268                 telecine_patterns[self->pattern].ratio_n,
2269                 telecine_patterns[self->pattern].ratio_d, &self->fps_n,
2270                 &self->fps_d)))
2271       GST_ERROR_OBJECT (self,
2272           "Multiplying the framerate by the telecine pattern ratio overflowed!");
2273     gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, self->fps_n,
2274         self->fps_d, NULL);
2275   } else if (self->low_latency > 0) {
2276     if (interlacing_method == GST_DEINTERLACE_TELECINE) {
2277       /* for initial buffers of a telecine pattern, until there is a lock we
2278        * we output naïvely adjusted timestamps */
2279       srccaps = gst_caps_copy (caps);
2280       gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
2281     } else if (!self->passthrough && self->fields == GST_DEINTERLACE_ALL) {
2282       gint fps_n = self->fps_n, fps_d = self->fps_d;
2283
2284       if (!gst_fraction_double (&fps_n, &fps_d, FALSE))
2285         goto invalid_caps;
2286
2287       srccaps = gst_caps_copy (caps);
2288
2289       gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, fps_n,
2290           fps_d, NULL);
2291     } else {
2292       srccaps = gst_caps_ref (caps);
2293     }
2294   } else {
2295     /* in high latency pattern locking mode if we don't have a pattern lock,
2296      * the sink pad caps are the best we know */
2297     srccaps = gst_caps_ref (caps);
2298   }
2299
2300   if (self->mode != GST_DEINTERLACE_MODE_DISABLED) {
2301     srccaps = gst_caps_make_writable (srccaps);
2302     gst_structure_remove_field (gst_caps_get_structure (srccaps, 0),
2303         "interlacing-method");
2304     gst_caps_set_simple (srccaps, "interlaced", G_TYPE_BOOLEAN, FALSE, NULL);
2305   }
2306
2307   if (!gst_pad_set_caps (self->srcpad, srccaps))
2308     goto caps_not_accepted;
2309
2310   self->frame_size =
2311       gst_video_format_get_size (self->format, self->width, self->height);
2312
2313   if (G_LIKELY (self->fps_n != 0)) {
2314     self->field_duration =
2315         gst_util_uint64_scale (GST_SECOND, self->fps_d, 2 * self->fps_n);
2316   } else {
2317     self->field_duration = 0;
2318   }
2319
2320   gst_deinterlace_set_method (self, self->method_id);
2321   gst_deinterlace_method_setup (self->method, self->format, self->width,
2322       self->height);
2323
2324   GST_DEBUG_OBJECT (pad, "Sink caps: %" GST_PTR_FORMAT, caps);
2325   GST_DEBUG_OBJECT (pad, "Src  caps: %" GST_PTR_FORMAT, srccaps);
2326
2327   gst_caps_unref (srccaps);
2328
2329 done:
2330
2331   gst_object_unref (self);
2332   return res;
2333
2334 invalid_caps:
2335   res = FALSE;
2336   GST_ERROR_OBJECT (pad, "Invalid caps: %" GST_PTR_FORMAT, caps);
2337   goto done;
2338
2339 caps_not_accepted:
2340   res = FALSE;
2341   GST_ERROR_OBJECT (pad, "Caps not accepted: %" GST_PTR_FORMAT, srccaps);
2342   gst_caps_unref (srccaps);
2343   goto done;
2344 }
2345
2346 static gboolean
2347 gst_deinterlace_sink_event (GstPad * pad, GstEvent * event)
2348 {
2349   gboolean res = TRUE;
2350   GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad));
2351
2352   GST_LOG_OBJECT (pad, "received %s event: %" GST_PTR_FORMAT,
2353       GST_EVENT_TYPE_NAME (event), event);
2354
2355   switch (GST_EVENT_TYPE (event)) {
2356     case GST_EVENT_NEWSEGMENT:
2357     {
2358       GstFormat fmt;
2359       gboolean is_update;
2360       gint64 start, end, base;
2361       gdouble rate, applied_rate;
2362
2363       gst_event_parse_new_segment_full (event, &is_update, &rate,
2364           &applied_rate, &fmt, &start, &end, &base);
2365
2366       gst_deinterlace_reset_qos (self);
2367       gst_deinterlace_reset_history (self, FALSE);
2368
2369       if (fmt == GST_FORMAT_TIME) {
2370         GST_DEBUG_OBJECT (pad,
2371             "Got NEWSEGMENT event in GST_FORMAT_TIME, passing on (%"
2372             GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")", GST_TIME_ARGS (start),
2373             GST_TIME_ARGS (end));
2374         gst_segment_set_newsegment_full (&self->segment, is_update, rate,
2375             applied_rate, fmt, start, end, base);
2376       } else {
2377         gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
2378       }
2379
2380       res = gst_pad_push_event (self->srcpad, event);
2381       break;
2382     }
2383     case GST_EVENT_CUSTOM_DOWNSTREAM:{
2384       gboolean still_state;
2385
2386       if (gst_video_event_parse_still_frame (event, &still_state)) {
2387         GST_DEBUG_OBJECT (self, "Received still frame event, state %d",
2388             still_state);
2389
2390         if (still_state) {
2391           GstFlowReturn ret;
2392
2393           GST_DEBUG_OBJECT (self, "Handling still frame");
2394           self->still_frame_mode = TRUE;
2395           gst_deinterlace_reset_history (self, FALSE);
2396           if (self->last_buffer) {
2397             ret =
2398                 gst_pad_push (self->srcpad, gst_buffer_ref (self->last_buffer));
2399             GST_DEBUG_OBJECT (self, "Pushed still frame, result: %s",
2400                 gst_flow_get_name (ret));
2401           } else {
2402             GST_WARNING_OBJECT (self, "No pending buffer!");
2403           }
2404         } else {
2405           GST_DEBUG_OBJECT (self, "Ending still frames");
2406           self->still_frame_mode = FALSE;
2407         }
2408       }
2409     }
2410       /* fall through */
2411     case GST_EVENT_EOS:
2412       self->have_eos = TRUE;
2413       gst_deinterlace_reset_history (self, FALSE);
2414
2415       /* fall through */
2416     default:
2417       res = gst_pad_push_event (self->srcpad, event);
2418       break;
2419
2420     case GST_EVENT_FLUSH_STOP:
2421       if (self->still_frame_mode) {
2422         GST_DEBUG_OBJECT (self, "Ending still frames");
2423         self->still_frame_mode = FALSE;
2424       }
2425       gst_deinterlace_reset_qos (self);
2426       res = gst_pad_push_event (self->srcpad, event);
2427       gst_deinterlace_reset_history (self, TRUE);
2428       break;
2429   }
2430
2431   gst_object_unref (self);
2432   return res;
2433 }
2434
2435 static gboolean
2436 gst_deinterlace_sink_query (GstPad * pad, GstQuery * query)
2437 {
2438   GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad));
2439   gboolean res = FALSE;
2440
2441   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
2442
2443   switch (GST_QUERY_TYPE (query)) {
2444     default:{
2445       GstPad *peer = gst_pad_get_peer (self->srcpad);
2446
2447       if (peer) {
2448         res = gst_pad_query (peer, query);
2449         gst_object_unref (peer);
2450       } else {
2451         res = FALSE;
2452       }
2453       break;
2454     }
2455   }
2456
2457   gst_object_unref (self);
2458   return res;
2459 }
2460
2461 static GstStateChangeReturn
2462 gst_deinterlace_change_state (GstElement * element, GstStateChange transition)
2463 {
2464   GstStateChangeReturn ret;
2465   GstDeinterlace *self = GST_DEINTERLACE (element);
2466
2467   switch (transition) {
2468     case GST_STATE_CHANGE_NULL_TO_READY:
2469       break;
2470     case GST_STATE_CHANGE_READY_TO_PAUSED:
2471       break;
2472     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2473       break;
2474     default:
2475       break;
2476   }
2477
2478   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2479   if (ret != GST_STATE_CHANGE_SUCCESS)
2480     return ret;
2481
2482   switch (transition) {
2483     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2484       break;
2485     case GST_STATE_CHANGE_PAUSED_TO_READY:
2486       gst_deinterlace_reset (self);
2487       break;
2488     case GST_STATE_CHANGE_READY_TO_NULL:
2489     default:
2490       break;
2491   }
2492
2493   return ret;
2494 }
2495
2496 static gboolean
2497 gst_deinterlace_src_event (GstPad * pad, GstEvent * event)
2498 {
2499   GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad));
2500   gboolean res;
2501
2502   GST_DEBUG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
2503
2504   switch (GST_EVENT_TYPE (event)) {
2505     case GST_EVENT_QOS:{
2506       GstClockTimeDiff diff;
2507       GstClockTime timestamp;
2508       gdouble proportion;
2509
2510       gst_event_parse_qos (event, &proportion, &diff, &timestamp);
2511
2512       gst_deinterlace_update_qos (self, proportion, diff, timestamp);
2513     }
2514       /* fall through */
2515     default:
2516       res = gst_pad_push_event (self->sinkpad, event);
2517       break;
2518   }
2519
2520   gst_object_unref (self);
2521
2522   return res;
2523 }
2524
2525 static gboolean
2526 gst_deinterlace_src_query (GstPad * pad, GstQuery * query)
2527 {
2528   GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad));
2529   gboolean res = FALSE;
2530
2531   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
2532
2533   switch (GST_QUERY_TYPE (query)) {
2534     case GST_QUERY_LATENCY:
2535       if (!self->passthrough) {
2536         GstClockTime min, max;
2537         gboolean live;
2538         GstPad *peer;
2539
2540         if ((peer = gst_pad_get_peer (self->sinkpad))) {
2541           if ((res = gst_pad_query (peer, query))) {
2542             GstClockTime latency;
2543             gint fields_required = 0;
2544             gint method_latency = 0;
2545
2546             if (self->method) {
2547               fields_required =
2548                   gst_deinterlace_method_get_fields_required (self->method);
2549               method_latency =
2550                   gst_deinterlace_method_get_latency (self->method);
2551             }
2552
2553             gst_query_parse_latency (query, &live, &min, &max);
2554
2555             GST_DEBUG_OBJECT (self, "Peer latency: min %"
2556                 GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
2557                 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
2558
2559             /* add our own latency */
2560             latency = (fields_required + method_latency) * self->field_duration;
2561
2562             GST_DEBUG_OBJECT (self, "Our latency: min %" GST_TIME_FORMAT
2563                 ", max %" GST_TIME_FORMAT,
2564                 GST_TIME_ARGS (latency), GST_TIME_ARGS (latency));
2565
2566             min += latency;
2567             if (max != GST_CLOCK_TIME_NONE)
2568               max += latency;
2569
2570             GST_DEBUG_OBJECT (self, "Calculated total latency : min %"
2571                 GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
2572                 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
2573
2574             gst_query_set_latency (query, live, min, max);
2575           }
2576           gst_object_unref (peer);
2577         } else {
2578           res = FALSE;
2579         }
2580         break;
2581       }
2582     default:{
2583       GstPad *peer = gst_pad_get_peer (self->sinkpad);
2584
2585       if (peer) {
2586         res = gst_pad_query (peer, query);
2587         gst_object_unref (peer);
2588       } else {
2589         res = FALSE;
2590       }
2591       break;
2592     }
2593   }
2594
2595   gst_object_unref (self);
2596   return res;
2597 }
2598
2599 static const GstQueryType *
2600 gst_deinterlace_src_query_types (GstPad * pad)
2601 {
2602   static const GstQueryType types[] = {
2603     GST_QUERY_LATENCY,
2604     GST_QUERY_NONE
2605   };
2606   return types;
2607 }
2608
2609 static GstFlowReturn
2610 gst_deinterlace_alloc_buffer (GstPad * pad, guint64 offset, guint size,
2611     GstCaps * caps, GstBuffer ** buf)
2612 {
2613   GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad));
2614   GstFlowReturn ret = GST_FLOW_OK;
2615
2616   *buf = NULL;
2617
2618   GST_DEBUG_OBJECT (pad, "alloc with caps %" GST_PTR_FORMAT ", size %u", caps,
2619       size);
2620
2621   if (self->still_frame_mode || self->passthrough) {
2622     ret = gst_pad_alloc_buffer (self->srcpad, offset, size, caps, buf);
2623   } else if (G_LIKELY (!self->request_caps)) {
2624     *buf = gst_buffer_try_new_and_alloc (size);
2625     if (G_UNLIKELY (!*buf)) {
2626       ret = GST_FLOW_ERROR;
2627     } else {
2628       gst_buffer_set_caps (*buf, caps);
2629       GST_BUFFER_OFFSET (*buf) = offset;
2630     }
2631   } else {
2632     gint width, height;
2633     GstVideoFormat fmt;
2634     guint new_frame_size;
2635     GstCaps *new_caps = gst_caps_copy (self->request_caps);
2636
2637     if (self->fields == GST_DEINTERLACE_ALL) {
2638       gint n, d;
2639       GstStructure *s = gst_caps_get_structure (new_caps, 0);
2640
2641       gst_structure_get_fraction (s, "framerate", &n, &d);
2642
2643       if (!gst_fraction_double (&n, &d, TRUE)) {
2644         gst_object_unref (self);
2645         gst_caps_unref (new_caps);
2646         return GST_FLOW_OK;
2647       }
2648
2649       gst_structure_set (s, "framerate", GST_TYPE_FRACTION, n, d, NULL);
2650     }
2651
2652     if (G_UNLIKELY (!gst_video_format_parse_caps (new_caps, &fmt, &width,
2653                 &height))) {
2654       gst_object_unref (self);
2655       gst_caps_unref (new_caps);
2656       return GST_FLOW_OK;
2657     }
2658
2659     new_frame_size = gst_video_format_get_size (fmt, width, height);
2660
2661     *buf = gst_buffer_try_new_and_alloc (new_frame_size);
2662     if (G_UNLIKELY (!*buf)) {
2663       ret = GST_FLOW_ERROR;
2664     } else {
2665       gst_buffer_set_caps (*buf, new_caps);
2666       gst_caps_unref (self->request_caps);
2667       self->request_caps = NULL;
2668       gst_caps_unref (new_caps);
2669     }
2670   }
2671
2672   gst_object_unref (self);
2673
2674   return ret;
2675 }
2676
2677 static gboolean
2678 plugin_init (GstPlugin * plugin)
2679 {
2680   GST_DEBUG_CATEGORY_INIT (deinterlace_debug, "deinterlace", 0, "Deinterlacer");
2681
2682 #if HAVE_ORC
2683   orc_init ();
2684 #endif
2685
2686   if (!gst_element_register (plugin, "deinterlace", GST_RANK_NONE,
2687           GST_TYPE_DEINTERLACE)) {
2688     return FALSE;
2689   }
2690
2691   return TRUE;
2692 }
2693
2694 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2695     GST_VERSION_MINOR,
2696     deinterlace,
2697     "Deinterlacer", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
2698     GST_PACKAGE_ORIGIN);