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