v4l2videodec: Increase v4l2videodecoder rank
[platform/upstream/gst-plugins-good.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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, 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-1.0 -v filesrc location=/path/to/file ! decodebin ! videoconvert ! deinterlace ! videoconvert ! 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 };
74
75 #define GST_DEINTERLACE_BUFFER_STATE_P    (1<<0)
76 #define GST_DEINTERLACE_BUFFER_STATE_I    (1<<1)
77 #define GST_DEINTERLACE_BUFFER_STATE_TC_B (1<<2)
78 #define GST_DEINTERLACE_BUFFER_STATE_TC_T (1<<3)
79 #define GST_DEINTERLACE_BUFFER_STATE_TC_P (1<<4)
80 #define GST_DEINTERLACE_BUFFER_STATE_TC_M (1<<5)
81 #define GST_DEINTERLACE_BUFFER_STATE_RFF  (1<<6)
82
83 #define GST_ONE \
84   (GST_DEINTERLACE_BUFFER_STATE_TC_T | GST_DEINTERLACE_BUFFER_STATE_TC_B)
85 #define GST_PRG \
86   (GST_DEINTERLACE_BUFFER_STATE_P | GST_DEINTERLACE_BUFFER_STATE_TC_P)
87 #define GST_INT \
88   (GST_DEINTERLACE_BUFFER_STATE_I | GST_DEINTERLACE_BUFFER_STATE_TC_M)
89 #define GST_RFF (GST_DEINTERLACE_BUFFER_STATE_RFF)
90
91 #define GST_DEINTERLACE_OBSCURE_THRESHOLD 5
92
93 static const TelecinePattern telecine_patterns[] = {
94   /* 60i -> 60p or 50i -> 50p (NOTE THE WEIRD RATIOS) */
95   {"1:1", 1, 2, 1, {GST_ONE,}},
96   /* 60i -> 30p or 50i -> 25p */
97   {"2:2", 1, 1, 1, {GST_INT,}},
98   /* 60i telecine -> 24p */
99   {"2:3-RFF", 4, 4, 5, {GST_PRG, GST_RFF, GST_PRG, GST_RFF,}},
100   {"2:3", 5, 4, 5, {GST_PRG, GST_PRG, GST_ONE, GST_ONE, GST_PRG,}},
101   {"3:2:2:3-RFF", 4, 4, 5, {GST_RFF, GST_PRG, GST_PRG, GST_RFF,}},
102   {"3:2:2:3", 5, 4, 5, {GST_PRG, GST_ONE, GST_INT, GST_ONE, GST_PRG,}},
103   /* fieldanalysis should indicate this using RFF on the second and fourth
104    * buffers and not send the third buffer at all. it will be identified as
105    * 3:2:2:3-RFF */
106   /* {"2:3:3:2", 5, 4, 5, {GST_PRG, GST_PRG, GST_DRP, GST_PRG, GST_PRG,}}, */
107
108   /* The following patterns are obscure and are ignored if ignore-obscure is
109    * set to true. If any patterns are added above this line, check and edit
110    * GST_DEINTERLACE_OBSCURE_THRESHOLD */
111
112   /* 50i Euro pulldown -> 24p */
113   {"2-11:3", 25, 24, 25, {GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_PRG,
114               GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_PRG,
115               GST_PRG, GST_PRG, GST_ONE, GST_INT, GST_INT,
116               GST_INT, GST_INT, GST_INT, GST_INT, GST_INT,
117           GST_INT, GST_INT, GST_INT, GST_ONE, GST_PRG,}},
118 #if 0
119   /* haven't figured out how fieldanalysis should handle these yet */
120   /* 60i (NTSC 30000/1001) -> 16p (16000/1001) */
121   {"3:4-3", 15, 8, 15, {GST_PRG, GST_DRP, GST_PRG, GST_DRP, GST_PRG,
122               GST_DRP, GST_PRG, GST_DRP, GST_PRG, GST_DRP,
123           GST_PRG, GST_DRP, GST_PRG, GST_DRP, GST_PRG,}},
124   /* 50i (PAL) -> 16p */
125   {"3-7:4", 25, 16, 25, {GST_PRG, GST_DRP, GST_PRG, GST_PRG, GST_DRP,
126               GST_PRG, GST_PRG, GST_DRP, GST_PRG, GST_PRG,
127               GST_DRP, GST_PRG, GST_DRP, GST_PRG, GST_PRG,
128               GST_DRP, GST_PRG, GST_PRG, GST_DRP, GST_PRG,
129           GST_PRG, GST_DRP, GST_PRG, GST_PRG, GST_DRP,}},
130   /* NTSC 60i -> 18p */
131   {"3:3:4", 5, 3, 5, {GST_PRG, GST_DRP, GST_PRG, GST_DRP, GST_PRG,}},
132   /* NTSC 60i -> 20p */
133   {"3:3", 3, 2, 3, {GST_PRG, GST_DRP, GST_PRG,}},
134 #endif
135   /* NTSC 60i -> 27.5 */
136   {"3:2-4", 11, 10, 11, {GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_PRG,
137               GST_PRG, GST_ONE, GST_INT, GST_INT, GST_INT,
138           GST_ONE,}},
139   /* PAL 50i -> 27.5 */
140   {"1:2-4", 9, 9, 10, {GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_INT,
141           GST_INT, GST_INT, GST_INT, GST_INT,}},
142 };
143
144 static const GEnumValue methods_types[] = {
145   {GST_DEINTERLACE_TOMSMOCOMP, "Motion Adaptive: Motion Search",
146       "tomsmocomp"},
147   {GST_DEINTERLACE_GREEDY_H, "Motion Adaptive: Advanced Detection",
148       "greedyh"},
149   {GST_DEINTERLACE_GREEDY_L, "Motion Adaptive: Simple Detection", "greedyl"},
150   {GST_DEINTERLACE_VFIR, "Blur Vertical", "vfir"},
151   {GST_DEINTERLACE_LINEAR, "Linear", "linear"},
152   {GST_DEINTERLACE_LINEAR_BLEND, "Blur: Temporal (Do Not Use)",
153       "linearblend"},
154   {GST_DEINTERLACE_SCALER_BOB, "Double lines", "scalerbob"},
155   {GST_DEINTERLACE_WEAVE, "Weave (Do Not Use)", "weave"},
156   {GST_DEINTERLACE_WEAVE_TFF, "Progressive: Top Field First (Do Not Use)",
157       "weavetff"},
158   {GST_DEINTERLACE_WEAVE_BFF, "Progressive: Bottom Field First (Do Not Use)",
159       "weavebff"},
160   {0, NULL, NULL},
161 };
162
163 static const GEnumValue locking_types[] = {
164   {GST_DEINTERLACE_LOCKING_NONE,
165       "No pattern locking", "none"},
166   {GST_DEINTERLACE_LOCKING_AUTO,
167         "Choose passive/active locking depending on whether upstream is live",
168       "auto"},
169   {GST_DEINTERLACE_LOCKING_ACTIVE,
170         "Block until pattern-locked. Use accurate timestamp interpolation within a pattern repeat.",
171       "active"},
172   {GST_DEINTERLACE_LOCKING_PASSIVE,
173         "Do not block. Use naïve timestamp adjustment until pattern-locked based on state history.",
174       "passive"},
175   {0, NULL, NULL},
176 };
177
178
179 #define GST_TYPE_DEINTERLACE_METHODS (gst_deinterlace_methods_get_type ())
180 static GType
181 gst_deinterlace_methods_get_type (void)
182 {
183   static GType deinterlace_methods_type = 0;
184
185   if (!deinterlace_methods_type) {
186     deinterlace_methods_type =
187         g_enum_register_static ("GstDeinterlaceMethods", methods_types);
188   }
189   return deinterlace_methods_type;
190 }
191
192 #define GST_TYPE_DEINTERLACE_FIELDS (gst_deinterlace_fields_get_type ())
193 static GType
194 gst_deinterlace_fields_get_type (void)
195 {
196   static GType deinterlace_fields_type = 0;
197
198   static const GEnumValue fields_types[] = {
199     {GST_DEINTERLACE_ALL, "All fields", "all"},
200     {GST_DEINTERLACE_TF, "Top fields only", "top"},
201     {GST_DEINTERLACE_BF, "Bottom fields only", "bottom"},
202     {GST_DEINTERLACE_FIELDS_AUTO, "Automatically detect", "auto"},
203     {0, NULL, NULL},
204   };
205
206   if (!deinterlace_fields_type) {
207     deinterlace_fields_type =
208         g_enum_register_static ("GstDeinterlaceFields", fields_types);
209   }
210   return deinterlace_fields_type;
211 }
212
213 #define GST_TYPE_DEINTERLACE_FIELD_LAYOUT (gst_deinterlace_field_layout_get_type ())
214 static GType
215 gst_deinterlace_field_layout_get_type (void)
216 {
217   static GType deinterlace_field_layout_type = 0;
218
219   static const GEnumValue field_layout_types[] = {
220     {GST_DEINTERLACE_LAYOUT_AUTO, "Auto detection", "auto"},
221     {GST_DEINTERLACE_LAYOUT_TFF, "Top field first", "tff"},
222     {GST_DEINTERLACE_LAYOUT_BFF, "Bottom field first", "bff"},
223     {0, NULL, NULL},
224   };
225
226   if (!deinterlace_field_layout_type) {
227     deinterlace_field_layout_type =
228         g_enum_register_static ("GstDeinterlaceFieldLayout",
229         field_layout_types);
230   }
231   return deinterlace_field_layout_type;
232 }
233
234 #define GST_TYPE_DEINTERLACE_MODES (gst_deinterlace_modes_get_type ())
235 static GType
236 gst_deinterlace_modes_get_type (void)
237 {
238   static GType deinterlace_modes_type = 0;
239
240   static const GEnumValue modes_types[] = {
241     {GST_DEINTERLACE_MODE_AUTO, "Auto detection (best effort)", "auto"},
242     {GST_DEINTERLACE_MODE_INTERLACED, "Force deinterlacing", "interlaced"},
243     {GST_DEINTERLACE_MODE_DISABLED, "Run in passthrough mode", "disabled"},
244     {GST_DEINTERLACE_MODE_AUTO_STRICT, "Auto detection (strict)",
245         "auto-strict"},
246     {0, NULL, NULL},
247   };
248
249   if (!deinterlace_modes_type) {
250     deinterlace_modes_type =
251         g_enum_register_static ("GstDeinterlaceModes", modes_types);
252   }
253   return deinterlace_modes_type;
254 }
255
256 #define GST_TYPE_DEINTERLACE_LOCKING (gst_deinterlace_locking_get_type ())
257 static GType
258 gst_deinterlace_locking_get_type (void)
259 {
260   static GType deinterlace_locking_type = 0;
261
262   if (!deinterlace_locking_type) {
263     deinterlace_locking_type =
264         g_enum_register_static ("GstDeinterlaceLocking", locking_types);
265   }
266
267   return deinterlace_locking_type;
268 }
269
270 #define DEINTERLACE_VIDEO_FORMATS \
271     "{ AYUV, ARGB, ABGR, RGBA, BGRA, Y444, xRGB, xBGR, RGBx, BGRx, RGB, " \
272     "BGR, YUY2, YVYU, UYVY, Y42B, I420, YV12, Y41B, NV12, NV21 }"
273
274 #define DEINTERLACE_CAPS GST_VIDEO_CAPS_MAKE(DEINTERLACE_VIDEO_FORMATS)
275
276 #define DEINTERLACE_ALL_CAPS DEINTERLACE_CAPS ";" \
277     GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("ANY", GST_VIDEO_FORMATS_ALL)
278
279 static GstStaticCaps progressive_caps =
280 GST_STATIC_CAPS ("video/x-raw(ANY),interlace-mode=(string)progressive");
281 static GstStaticCaps deinterlace_caps = GST_STATIC_CAPS (DEINTERLACE_CAPS);
282
283 static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
284     GST_PAD_SRC,
285     GST_PAD_ALWAYS,
286     GST_STATIC_CAPS (DEINTERLACE_ALL_CAPS)
287     );
288
289 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
290     GST_PAD_SINK,
291     GST_PAD_ALWAYS,
292     GST_STATIC_CAPS (DEINTERLACE_ALL_CAPS)
293     );
294
295 static void gst_deinterlace_finalize (GObject * self);
296 static void gst_deinterlace_set_property (GObject * self, guint prop_id,
297     const GValue * value, GParamSpec * pspec);
298 static void gst_deinterlace_get_property (GObject * self, guint prop_id,
299     GValue * value, GParamSpec * pspec);
300
301 static GstCaps *gst_deinterlace_getcaps (GstDeinterlace * self, GstPad * pad,
302     GstCaps * filter);
303 static gboolean gst_deinterlace_setcaps (GstDeinterlace * self, GstPad * pad,
304     GstCaps * caps);
305 static gboolean gst_deinterlace_sink_event (GstPad * pad, GstObject * parent,
306     GstEvent * event);
307 static gboolean gst_deinterlace_sink_query (GstPad * pad, GstObject * parent,
308     GstQuery * query);
309 static GstFlowReturn gst_deinterlace_chain (GstPad * pad, GstObject * parent,
310     GstBuffer * buffer);
311 static GstStateChangeReturn gst_deinterlace_change_state (GstElement * element,
312     GstStateChange transition);
313 static gboolean gst_deinterlace_set_allocation (GstDeinterlace * self,
314     GstBufferPool * pool, GstAllocator * allocator,
315     GstAllocationParams * params);
316
317 static gboolean gst_deinterlace_src_event (GstPad * pad, GstObject * parent,
318     GstEvent * event);
319 static gboolean gst_deinterlace_src_query (GstPad * pad, GstObject * parent,
320     GstQuery * query);
321
322 static GstFlowReturn gst_deinterlace_output_frame (GstDeinterlace * self,
323     gboolean flushing);
324 static void gst_deinterlace_reset (GstDeinterlace * self);
325 static void gst_deinterlace_update_qos (GstDeinterlace * self,
326     gdouble proportion, GstClockTimeDiff diff, GstClockTime time);
327 static void gst_deinterlace_reset_qos (GstDeinterlace * self);
328 static void gst_deinterlace_read_qos (GstDeinterlace * self,
329     gdouble * proportion, GstClockTime * time);
330
331 #define IS_TELECINE(m) ((m) == GST_VIDEO_INTERLACE_MODE_MIXED && self->pattern > 1)
332
333 /* FIXME: what's the point of the childproxy interface here? What can you
334  * actually do with it? The method objects seem to have no properties */
335 #if 0
336 static void gst_deinterlace_child_proxy_interface_init (gpointer g_iface,
337     gpointer iface_data);
338
339 static void
340 _do_init (GType object_type)
341 {
342   const GInterfaceInfo child_proxy_interface_info = {
343     (GInterfaceInitFunc) gst_deinterlace_child_proxy_interface_init,
344     NULL,                       /* interface_finalize */
345     NULL                        /* interface_data */
346   };
347
348   g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
349       &child_proxy_interface_info);
350 }
351 #endif
352
353 G_DEFINE_TYPE (GstDeinterlace, gst_deinterlace, GST_TYPE_ELEMENT);
354
355 #define parent_class gst_deinterlace_parent_class
356
357 static const struct
358 {
359   GType (*get_type) (void);
360 } _method_types[] = {
361   {
362   gst_deinterlace_method_tomsmocomp_get_type}, {
363   gst_deinterlace_method_greedy_h_get_type}, {
364   gst_deinterlace_method_greedy_l_get_type}, {
365   gst_deinterlace_method_vfir_get_type}, {
366   gst_deinterlace_method_linear_get_type}, {
367   gst_deinterlace_method_linear_blend_get_type}, {
368   gst_deinterlace_method_scaler_bob_get_type}, {
369   gst_deinterlace_method_weave_get_type}, {
370   gst_deinterlace_method_weave_tff_get_type}, {
371   gst_deinterlace_method_weave_bff_get_type}
372 };
373
374 static void
375 gst_deinterlace_set_method (GstDeinterlace * self, GstDeinterlaceMethods method)
376 {
377   GType method_type;
378   gint width, height;
379   GstVideoFormat format;
380
381   GST_DEBUG_OBJECT (self, "Setting new method %d", method);
382
383   width = GST_VIDEO_INFO_WIDTH (&self->vinfo);
384   height = GST_VIDEO_INFO_HEIGHT (&self->vinfo);
385   format = GST_VIDEO_INFO_FORMAT (&self->vinfo);
386
387   if (self->method) {
388     if (self->method_id == method &&
389         gst_deinterlace_method_supported (G_TYPE_FROM_INSTANCE (self->method),
390             format, width, height)) {
391       GST_DEBUG_OBJECT (self, "Reusing current method");
392       return;
393     }
394 #if 0
395     gst_child_proxy_child_removed (GST_OBJECT (self),
396         GST_OBJECT (self->method));
397     gst_object_unparent (GST_OBJECT (self->method));
398     self->method = NULL;
399 #endif
400   }
401
402   method_type =
403       _method_types[method].get_type !=
404       NULL ? _method_types[method].get_type () : G_TYPE_INVALID;
405   if (method_type == G_TYPE_INVALID
406       || !gst_deinterlace_method_supported (method_type, format,
407           width, height)) {
408     GType tmp;
409     gint i;
410
411     method_type = G_TYPE_INVALID;
412
413     GST_WARNING_OBJECT (self, "Method doesn't support requested format");
414     for (i = 0; i < G_N_ELEMENTS (_method_types); i++) {
415       if (_method_types[i].get_type == NULL)
416         continue;
417       tmp = _method_types[i].get_type ();
418       if (gst_deinterlace_method_supported (tmp, format, width, height)) {
419         GST_DEBUG_OBJECT (self, "Using method %d", i);
420         method_type = tmp;
421         method = i;
422         break;
423       }
424     }
425     /* If we get here we must have invalid caps! */
426     g_assert (method_type != G_TYPE_INVALID);
427   }
428
429   self->method = g_object_new (method_type, "name", "method", NULL);
430   self->method_id = method;
431
432   gst_object_set_parent (GST_OBJECT (self->method), GST_OBJECT (self));
433 #if 0
434   gst_child_proxy_child_added (GST_OBJECT (self), GST_OBJECT (self->method));
435 #endif
436
437   if (self->method)
438     gst_deinterlace_method_setup (self->method, &self->vinfo);
439 }
440
441 static gboolean
442 gst_deinterlace_clip_buffer (GstDeinterlace * self, GstBuffer * buffer)
443 {
444   gboolean ret = TRUE;
445   GstClockTime start, stop;
446   guint64 cstart, cstop;
447
448   GST_DEBUG_OBJECT (self,
449       "Clipping buffer to the current segment: %" GST_TIME_FORMAT " -- %"
450       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
451       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
452   GST_DEBUG_OBJECT (self, "Current segment: %" GST_SEGMENT_FORMAT,
453       &self->segment);
454
455   if (G_UNLIKELY (self->segment.format != GST_FORMAT_TIME))
456     goto beach;
457   if (G_UNLIKELY (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)))
458     goto beach;
459
460   start = GST_BUFFER_TIMESTAMP (buffer);
461   stop = start + GST_BUFFER_DURATION (buffer);
462
463   if (!(ret = gst_segment_clip (&self->segment, GST_FORMAT_TIME,
464               start, stop, &cstart, &cstop)))
465     goto beach;
466
467   GST_BUFFER_TIMESTAMP (buffer) = cstart;
468   if (GST_CLOCK_TIME_IS_VALID (cstop))
469     GST_BUFFER_DURATION (buffer) = cstop - cstart;
470
471 beach:
472   if (ret)
473     GST_DEBUG_OBJECT (self,
474         "Clipped buffer to the current segment: %" GST_TIME_FORMAT " -- %"
475         GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
476         GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
477   else
478     GST_DEBUG_OBJECT (self, "Buffer outside the current segment -- dropping");
479
480   return ret;
481 }
482
483 static void
484 gst_deinterlace_class_init (GstDeinterlaceClass * klass)
485 {
486   GObjectClass *gobject_class = (GObjectClass *) klass;
487
488   GstElementClass *element_class = (GstElementClass *) klass;
489
490   gst_element_class_add_static_pad_template (element_class, &src_templ);
491   gst_element_class_add_static_pad_template (element_class, &sink_templ);
492
493   gst_element_class_set_static_metadata (element_class,
494       "Deinterlacer",
495       "Filter/Effect/Video/Deinterlace",
496       "Deinterlace Methods ported from DScaler/TvTime",
497       "Martin Eikermann <meiker@upb.de>, "
498       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
499
500   gobject_class->set_property = gst_deinterlace_set_property;
501   gobject_class->get_property = gst_deinterlace_get_property;
502   gobject_class->finalize = gst_deinterlace_finalize;
503
504   /**
505    * GstDeinterlace:mode:
506    *
507    * This selects whether the deinterlacing methods should
508    * always be applied or if they should only be applied
509    * on content that has the "interlaced" flag on the caps.
510    */
511   g_object_class_install_property (gobject_class, PROP_MODE,
512       g_param_spec_enum ("mode",
513           "Mode",
514           "Deinterlace Mode",
515           GST_TYPE_DEINTERLACE_MODES,
516           DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
517       );
518
519   /**
520    * GstDeinterlace:method:
521    *
522    * Selects the different deinterlacing algorithms that can be used.
523    * These provide different quality and CPU usage.
524    *
525    * Some methods provide parameters which can be set by getting
526    * the "method" child via the #GstChildProxy interface and
527    * setting the appropiate properties on it.
528    *
529    * <itemizedlist>
530    * <listitem>
531    * <para>
532    * tomsmocomp
533    * Motion Adaptive: Motion Search
534    * </para>
535    * </listitem>
536    * <listitem>
537    * <para>
538    * greedyh
539    * Motion Adaptive: Advanced Detection
540    * </para>
541    * </listitem>
542    * <listitem>
543    * <para>
544    * greedyl
545    * Motion Adaptive: Simple Detection
546    * </para>
547    * </listitem>
548    * <listitem>
549    * <para>
550    * vfir
551    * Blur vertical
552    * </para>
553    * </listitem>
554    * <listitem>
555    * <para>
556    * linear
557    * Linear interpolation
558    * </para>
559    * </listitem>
560    * <listitem>
561    * <para>
562    * linearblend
563    * Linear interpolation in time domain.  Any motion causes significant
564    * ghosting, so this method should not be used.
565    * </para>
566    * </listitem>
567    * <listitem>
568    * <para>
569    * scalerbob
570    * Double lines
571    * </para>
572    * </listitem>
573    * <listitem>
574    * <para>
575    * weave
576    * Weave.  Bad quality, do not use.
577    * </para>
578    * </listitem>
579    * <listitem>
580    * <para>
581    * weavetff
582    * Progressive: Top Field First.  Bad quality, do not use.
583    * </para>
584    * </listitem>
585    * <listitem>
586    * <para>
587    * weavebff
588    * Progressive: Bottom Field First.  Bad quality, do not use.
589    * </para>
590    * </listitem>
591    * </itemizedlist>
592    */
593   g_object_class_install_property (gobject_class, PROP_METHOD,
594       g_param_spec_enum ("method",
595           "Method",
596           "Deinterlace Method",
597           GST_TYPE_DEINTERLACE_METHODS,
598           DEFAULT_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
599       );
600
601   /**
602    * GstDeinterlace:fields:
603    *
604    * This selects which fields should be output. If "all" is selected
605    * the output framerate will be double.
606    */
607   g_object_class_install_property (gobject_class, PROP_FIELDS,
608       g_param_spec_enum ("fields",
609           "fields",
610           "Fields to use for deinterlacing",
611           GST_TYPE_DEINTERLACE_FIELDS,
612           DEFAULT_FIELDS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
613       );
614
615   /**
616    * GstDeinterlace:layout:
617    *
618    * This selects which fields is the first in time.
619    *
620    */
621   g_object_class_install_property (gobject_class, PROP_FIELD_LAYOUT,
622       g_param_spec_enum ("tff",
623           "tff",
624           "Deinterlace top field first",
625           GST_TYPE_DEINTERLACE_FIELD_LAYOUT,
626           DEFAULT_FIELD_LAYOUT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
627       );
628
629   /**
630    * GstDeinterlace:locking:
631    *
632    * This selects which approach to pattern locking is used which affects
633    * processing latency and accuracy of timestamp adjustment for telecine
634    * streams.
635    */
636   g_object_class_install_property (gobject_class, PROP_LOCKING,
637       g_param_spec_enum ("locking", "locking", "Pattern locking mode",
638           GST_TYPE_DEINTERLACE_LOCKING, DEFAULT_LOCKING,
639           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
640
641   /**
642    * GstDeinterlace:ignore-obscure:
643    *
644    * This selects whether to ignore obscure/rare telecine patterns.
645    * NTSC 2:3 pulldown variants are the only really common patterns.
646    */
647   g_object_class_install_property (gobject_class, PROP_IGNORE_OBSCURE,
648       g_param_spec_boolean ("ignore-obscure", "ignore-obscure",
649           "Ignore obscure telecine patterns (only consider P, I and 2:3 "
650           "variants).", DEFAULT_IGNORE_OBSCURE,
651           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
652
653   /**
654    * GstDeinterlace:drop-orphans:
655    *
656    * This selects whether to drop orphan fields at the beginning of telecine
657    * patterns in active locking mode.
658    */
659   g_object_class_install_property (gobject_class, PROP_DROP_ORPHANS,
660       g_param_spec_boolean ("drop-orphans", "drop-orphans",
661           "Drop orphan fields at the beginning of telecine patterns in "
662           "active locking mode.", DEFAULT_DROP_ORPHANS,
663           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
664
665   element_class->change_state =
666       GST_DEBUG_FUNCPTR (gst_deinterlace_change_state);
667 }
668
669 #if 0
670 static GstObject *
671 gst_deinterlace_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
672     guint index)
673 {
674   GstDeinterlace *self = GST_DEINTERLACE (child_proxy);
675
676   g_return_val_if_fail (index == 0, NULL);
677
678   return gst_object_ref (self->method);
679 }
680
681 static guint
682 gst_deinterlace_child_proxy_get_children_count (GstChildProxy * child_proxy)
683 {
684   GstDeinterlace *self = GST_DEINTERLACE (child_proxy);
685
686   return ((self->method) ? 1 : 0);
687 }
688
689 static void
690 gst_deinterlace_child_proxy_interface_init (gpointer g_iface,
691     gpointer iface_data)
692 {
693   GstChildProxyInterface *iface = g_iface;
694
695   iface->get_child_by_index = gst_deinterlace_child_proxy_get_child_by_index;
696   iface->get_children_count = gst_deinterlace_child_proxy_get_children_count;
697 }
698 #endif
699
700 static void
701 gst_deinterlace_init (GstDeinterlace * self)
702 {
703   self->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
704   gst_pad_set_chain_function (self->sinkpad,
705       GST_DEBUG_FUNCPTR (gst_deinterlace_chain));
706   gst_pad_set_event_function (self->sinkpad,
707       GST_DEBUG_FUNCPTR (gst_deinterlace_sink_event));
708   gst_pad_set_query_function (self->sinkpad,
709       GST_DEBUG_FUNCPTR (gst_deinterlace_sink_query));
710   gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
711
712   self->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
713   gst_pad_set_event_function (self->srcpad,
714       GST_DEBUG_FUNCPTR (gst_deinterlace_src_event));
715   gst_pad_set_query_function (self->srcpad,
716       GST_DEBUG_FUNCPTR (gst_deinterlace_src_query));
717   gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
718
719   self->mode = DEFAULT_MODE;
720   self->user_set_method_id = DEFAULT_METHOD;
721   gst_video_info_init (&self->vinfo);
722   gst_deinterlace_set_method (self, self->user_set_method_id);
723   self->fields = DEFAULT_FIELDS;
724   self->user_set_fields = DEFAULT_FIELDS;
725   self->field_layout = DEFAULT_FIELD_LAYOUT;
726   self->locking = DEFAULT_LOCKING;
727   self->ignore_obscure = DEFAULT_IGNORE_OBSCURE;
728   self->drop_orphans = DEFAULT_DROP_ORPHANS;
729
730   self->low_latency = -1;
731   self->pattern = -1;
732   self->pattern_phase = -1;
733   self->pattern_count = 0;
734   self->output_count = 0;
735   self->pattern_base_ts = GST_CLOCK_TIME_NONE;
736   self->pattern_buf_dur = GST_CLOCK_TIME_NONE;
737   self->still_frame_mode = FALSE;
738   self->telecine_tc_warned = FALSE;
739
740   gst_deinterlace_reset (self);
741 }
742
743 static GstVideoFrame *
744 gst_video_frame_new_and_map (GstVideoInfo * vinfo, GstBuffer * buffer,
745     GstMapFlags flags)
746 {
747   GstVideoFrame *frame = g_malloc0 (sizeof (GstVideoFrame));
748   if (!gst_video_frame_map (frame, vinfo, buffer, flags)) {
749     g_free (frame);
750     g_return_val_if_reached (NULL);
751     return NULL;
752   }
753   return frame;
754 }
755
756 static void
757 gst_video_frame_unmap_and_free (GstVideoFrame * frame)
758 {
759   gst_video_frame_unmap (frame);
760   g_free (frame);
761 }
762
763 static GstVideoFrame *
764 gst_deinterlace_pop_history (GstDeinterlace * self)
765 {
766   GstVideoFrame *frame;
767
768   g_return_val_if_fail (self->history_count > 0, NULL);
769
770   GST_DEBUG_OBJECT (self, "Pop last history frame -- current history size %d",
771       self->history_count);
772
773   frame = self->field_history[self->history_count - 1].frame;
774
775   self->history_count--;
776   if (self->locking != GST_DEINTERLACE_LOCKING_NONE && (!self->history_count
777           || GST_VIDEO_FRAME_PLANE_DATA (frame, 0) !=
778           GST_VIDEO_FRAME_PLANE_DATA (self->field_history[self->history_count -
779                   1].frame, 0))) {
780     if (!self->low_latency)
781       self->state_count--;
782     if (self->pattern_lock) {
783       self->pattern_count++;
784       if (self->pattern != -1
785           && self->pattern_count >= telecine_patterns[self->pattern].length) {
786         self->pattern_count = 0;
787         self->output_count = 0;
788       }
789     }
790   }
791
792   GST_DEBUG_OBJECT (self, "Returning frame: %p %" GST_TIME_FORMAT
793       " with duration %" GST_TIME_FORMAT " and size %" G_GSIZE_FORMAT, frame,
794       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (frame->buffer)),
795       GST_TIME_ARGS (GST_BUFFER_DURATION (frame->buffer)),
796       GST_VIDEO_FRAME_SIZE (frame));
797
798   return frame;
799 }
800
801 static void
802 gst_deinterlace_delete_meta_at (GstDeinterlace * self, gint idx)
803 {
804   if (self->field_history[idx].frame) {
805     if (self->field_history[idx].tc) {
806       gst_video_time_code_free (self->field_history[idx].tc);
807       self->field_history[idx].tc = NULL;
808     }
809     if (self->field_history[idx].caption) {
810       g_free (self->field_history[idx].caption->data);
811       g_free (self->field_history[idx].caption);
812       self->field_history[idx].caption = NULL;
813     }
814   }
815 }
816
817 static void
818 gst_deinterlace_pop_and_clear (GstDeinterlace * self)
819 {
820   gint idx;
821
822   if (self->history_count <= 0)
823     return;
824
825   idx = self->history_count - 1;
826   gst_deinterlace_delete_meta_at (self, idx);
827
828   /* FIXME: pop_history should return a structure with the frame and its meta.
829    * Currently we're just doing guesswork with the indices. Maybe just
830    * refactor the history functionality to make something clearer */
831   gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
832 }
833
834 static void
835 gst_deinterlace_reset_history (GstDeinterlace * self, gboolean drop_all)
836 {
837   gint i;
838
839   if (!drop_all) {
840     GST_DEBUG_OBJECT (self, "Flushing history (count %d)", self->history_count);
841     while (self->history_count > 0) {
842       if (gst_deinterlace_output_frame (self, TRUE) != GST_FLOW_OK) {
843         /* Encountered error, or flushing -> skip and drop all remaining */
844         drop_all = TRUE;
845         break;
846       }
847     }
848   }
849   if (drop_all) {
850     GST_DEBUG_OBJECT (self, "Resetting history (count %d)",
851         self->history_count);
852
853     for (i = 0; i < self->history_count; i++) {
854       if (self->field_history[i].frame) {
855         gst_video_frame_unmap_and_free (self->field_history[i].frame);
856         self->field_history[i].frame = NULL;
857         gst_deinterlace_delete_meta_at (self, i);
858       }
859     }
860   }
861   memset (self->field_history, 0,
862       GST_DEINTERLACE_MAX_FIELD_HISTORY * sizeof (GstDeinterlaceField));
863   self->history_count = 0;
864   memset (self->buf_states, 0,
865       GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY *
866       sizeof (GstDeinterlaceBufferState));
867   self->state_count = 0;
868   self->pattern_lock = FALSE;
869   self->pattern_refresh = TRUE;
870   self->cur_field_idx = -1;
871
872   if (!self->still_frame_mode && self->last_buffer) {
873     gst_buffer_unref (self->last_buffer);
874     self->last_buffer = NULL;
875   }
876 }
877
878 static void
879 gst_deinterlace_reset (GstDeinterlace * self)
880 {
881   GST_DEBUG_OBJECT (self, "Resetting internal state");
882
883   gst_video_info_init (&self->vinfo);
884
885   self->passthrough = FALSE;
886
887   self->reconfigure = FALSE;
888   if ((gint) self->new_mode != -1)
889     self->mode = self->new_mode;
890   if ((gint) self->new_fields != -1)
891     self->user_set_fields = self->new_fields;
892   self->new_mode = -1;
893   self->new_fields = -1;
894
895   gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
896
897   if (self->request_caps)
898     gst_caps_unref (self->request_caps);
899   self->request_caps = NULL;
900
901   gst_deinterlace_reset_history (self, TRUE);
902
903   gst_deinterlace_reset_qos (self);
904
905   self->need_more = FALSE;
906   self->have_eos = FALSE;
907
908   self->discont = TRUE;
909   self->telecine_tc_warned = FALSE;
910
911   gst_deinterlace_set_allocation (self, NULL, NULL, NULL);
912 }
913
914 static void
915 gst_deinterlace_set_property (GObject * object, guint prop_id,
916     const GValue * value, GParamSpec * pspec)
917 {
918   GstDeinterlace *self;
919
920   self = GST_DEINTERLACE (object);
921
922   switch (prop_id) {
923     case PROP_MODE:{
924       gint new_mode;
925
926       GST_OBJECT_LOCK (self);
927       new_mode = g_value_get_enum (value);
928       if (self->mode != new_mode && gst_pad_has_current_caps (self->srcpad)) {
929         self->reconfigure = TRUE;
930         self->new_mode = new_mode;
931       } else {
932         self->mode = new_mode;
933       }
934       GST_OBJECT_UNLOCK (self);
935       break;
936     }
937     case PROP_METHOD:
938       self->user_set_method_id = g_value_get_enum (value);
939       gst_deinterlace_set_method (self, self->user_set_method_id);
940       break;
941     case PROP_FIELDS:{
942       gint new_fields;
943
944       GST_OBJECT_LOCK (self);
945       new_fields = g_value_get_enum (value);
946       if (self->user_set_fields != new_fields
947           && gst_pad_has_current_caps (self->srcpad)) {
948         self->reconfigure = TRUE;
949         self->new_fields = new_fields;
950       } else {
951         self->user_set_fields = new_fields;
952       }
953       GST_OBJECT_UNLOCK (self);
954       break;
955     }
956     case PROP_FIELD_LAYOUT:
957       self->field_layout = g_value_get_enum (value);
958       break;
959     case PROP_LOCKING:
960       self->locking = g_value_get_enum (value);
961       break;
962     case PROP_IGNORE_OBSCURE:
963       self->ignore_obscure = g_value_get_boolean (value);
964       break;
965     case PROP_DROP_ORPHANS:
966       self->drop_orphans = g_value_get_boolean (value);
967       break;
968     default:
969       G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
970   }
971
972 }
973
974 static void
975 gst_deinterlace_get_property (GObject * object, guint prop_id,
976     GValue * value, GParamSpec * pspec)
977 {
978   GstDeinterlace *self;
979
980   self = GST_DEINTERLACE (object);
981
982   switch (prop_id) {
983     case PROP_MODE:
984       g_value_set_enum (value, self->mode);
985       break;
986     case PROP_METHOD:
987       g_value_set_enum (value, self->user_set_method_id);
988       break;
989     case PROP_FIELDS:
990       g_value_set_enum (value, self->user_set_fields);
991       break;
992     case PROP_FIELD_LAYOUT:
993       g_value_set_enum (value, self->field_layout);
994       break;
995     case PROP_LOCKING:
996       g_value_set_enum (value, self->locking);
997       break;
998     case PROP_IGNORE_OBSCURE:
999       g_value_set_boolean (value, self->ignore_obscure);
1000       break;
1001     case PROP_DROP_ORPHANS:
1002       g_value_set_boolean (value, self->drop_orphans);
1003       break;
1004     default:
1005       G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
1006   }
1007 }
1008
1009 static void
1010 gst_deinterlace_finalize (GObject * object)
1011 {
1012   GstDeinterlace *self = GST_DEINTERLACE (object);
1013
1014   gst_deinterlace_reset (self);
1015
1016   if (self->method) {
1017     gst_object_unparent (GST_OBJECT (self->method));
1018     self->method = NULL;
1019   }
1020
1021   G_OBJECT_CLASS (parent_class)->finalize (object);
1022 }
1023
1024 static void
1025 gst_deinterlace_update_pattern_timestamps (GstDeinterlace * self)
1026 {
1027   gint state_idx;
1028   if (self->low_latency) {
1029     /* in low-latency mode the buffer state history contains old buffer
1030      * states as well as the current one and perhaps some future ones.
1031      * the current buffer's state is given by the number of field pairs
1032      * rounded up, minus 1. the below is equivalent */
1033     state_idx = (self->history_count - 1) >> 1;
1034   } else {
1035     /* in high-latency mode state_count - 1 is the current buffer's state */
1036     state_idx = self->state_count - 1;
1037   }
1038
1039   self->pattern_base_ts = self->buf_states[state_idx].timestamp;
1040   if (self->buf_states[state_idx].state != GST_RFF) {
1041     self->pattern_buf_dur =
1042         (self->buf_states[state_idx].duration *
1043         telecine_patterns[self->pattern].ratio_d) /
1044         telecine_patterns[self->pattern].ratio_n;
1045   } else {
1046     self->pattern_buf_dur =
1047         (self->buf_states[state_idx].duration *
1048         telecine_patterns[self->pattern].ratio_d * 2) /
1049         (telecine_patterns[self->pattern].ratio_n * 3);
1050   }
1051   GST_DEBUG_OBJECT (self,
1052       "Starting a new pattern repeat with base ts %" GST_TIME_FORMAT
1053       " and dur %" GST_TIME_FORMAT, GST_TIME_ARGS (self->pattern_base_ts),
1054       GST_TIME_ARGS (self->pattern_buf_dur));
1055 }
1056
1057 static void
1058 gst_deinterlace_get_buffer_state (GstDeinterlace * self, GstVideoFrame * frame,
1059     guint8 * state, GstVideoInterlaceMode * i_mode)
1060 {
1061   GstVideoInterlaceMode interlacing_mode;
1062
1063   if (!(i_mode || state))
1064     return;
1065
1066   interlacing_mode = GST_VIDEO_INFO_INTERLACE_MODE (&frame->info);
1067   if (self->mode == GST_DEINTERLACE_MODE_INTERLACED)
1068     interlacing_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
1069
1070   if (state) {
1071     if (interlacing_mode == GST_VIDEO_INTERLACE_MODE_MIXED) {
1072       if (GST_VIDEO_FRAME_IS_RFF (frame)) {
1073         *state = GST_DEINTERLACE_BUFFER_STATE_RFF;
1074       } else if (GST_VIDEO_FRAME_IS_ONEFIELD (frame)) {
1075         /* tc top if tff, tc bottom otherwise */
1076         if (GST_VIDEO_FRAME_IS_TFF (frame)) {
1077           *state = GST_DEINTERLACE_BUFFER_STATE_TC_T;
1078         } else {
1079           *state = GST_DEINTERLACE_BUFFER_STATE_TC_B;
1080         }
1081       } else if (GST_VIDEO_FRAME_IS_INTERLACED (frame)) {
1082         *state = GST_DEINTERLACE_BUFFER_STATE_TC_M;
1083       } else {
1084         *state = GST_DEINTERLACE_BUFFER_STATE_TC_P;
1085       }
1086     } else {
1087       if (interlacing_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED) {
1088         *state = GST_DEINTERLACE_BUFFER_STATE_I;
1089       } else {
1090         *state = GST_DEINTERLACE_BUFFER_STATE_P;
1091       }
1092     }
1093   }
1094
1095   if (i_mode)
1096     *i_mode = interlacing_mode;
1097 }
1098
1099 #define STATE_TO_STRING(s) ((s) == GST_DEINTERLACE_BUFFER_STATE_P ? "P" : \
1100   (s) == GST_DEINTERLACE_BUFFER_STATE_I ? "I" : \
1101   (s) == GST_DEINTERLACE_BUFFER_STATE_TC_B ? "B" : \
1102   (s) == GST_DEINTERLACE_BUFFER_STATE_TC_T ? "T" : \
1103   (s) == GST_DEINTERLACE_BUFFER_STATE_TC_P ? "TCP" : \
1104   (s) == GST_DEINTERLACE_BUFFER_STATE_TC_M ? "TCM" : "RFF")
1105
1106 #define MODE_TO_STRING(m) ((m) == GST_VIDEO_INTERLACE_MODE_MIXED ? "MIXED" : \
1107   (m) == GST_VIDEO_INTERLACE_MODE_INTERLEAVED ? "I" : \
1108   (m) == GST_VIDEO_INTERLACE_MODE_FIELDS ? "FIELDS" : "P")
1109
1110 static void
1111 gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer)
1112 {
1113   int i = 1;
1114   GstDeinterlaceFieldLayout field_layout = self->field_layout;
1115   gboolean tff;
1116   gboolean onefield;
1117   GstVideoFrame *frame = NULL;
1118   GstVideoFrame *field1, *field2 = NULL;
1119   guint fields_to_push;
1120   guint field1_flags, field2_flags;
1121   GstVideoInterlaceMode interlacing_mode;
1122   guint8 buf_state;
1123
1124   /* we will only read from this buffer and write into fresh output buffers
1125    * if this is not the case, change the map flags as appropriate
1126    */
1127   frame = gst_video_frame_new_and_map (&self->vinfo, buffer, GST_MAP_READ);
1128
1129   tff = GST_VIDEO_FRAME_IS_TFF (frame);
1130   onefield = GST_VIDEO_FRAME_IS_ONEFIELD (frame);
1131   fields_to_push = (onefield) ? 1 : 2;
1132
1133   g_return_if_fail (self->history_count <
1134       GST_DEINTERLACE_MAX_FIELD_HISTORY - fields_to_push);
1135
1136   gst_deinterlace_get_buffer_state (self, frame, &buf_state, &interlacing_mode);
1137
1138   GST_DEBUG_OBJECT (self,
1139       "Pushing new frame as %d fields to the history (count before %d): ptr %p at %"
1140       GST_TIME_FORMAT " with duration %" GST_TIME_FORMAT
1141       ", size %" G_GSIZE_FORMAT ", state %s, interlacing mode %s",
1142       fields_to_push, self->history_count, frame,
1143       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1144       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
1145       gst_buffer_get_size (buffer),
1146       STATE_TO_STRING (buf_state), MODE_TO_STRING (interlacing_mode));
1147
1148   /* move up for new state */
1149   memmove (&self->buf_states[1], &self->buf_states[0],
1150       (GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY - 1) *
1151       sizeof (GstDeinterlaceBufferState));
1152   self->buf_states[0].state = buf_state;
1153   self->buf_states[0].timestamp = GST_BUFFER_TIMESTAMP (buffer);
1154   self->buf_states[0].duration = GST_BUFFER_DURATION (buffer);
1155   if (self->state_count < GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY)
1156     self->state_count++;
1157
1158   for (i = GST_DEINTERLACE_MAX_FIELD_HISTORY - 1; i >= fields_to_push; i--) {
1159     self->field_history[i].frame =
1160         self->field_history[i - fields_to_push].frame;
1161     self->field_history[i].flags =
1162         self->field_history[i - fields_to_push].flags;
1163     self->field_history[i].tc = self->field_history[i - fields_to_push].tc;
1164     self->field_history[i].caption =
1165         self->field_history[i - fields_to_push].caption;
1166     self->field_history[i - fields_to_push].frame = NULL;
1167     self->field_history[i - fields_to_push].tc = NULL;
1168     self->field_history[i - fields_to_push].caption = NULL;
1169   }
1170
1171   if (field_layout == GST_DEINTERLACE_LAYOUT_AUTO) {
1172     if (!GST_VIDEO_INFO_IS_INTERLACED (&self->vinfo)) {
1173       GST_WARNING_OBJECT (self, "Can't detect field layout -- assuming TFF");
1174       field_layout = GST_DEINTERLACE_LAYOUT_TFF;
1175     } else if (tff) {
1176       field_layout = GST_DEINTERLACE_LAYOUT_TFF;
1177     } else {
1178       field_layout = GST_DEINTERLACE_LAYOUT_BFF;
1179     }
1180   }
1181
1182   field1 = frame;
1183   field2 = gst_video_frame_new_and_map (&self->vinfo, buffer, GST_MAP_READ);
1184   if (field_layout == GST_DEINTERLACE_LAYOUT_TFF) {
1185     GST_DEBUG_OBJECT (self, "Top field first");
1186     field1_flags = PICTURE_INTERLACED_TOP;
1187     field2_flags = PICTURE_INTERLACED_BOTTOM;
1188   } else {
1189     GST_DEBUG_OBJECT (self, "Bottom field first");
1190     field1_flags = PICTURE_INTERLACED_BOTTOM;
1191     field2_flags = PICTURE_INTERLACED_TOP;
1192   }
1193
1194   /* Swap for reverse playback */
1195   if (self->segment.rate < 0) {
1196     field1_flags = field1_flags ^ field2_flags;
1197     field2_flags = field1_flags ^ field2_flags;
1198     field1_flags = field1_flags ^ field2_flags;
1199   }
1200
1201   if (!onefield) {
1202     GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (buffer);
1203     GstVideoCaptionMeta *cc_meta = gst_buffer_get_video_caption_meta (buffer);
1204
1205     GST_DEBUG_OBJECT (self, "Two fields");
1206     self->field_history[1].frame = field1;
1207     self->field_history[1].flags = field1_flags;
1208
1209     self->field_history[0].frame = field2;
1210     self->field_history[0].flags = field2_flags;
1211
1212     if (meta) {
1213       self->field_history[0].tc = gst_video_time_code_copy (&meta->tc);
1214       self->field_history[0].tc->config.flags &=
1215           ~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
1216       self->field_history[1].tc = gst_video_time_code_copy (&meta->tc);
1217       self->field_history[1].tc->config.flags &=
1218           ~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
1219     }
1220
1221     if (cc_meta) {
1222       self->field_history[0].caption = g_new (GstVideoCaptionMeta, 1);
1223       self->field_history[0].caption->data = g_malloc (cc_meta->size);
1224       self->field_history[0].caption->caption_type = cc_meta->caption_type;
1225       self->field_history[0].caption->size = cc_meta->size;
1226       memcpy (self->field_history[0].caption->data, cc_meta->data,
1227           cc_meta->size);
1228       self->field_history[1].caption = g_new (GstVideoCaptionMeta, 1);
1229       self->field_history[1].caption->data = g_malloc (cc_meta->size);
1230       self->field_history[1].caption->caption_type = cc_meta->caption_type;
1231       self->field_history[1].caption->size = cc_meta->size;
1232       memcpy (self->field_history[1].caption->data, cc_meta->data,
1233           cc_meta->size);
1234     }
1235   } else {                      /* onefield */
1236     GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (buffer);
1237     GstVideoCaptionMeta *cc_meta = gst_buffer_get_video_caption_meta (buffer);
1238
1239     GST_DEBUG_OBJECT (self, "One field");
1240     self->field_history[0].frame = field1;
1241     self->field_history[0].flags = field1_flags;
1242     if (meta) {
1243       self->field_history[0].tc = gst_video_time_code_copy (&meta->tc);
1244       self->field_history[0].tc->config.flags &=
1245           ~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
1246     }
1247
1248     if (cc_meta) {
1249       self->field_history[0].caption = g_new (GstVideoCaptionMeta, 1);
1250       self->field_history[0].caption->data = g_malloc (cc_meta->size);
1251       self->field_history[0].caption->caption_type = cc_meta->caption_type;
1252       self->field_history[0].caption->size = cc_meta->size;
1253       memcpy (self->field_history[0].caption->data, cc_meta->data,
1254           cc_meta->size);
1255     }
1256     gst_video_frame_unmap_and_free (field2);
1257   }
1258
1259   /* we can manage the buffer ref count using the maps from here on */
1260   gst_buffer_unref (buffer);
1261
1262   self->history_count += fields_to_push;
1263   self->cur_field_idx += fields_to_push;
1264
1265   GST_DEBUG_OBJECT (self, "Pushed buffer -- current history size %d, index %d",
1266       self->history_count, self->cur_field_idx);
1267
1268   if (self->last_buffer)
1269     gst_buffer_unref (self->last_buffer);
1270   self->last_buffer = gst_buffer_ref (buffer);
1271 }
1272
1273 static void
1274 gst_deinterlace_update_qos (GstDeinterlace * self, gdouble proportion,
1275     GstClockTimeDiff diff, GstClockTime timestamp)
1276 {
1277   GST_DEBUG_OBJECT (self,
1278       "Updating QoS: proportion %lf, diff %" GST_STIME_FORMAT ", timestamp %"
1279       GST_TIME_FORMAT, proportion, GST_STIME_ARGS (diff),
1280       GST_TIME_ARGS (timestamp));
1281
1282   GST_OBJECT_LOCK (self);
1283   self->proportion = proportion;
1284   if (G_LIKELY (timestamp != GST_CLOCK_TIME_NONE)) {
1285     if (G_UNLIKELY (diff > 0))
1286       self->earliest_time =
1287           timestamp + 2 * diff + ((self->fields ==
1288               GST_DEINTERLACE_ALL) ? self->field_duration : 2 *
1289           self->field_duration);
1290     else
1291       self->earliest_time = timestamp + diff;
1292   } else {
1293     self->earliest_time = GST_CLOCK_TIME_NONE;
1294   }
1295   GST_OBJECT_UNLOCK (self);
1296 }
1297
1298 static void
1299 gst_deinterlace_reset_qos (GstDeinterlace * self)
1300 {
1301   gst_deinterlace_update_qos (self, 0.5, 0, GST_CLOCK_TIME_NONE);
1302   self->processed = 0;
1303   self->dropped = 0;
1304 }
1305
1306 static void
1307 gst_deinterlace_read_qos (GstDeinterlace * self, gdouble * proportion,
1308     GstClockTime * time)
1309 {
1310   GST_OBJECT_LOCK (self);
1311   *proportion = self->proportion;
1312   *time = self->earliest_time;
1313   GST_OBJECT_UNLOCK (self);
1314 }
1315
1316 /* Perform qos calculations before processing the next frame. Returns TRUE if
1317  * the frame should be processed, FALSE if the frame can be dropped entirely */
1318 static gboolean
1319 gst_deinterlace_do_qos (GstDeinterlace * self, const GstBuffer * buffer)
1320 {
1321   GstClockTime qostime, earliest_time;
1322   GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
1323   gdouble proportion;
1324
1325   /* no timestamp, can't do QoS => process frame */
1326   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
1327     GST_LOG_OBJECT (self, "invalid timestamp, can't do QoS, process frame");
1328     goto keep_frame;
1329   }
1330
1331   /* get latest QoS observation values */
1332   gst_deinterlace_read_qos (self, &proportion, &earliest_time);
1333
1334   /* skip qos if we have no observation (yet) => process frame */
1335   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
1336     GST_LOG_OBJECT (self, "no observation yet, process frame");
1337     goto keep_frame;
1338   }
1339
1340   /* qos is done on running time */
1341   qostime = gst_segment_to_running_time (&self->segment, GST_FORMAT_TIME,
1342       timestamp);
1343
1344   /* see how our next timestamp relates to the latest qos timestamp */
1345   GST_LOG_OBJECT (self, "qostime %" GST_TIME_FORMAT ", earliest %"
1346       GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
1347
1348   if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
1349     GstClockTime stream_time, jitter;
1350     GstMessage *qos_msg;
1351
1352     GST_DEBUG_OBJECT (self, "we are late, drop frame");
1353     self->dropped++;
1354     stream_time =
1355         gst_segment_to_stream_time (&self->segment, GST_FORMAT_TIME, timestamp);
1356     jitter = GST_CLOCK_DIFF (qostime, earliest_time);
1357     qos_msg =
1358         gst_message_new_qos (GST_OBJECT (self), FALSE, qostime, stream_time,
1359         timestamp, GST_BUFFER_DURATION (buffer));
1360     gst_message_set_qos_values (qos_msg, jitter, proportion, 1000000);
1361     gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS,
1362         self->processed, self->dropped);
1363     gst_element_post_message (GST_ELEMENT (self), qos_msg);
1364     return FALSE;
1365   }
1366
1367   GST_LOG_OBJECT (self, "process frame");
1368 keep_frame:
1369   self->processed++;
1370   return TRUE;
1371 }
1372
1373 static gboolean
1374 gst_deinterlace_fix_timestamps (GstDeinterlace * self,
1375     GstVideoFrame * field1, GstVideoFrame * field2)
1376 {
1377   GstVideoFrame *field3, *field4;
1378   GstVideoInterlaceMode interlacing_mode;
1379
1380   /* FIXME: This is broken for rate < 0 */
1381   if (self->pattern_lock && self->pattern > -1) {
1382     /* accurate pattern-locked timestamp adjustment */
1383     if (!self->pattern_count)
1384       gst_deinterlace_update_pattern_timestamps (self);
1385
1386     GST_BUFFER_TIMESTAMP (field1->buffer) =
1387         self->pattern_base_ts + self->output_count * self->pattern_buf_dur;
1388     GST_BUFFER_DURATION (field1->buffer) = self->pattern_buf_dur;
1389     self->output_count++;
1390   } else {
1391     /* naive (but low-latency) timestamp adjustment based on subsequent
1392      * fields/buffers */
1393     if (field2
1394         && GST_VIDEO_FRAME_PLANE_DATA (field1,
1395             0) != GST_VIDEO_FRAME_PLANE_DATA (field2, 0)) {
1396       if (GST_BUFFER_TIMESTAMP (field1->buffer) +
1397           GST_BUFFER_DURATION (field1->buffer) ==
1398           GST_BUFFER_TIMESTAMP (field2->buffer)) {
1399         GST_BUFFER_TIMESTAMP (field1->buffer) =
1400             GST_BUFFER_TIMESTAMP (field2->buffer) =
1401             (GST_BUFFER_TIMESTAMP (field1->buffer) +
1402             GST_BUFFER_TIMESTAMP (field2->buffer)) / 2;
1403       } else {
1404         GST_BUFFER_TIMESTAMP (field2->buffer) =
1405             GST_BUFFER_TIMESTAMP (field1->buffer);
1406       }
1407     }
1408
1409     if (self->history_count < 3) {
1410       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need 3)",
1411           self->history_count);
1412       return FALSE;
1413     }
1414
1415     field3 = self->field_history[self->history_count - 3].frame;
1416     interlacing_mode = GST_VIDEO_INFO_INTERLACE_MODE (&field3->info);
1417     if (IS_TELECINE (interlacing_mode)) {
1418       if (self->history_count < 4) {
1419         GST_DEBUG_OBJECT (self, "Need more fields (have %d, need 4)",
1420             self->history_count);
1421         return FALSE;
1422       }
1423
1424       field4 = self->field_history[self->history_count - 4].frame;
1425       if (GST_VIDEO_FRAME_PLANE_DATA (field3,
1426               0) != GST_VIDEO_FRAME_PLANE_DATA (field4, 0)) {
1427         /* telecine fields in separate buffers */
1428         GST_BUFFER_TIMESTAMP (field3->buffer) =
1429             (GST_BUFFER_TIMESTAMP (field3->buffer) +
1430             GST_BUFFER_TIMESTAMP (field4->buffer)) / 2;
1431       }
1432     }
1433
1434     GST_BUFFER_DURATION (field1->buffer) =
1435         GST_BUFFER_TIMESTAMP (field3->buffer) -
1436         GST_BUFFER_TIMESTAMP (field1->buffer);
1437   }
1438
1439   GST_DEBUG_OBJECT (self,
1440       "Field 1 adjusted to ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
1441       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1->buffer)),
1442       GST_TIME_ARGS (GST_BUFFER_DURATION (field1->buffer)));
1443   return TRUE;
1444 }
1445
1446 static void
1447 gst_deinterlace_get_pattern_lock (GstDeinterlace * self, gboolean * flush_one)
1448 {
1449   /* loop over all possible patterns and all possible phases
1450    * giving each a score. the highest score gets the lock */
1451   /* the score is calculated as the number of matched buffers in the
1452    * sequence starting at the phase offset with those from the history
1453    * then the longest duration pattern match is taken. if there is more than
1454    * one pattern matching all buffers, we take the longest pattern of those.
1455    * matches to complete patterns are preferred. if no non-trivial pattern is
1456    * matched, trivial patterns are tested. */
1457   gint i, j, k, score, pattern, phase;
1458   const gint state_count = self->state_count;
1459   const gint n_required = self->ignore_obscure ?
1460       GST_DEINTERLACE_OBSCURE_THRESHOLD :
1461       GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY;
1462
1463   /* set unknown pattern as this is used in logic outside this function */
1464   self->pattern = -1;
1465
1466   /* wait for more buffers */
1467   if (!self->have_eos && state_count < n_required) {
1468     GST_DEBUG_OBJECT (self, "Need more buffers in state history - %d/%d",
1469         state_count, n_required);
1470     return;
1471   }
1472
1473   score = pattern = phase = -1;
1474
1475   /* loop over all patterns */
1476   for (i = 0; i < G_N_ELEMENTS (telecine_patterns); i++) {
1477     const guint8 length = telecine_patterns[i].length;
1478
1479     if (self->ignore_obscure && i >= GST_DEINTERLACE_OBSCURE_THRESHOLD)
1480       break;
1481
1482     if (state_count < length)
1483       continue;
1484
1485     /* loop over all phases */
1486     for (j = 0; j < length; j++) {
1487       /* low-latency mode looks at past buffers, high latency at future buffers */
1488       const gint state_idx =
1489           self->low_latency ? (self->history_count - 1) >> 1 : state_count - 1;
1490       /* loop over history, breaking on differing buffer states */
1491       for (k = 0; k < length && k < state_count; k++) {
1492         const guint8 hist = self->buf_states[state_idx - k].state;
1493         const guint8 patt = telecine_patterns[i].states[(j + k) % length];
1494         if (!(hist & patt))
1495           break;
1496       }
1497
1498       /* make complete matches more signficant */
1499       if (k == length)
1500         k += GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY;
1501
1502       /* take as new best pattern if the number of matched buffers is more than
1503        * for other patterns */
1504       if (k > score) {
1505         score = k;
1506         pattern = i;
1507         phase = j;
1508       }
1509     }
1510   }
1511
1512   if (pattern < 0) {
1513     GST_WARNING_OBJECT (self, "Failed to select a pattern");
1514     return;
1515   }
1516
1517   GST_DEBUG_OBJECT (self,
1518       "Final pattern match result: pa %d, ph %d, l %d, s %d", pattern, phase,
1519       telecine_patterns[pattern].length, score);
1520   self->pattern = pattern;
1521   self->pattern_phase = phase;
1522   self->pattern_count = 0;
1523   self->output_count = 0;
1524   self->pattern_lock = TRUE;
1525
1526   for (i = 0; i < telecine_patterns[pattern].length; i++) {
1527     gint state_idx =
1528         self->low_latency ? (self->history_count - 1) >> 1 : self->state_count -
1529         1;
1530     state_idx -= i;
1531     GST_LOG_OBJECT (self, "buf[%d] %s", i,
1532         STATE_TO_STRING (self->buf_states[state_idx].state));
1533   }
1534
1535   /* check for the case that the first field of the pattern is an orphan */
1536   if (pattern > 1
1537       && telecine_patterns[pattern].states[phase] & (GST_ONE | GST_INT)) {
1538     gint i = phase, field_count = 0;
1539     guint8 state = telecine_patterns[pattern].states[i];
1540
1541     do {
1542       if (state & GST_ONE) {
1543         field_count++;
1544 #if 0
1545       } else if (!(state & GST_DRP)) {
1546 #endif
1547       } else {
1548         field_count += 2;
1549       }
1550       i++;
1551       i %= telecine_patterns[pattern].length;
1552       state = telecine_patterns[pattern].states[i];
1553     } while (!(state & GST_PRG));
1554
1555     /* if field_count is odd, we have an orphan field at the beginning of the
1556      * sequence
1557      * note - don't do this in low-latency mode as we are somewhere within the
1558      * pattern already */
1559     if (!self->low_latency && (*flush_one = field_count & 1)) {
1560       GST_DEBUG_OBJECT (self, "Orphan field detected at the beginning of the "
1561           "pattern - it will be deinterlaced.");
1562     }
1563   }
1564 }
1565
1566 static GstFlowReturn
1567 gst_deinterlace_output_frame (GstDeinterlace * self, gboolean flushing)
1568 {
1569   GstClockTime timestamp;
1570   GstFlowReturn ret;
1571   gint fields_required;
1572   GstBuffer *buf, *outbuf;
1573   GstVideoFrame *outframe = NULL;
1574   GstDeinterlaceField *field1, *field2;
1575   GstVideoInterlaceMode interlacing_mode;
1576   guint8 buf_state;
1577   gboolean hl_no_lock;          /* indicates high latency timestamp adjustment but no pattern lock (could be ONEF or I) */
1578   gboolean same_buffer;         /* are field1 and field2 in the same buffer? */
1579   gboolean flush_one;           /* used for flushing one field when in high latency mode and not locked */
1580   TelecinePattern pattern;
1581   guint8 phase, count;
1582   const GstDeinterlaceLocking locking = self->locking;
1583   gboolean cc_added = FALSE;
1584
1585   memset (&pattern, 0, sizeof (pattern));
1586
1587 restart:
1588   ret = GST_FLOW_OK;
1589   hl_no_lock = FALSE;
1590   flush_one = FALSE;
1591   self->need_more = FALSE;
1592   phase = self->pattern_phase;
1593   count = self->pattern_count;
1594
1595   if (!self->history_count) {
1596     GST_DEBUG_OBJECT (self, "History is empty, waiting for more buffers!");
1597     goto need_more;
1598   }
1599
1600   field1 = &self->field_history[self->history_count - 1];
1601
1602   if (locking != GST_DEINTERLACE_LOCKING_NONE) {
1603     GstCaps *sinkcaps;
1604
1605     if (!self->state_count) {
1606       GST_ERROR_OBJECT (self,
1607           "BROKEN! Fields in history + no states should not happen!");
1608       return GST_FLOW_ERROR;
1609     }
1610
1611     gst_deinterlace_get_buffer_state (self, field1->frame, &buf_state,
1612         &interlacing_mode);
1613
1614     if (self->pattern != -1)
1615       pattern = telecine_patterns[self->pattern];
1616
1617     /* patterns 0 and 1 are interlaced, the rest are telecine */
1618     if (self->pattern > 1)
1619       interlacing_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
1620
1621     if (self->pattern == -1 || self->pattern_refresh
1622         || !(buf_state & pattern.states[(phase + count) % pattern.length])) {
1623       if (self->pattern == -1) {
1624         GST_DEBUG_OBJECT (self, "No pattern lock - refresh lock");
1625       } else if (self->pattern_refresh) {
1626         GST_DEBUG_OBJECT (self, "Pattern refresh - refresh lock");
1627       } else {
1628         GST_DEBUG_OBJECT (self, "Unexpected buffer state - refresh lock");
1629       }
1630       /* no pattern, pattern refresh set or unexpected buffer state */
1631       self->pattern_lock = FALSE;
1632       self->pattern_refresh = TRUE;
1633
1634       /* refresh pattern lock */
1635       gst_deinterlace_get_pattern_lock (self, &flush_one);
1636
1637       if (self->pattern != -1) {
1638         /* locked onto a valid pattern so refresh complete */
1639         GST_DEBUG_OBJECT (self, "Pattern locked! %s starting at %d",
1640             telecine_patterns[self->pattern].nick, self->pattern_phase);
1641         self->pattern_refresh = FALSE;
1642       } else if (!self->low_latency) {
1643         if (!self->pattern_lock) {
1644           goto need_more;
1645         } else {
1646           hl_no_lock = TRUE;
1647         }
1648       }
1649
1650       /* setcaps on sink and src pads */
1651       sinkcaps = gst_pad_get_current_caps (self->sinkpad);
1652       if (!sinkcaps || !gst_deinterlace_setcaps (self, self->sinkpad, sinkcaps)) {
1653         if (sinkcaps)
1654           gst_caps_unref (sinkcaps);
1655         return GST_FLOW_NOT_NEGOTIATED;
1656       }
1657
1658       gst_caps_unref (sinkcaps);
1659
1660       if (flush_one && self->drop_orphans) {
1661         GST_DEBUG_OBJECT (self, "Dropping orphan first field");
1662         self->cur_field_idx--;
1663         gst_deinterlace_pop_and_clear (self);
1664         goto restart;
1665       }
1666     }
1667   } else {
1668     gst_deinterlace_get_buffer_state (self, field1->frame, NULL,
1669         &interlacing_mode);
1670   }
1671
1672   same_buffer = self->history_count >= 2
1673       && (GST_VIDEO_FRAME_PLANE_DATA (field1->frame, 0) ==
1674       GST_VIDEO_FRAME_PLANE_DATA (self->field_history[self->history_count -
1675               2].frame, 0));
1676
1677   if ((flushing && self->history_count == 1) || (flush_one
1678           && !self->drop_orphans) || (hl_no_lock && (self->history_count == 1
1679               || !same_buffer))) {
1680     /* This case is for flushing a single field:
1681      * - flushing and 1 field in the history
1682      * - flush one (due to orphans in the pattern) and do not drop orphans
1683      * - high-latency pattern locking with no possible lock given the current
1684      *   state and either only one field in the history or the tip two fields
1685      *   are in separate buffers */
1686     GST_DEBUG_OBJECT (self, "Flushing one field using linear method");
1687     gst_deinterlace_set_method (self, GST_DEINTERLACE_LINEAR);
1688     fields_required = gst_deinterlace_method_get_fields_required (self->method);
1689   } else if (interlacing_mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE ||
1690       (interlacing_mode == GST_VIDEO_INTERLACE_MODE_MIXED &&
1691           !GST_VIDEO_FRAME_IS_INTERLACED (field1->frame))) {
1692     /* This case is for processing progressive buffers, telecine or plain
1693      * progressive */
1694     GstVideoFrame *field1_frame;
1695     GstBuffer *field1_buffer;
1696
1697     /* progressive */
1698     fields_required = 2;
1699
1700     /* Not enough fields in the history */
1701     if (!flushing && self->history_count < fields_required) {
1702       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1703           self->history_count, self->cur_field_idx + fields_required);
1704       goto need_more;
1705     }
1706
1707     field2 = &self->field_history[self->history_count - 2];
1708     if (GST_VIDEO_FRAME_PLANE_DATA (field1->frame,
1709             0) != GST_VIDEO_FRAME_PLANE_DATA (field2->frame, 0)) {
1710       /* ERROR - next two fields in field history are not one progressive buffer - weave? */
1711       GST_ERROR_OBJECT (self,
1712           "Progressive buffer but two fields at tip aren't in the same buffer!");
1713     }
1714
1715     if (IS_TELECINE (interlacing_mode)
1716         && !gst_deinterlace_fix_timestamps (self, field1->frame, field2->frame)
1717         && !flushing)
1718       goto need_more;
1719
1720     GST_DEBUG_OBJECT (self,
1721         "Frame type: Progressive; pushing buffer as a frame");
1722     /* pop and push */
1723     gst_deinterlace_delete_meta_at (self, self->history_count - 1);
1724     self->cur_field_idx--;
1725     field1_frame = gst_deinterlace_pop_history (self);
1726     field1_buffer = field1_frame->buffer;
1727     gst_buffer_ref (field1_buffer);
1728     gst_video_frame_unmap_and_free (field1_frame);
1729
1730     /* field2 is the same buffer as field1, but we need to remove it from the
1731      * history anyway */
1732     self->cur_field_idx--;
1733     gst_deinterlace_pop_and_clear (self);
1734     GST_DEBUG_OBJECT (self,
1735         "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1736         GST_TIME_FORMAT,
1737         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1_buffer)),
1738         GST_TIME_ARGS (GST_BUFFER_DURATION (field1_buffer)),
1739         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1_buffer) +
1740             GST_BUFFER_DURATION (field1_buffer)));
1741     if (self->discont) {
1742       GST_BUFFER_FLAG_SET (field1_buffer, GST_BUFFER_FLAG_DISCONT);
1743       self->discont = FALSE;
1744     }
1745     return gst_pad_push (self->srcpad, field1_buffer);
1746   } else if (IS_TELECINE (interlacing_mode)
1747       && GST_VIDEO_FRAME_IS_INTERLACED (field1->frame) && !same_buffer) {
1748     /* This case needs to identify telecine mixed buffers that require weaving
1749      * of two fields in different buffers.
1750      * - interlacing mode is mixed
1751      * - locked on to a telecine pattern
1752      * - frame is interlaced
1753      * - fields are in separate buffers
1754      * If we don't yet have a pattern lock, we will have to deinterlace as we
1755      * don't explicitly know we have a telecine sequence and so we drop through
1756      * to the plain deinterlace case */
1757     fields_required = 2;
1758     if (!flushing && self->history_count < fields_required) {
1759       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1760           self->history_count, self->cur_field_idx + fields_required);
1761       goto need_more;
1762     }
1763
1764     field2 = &self->field_history[self->history_count - 2];
1765     if (!gst_deinterlace_fix_timestamps (self, field1->frame, field2->frame)
1766         && !flushing)
1767       goto need_more;
1768
1769     /* check field1 and field2 buffer caps and flags are corresponding */
1770     if (field1->flags == field2->flags) {
1771       /* ERROR - fields are of same parity - what should be done here?
1772        * perhaps deinterlace the tip field and start again? */
1773       GST_ERROR_OBJECT (self, "Telecine mixed with fields of same parity!");
1774     }
1775     GST_DEBUG_OBJECT (self,
1776         "Frame type: Telecine Mixed; weaving tip two fields into a frame");
1777     /* set method to WEAVE */
1778     gst_deinterlace_set_method (self, GST_DEINTERLACE_WEAVE);
1779   } else {
1780     /* This is the final catch-all case that applies the selected deinterlacing
1781      * method. At this point the fields to be processed are either definitely
1782      * interlaced or we do not yet know that we have a telecine pattern lock
1783      * and so the best we can do is to deinterlace the fields. */
1784     gst_deinterlace_set_method (self, self->user_set_method_id);
1785     fields_required = gst_deinterlace_method_get_fields_required (self->method);
1786     if (flushing && self->history_count < fields_required) {
1787       /* note: we already checked for flushing with history count == 1 above
1788        * so we must have 2 or more fields in here */
1789       gst_deinterlace_set_method (self, GST_DEINTERLACE_VFIR);
1790       fields_required =
1791           gst_deinterlace_method_get_fields_required (self->method);
1792       GST_DEBUG_OBJECT (self, "Flushing field(s) using %s method",
1793           methods_types[self->method_id].value_nick);
1794     }
1795
1796     /* Not enough fields in the history */
1797     if (!flushing && self->history_count < fields_required) {
1798       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1799           self->history_count, self->cur_field_idx + fields_required);
1800       goto need_more;
1801     }
1802
1803     GST_DEBUG_OBJECT (self,
1804         "Frame type: Interlaced; deinterlacing using %s method",
1805         methods_types[self->method_id].value_nick);
1806   }
1807
1808   if (!flushing && self->cur_field_idx < 1) {
1809     goto need_more;
1810   } else if (self->cur_field_idx < 0 && flushing) {
1811     self->cur_field_idx++;
1812   }
1813
1814   if (self->fields == GST_DEINTERLACE_ALL || IS_TELECINE (interlacing_mode))
1815     GST_DEBUG_OBJECT (self, "All fields");
1816   else if (self->fields == GST_DEINTERLACE_TF)
1817     GST_DEBUG_OBJECT (self, "Top fields");
1818   else if (self->fields == GST_DEINTERLACE_BF)
1819     GST_DEBUG_OBJECT (self, "Bottom fields");
1820
1821   if ((self->field_history[self->cur_field_idx].flags == PICTURE_INTERLACED_TOP
1822           && (self->fields == GST_DEINTERLACE_TF
1823               || IS_TELECINE (interlacing_mode)))
1824       || (self->fields == GST_DEINTERLACE_ALL
1825           && !IS_TELECINE (interlacing_mode))) {
1826     gint index;
1827
1828     GST_DEBUG_OBJECT (self, "deinterlacing top field");
1829
1830     /* create new buffer */
1831     ret = gst_buffer_pool_acquire_buffer (self->pool, &outbuf, NULL);
1832     if (ret != GST_FLOW_OK)
1833       goto no_buffer;
1834
1835     g_return_val_if_fail (self->history_count >=
1836         1 + gst_deinterlace_method_get_latency (self->method), GST_FLOW_ERROR);
1837
1838     index =
1839         self->history_count - 1 -
1840         gst_deinterlace_method_get_latency (self->method);
1841     buf = self->field_history[index].frame->buffer;
1842
1843     if (self->field_history[index].tc) {
1844       gst_buffer_add_video_time_code_meta (outbuf,
1845           self->field_history[index].tc);
1846     }
1847     if (self->field_history[index].caption) {
1848       g_assert (self->field_history[index].caption->data != NULL);
1849       g_assert (!cc_added);
1850       gst_buffer_add_video_caption_meta (outbuf,
1851           self->field_history[index].caption->caption_type,
1852           self->field_history[index].caption->data,
1853           self->field_history[index].caption->size);
1854       cc_added = TRUE;
1855     }
1856     if (IS_TELECINE (interlacing_mode) && !self->telecine_tc_warned) {
1857       self->telecine_tc_warned = TRUE;
1858       GST_FIXME_OBJECT (self,
1859           "Detected telecine timecodes when deinterlacing. This is not "
1860           "supported yet. Resulting timecode may be wrong");
1861     }
1862     if (self->fields == GST_DEINTERLACE_ALL) {
1863       GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (outbuf);
1864       if (meta) {
1865         meta->tc.config.fps_n = 2 * meta->tc.config.fps_n;
1866         meta->tc.frames = 2 * meta->tc.frames;
1867       }
1868     }
1869     if (!IS_TELECINE (interlacing_mode)) {
1870       timestamp = GST_BUFFER_TIMESTAMP (buf);
1871
1872       if (self->fields == GST_DEINTERLACE_ALL) {
1873         if (self->segment.rate < 0)
1874           GST_BUFFER_TIMESTAMP (outbuf) = timestamp + self->field_duration;
1875         else
1876           GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1877         GST_BUFFER_DURATION (outbuf) = self->field_duration;
1878       } else {
1879         GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1880         GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration;
1881       }
1882       GST_DEBUG_OBJECT (self,
1883           "[ADJUST] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1884           GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1885           GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
1886           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
1887               GST_BUFFER_DURATION (outbuf)));
1888     } else {
1889       GST_BUFFER_TIMESTAMP (outbuf) =
1890           GST_BUFFER_TIMESTAMP (field1->frame->buffer);
1891       GST_BUFFER_DURATION (outbuf) =
1892           GST_BUFFER_DURATION (field1->frame->buffer);
1893     }
1894
1895     /* Check if we need to drop the frame because of QoS */
1896     if (!gst_deinterlace_do_qos (self, buf)) {
1897       self->cur_field_idx--;
1898       gst_deinterlace_pop_and_clear (self);
1899       gst_buffer_unref (outbuf);
1900       outbuf = NULL;
1901       ret = GST_FLOW_OK;
1902     } else {
1903       if (self->cur_field_idx < 0 && flushing) {
1904         if (self->history_count == 1) {
1905           gst_deinterlace_pop_and_clear (self);
1906           goto need_more;
1907         }
1908         self->cur_field_idx++;
1909       }
1910       if (self->cur_field_idx < 0) {
1911         goto need_more;
1912       }
1913       if (!flushing && self->cur_field_idx < 1) {
1914         goto need_more;
1915       }
1916
1917       /* map the frame so the deinterlace methods can write the data to the
1918        * correct memory locations */
1919       outframe =
1920           gst_video_frame_new_and_map (&self->vinfo, outbuf, GST_MAP_WRITE);
1921
1922       /* do magic calculus */
1923       gst_deinterlace_method_deinterlace_frame (self->method,
1924           self->field_history, self->history_count, outframe,
1925           self->cur_field_idx);
1926
1927       gst_video_frame_unmap_and_free (outframe);
1928
1929       self->cur_field_idx--;
1930       /* need to remove the field in the telecine weaving case */
1931       if ((IS_TELECINE (interlacing_mode)
1932               && self->method_id == GST_DEINTERLACE_WEAVE)
1933           || self->cur_field_idx + 1 +
1934           gst_deinterlace_method_get_latency (self->method) <
1935           self->history_count || flushing) {
1936         gst_deinterlace_pop_and_clear (self);
1937       }
1938
1939       if (gst_deinterlace_clip_buffer (self, outbuf)) {
1940         GST_DEBUG_OBJECT (self,
1941             "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1942             GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1943             GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
1944             GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
1945                 GST_BUFFER_DURATION (outbuf)));
1946         if (self->discont) {
1947           GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1948           self->discont = FALSE;
1949         }
1950         ret = gst_pad_push (self->srcpad, outbuf);
1951       } else {
1952         ret = GST_FLOW_OK;
1953         gst_buffer_unref (outbuf);
1954       }
1955
1956       outbuf = NULL;
1957       if (ret != GST_FLOW_OK)
1958         return ret;
1959       if (IS_TELECINE (interlacing_mode)
1960           && self->method_id == GST_DEINTERLACE_WEAVE) {
1961         /* pop off the second field */
1962         GST_DEBUG_OBJECT (self, "Removing unused field (count: %d)",
1963             self->history_count);
1964         self->cur_field_idx--;
1965         gst_deinterlace_pop_and_clear (self);
1966         interlacing_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
1967         return ret;
1968       }
1969     }
1970
1971     if (flush_one && !self->drop_orphans) {
1972       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
1973       goto restart;
1974     }
1975   }
1976   /* no calculation done: remove excess field */
1977   else if (self->field_history[self->cur_field_idx].flags ==
1978       PICTURE_INTERLACED_TOP && (self->fields == GST_DEINTERLACE_BF
1979           && !IS_TELECINE (interlacing_mode))) {
1980     GST_DEBUG_OBJECT (self, "Removing unused top field");
1981     self->cur_field_idx--;
1982     gst_deinterlace_pop_and_clear (self);
1983
1984     if (flush_one && !self->drop_orphans) {
1985       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
1986       goto restart;
1987     }
1988   }
1989
1990   if (self->history_count < fields_required)
1991     return ret;
1992
1993   if (self->cur_field_idx < 0)
1994     return ret;
1995
1996   /* deinterlace bottom_field */
1997   if ((self->field_history[self->cur_field_idx].flags ==
1998           PICTURE_INTERLACED_BOTTOM && (self->fields == GST_DEINTERLACE_BF
1999               || IS_TELECINE (interlacing_mode)))
2000       || (self->fields == GST_DEINTERLACE_ALL
2001           && !IS_TELECINE (interlacing_mode))) {
2002     gint index;
2003
2004     GST_DEBUG_OBJECT (self, "deinterlacing bottom field");
2005
2006     /* create new buffer */
2007     ret = gst_buffer_pool_acquire_buffer (self->pool, &outbuf, NULL);
2008     if (ret != GST_FLOW_OK)
2009       goto no_buffer;
2010
2011     g_return_val_if_fail (self->history_count >=
2012         gst_deinterlace_method_get_latency (self->method) + 1, GST_FLOW_ERROR);
2013
2014     index =
2015         self->history_count - 1 -
2016         gst_deinterlace_method_get_latency (self->method);
2017     buf = self->field_history[index].frame->buffer;
2018
2019     if (self->field_history[index].tc) {
2020       gst_buffer_add_video_time_code_meta (outbuf,
2021           self->field_history[index].tc);
2022     }
2023     if (self->field_history[index].caption && !cc_added) {
2024       g_assert (self->field_history[index].caption->data != NULL);
2025       gst_buffer_add_video_caption_meta (outbuf,
2026           self->field_history[index].caption->caption_type,
2027           self->field_history[index].caption->data,
2028           self->field_history[index].caption->size);
2029       cc_added = TRUE;
2030     }
2031     if (IS_TELECINE (interlacing_mode) && !self->telecine_tc_warned) {
2032       self->telecine_tc_warned = TRUE;
2033       GST_FIXME_OBJECT (self,
2034           "Detected telecine timecodes when deinterlacing. This is not "
2035           "supported yet. Resulting timecode may be wrong");
2036     }
2037     if (self->fields == GST_DEINTERLACE_ALL) {
2038       GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (outbuf);
2039       if (meta) {
2040         meta->tc.config.fps_n = 2 * meta->tc.config.fps_n;
2041         meta->tc.frames = 2 * meta->tc.frames + 1;
2042       }
2043     }
2044     if (!IS_TELECINE (interlacing_mode)) {
2045       timestamp = GST_BUFFER_TIMESTAMP (buf);
2046
2047       if (self->fields == GST_DEINTERLACE_ALL) {
2048         if (self->segment.rate < 0)
2049           GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
2050         else
2051           GST_BUFFER_TIMESTAMP (outbuf) = timestamp + self->field_duration;
2052         GST_BUFFER_DURATION (outbuf) = self->field_duration;
2053       } else {
2054         GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
2055         GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration;
2056       }
2057       GST_DEBUG_OBJECT (self,
2058           "[ADJUST] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2059           GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
2060           GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
2061           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
2062               GST_BUFFER_DURATION (outbuf)));
2063     } else {
2064       GST_BUFFER_TIMESTAMP (outbuf) =
2065           GST_BUFFER_TIMESTAMP (field1->frame->buffer);
2066       GST_BUFFER_DURATION (outbuf) =
2067           GST_BUFFER_DURATION (field1->frame->buffer);
2068     }
2069
2070     /* Check if we need to drop the frame because of QoS */
2071     if (!gst_deinterlace_do_qos (self, buf)) {
2072       self->cur_field_idx--;
2073       gst_deinterlace_pop_and_clear (self);
2074       gst_buffer_unref (outbuf);
2075       outbuf = NULL;
2076       ret = GST_FLOW_OK;
2077     } else {
2078       /* map the frame so the deinterlace methods can write the data to the
2079        * correct memory locations */
2080       outframe =
2081           gst_video_frame_new_and_map (&self->vinfo, outbuf, GST_MAP_WRITE);
2082
2083       /* do magic calculus */
2084       gst_deinterlace_method_deinterlace_frame (self->method,
2085           self->field_history, self->history_count, outframe,
2086           self->cur_field_idx);
2087
2088       gst_video_frame_unmap_and_free (outframe);
2089
2090       self->cur_field_idx--;
2091       /* need to remove the field in the telecine weaving case */
2092       if ((IS_TELECINE (interlacing_mode)
2093               && self->method_id == GST_DEINTERLACE_WEAVE)
2094           || self->cur_field_idx + 1 +
2095           gst_deinterlace_method_get_latency (self->method) <
2096           self->history_count) {
2097         gst_deinterlace_pop_and_clear (self);
2098       }
2099
2100       if (gst_deinterlace_clip_buffer (self, outbuf)) {
2101         GST_DEBUG_OBJECT (self,
2102             "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2103             GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
2104             GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
2105             GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
2106                 GST_BUFFER_DURATION (outbuf)));
2107         ret = gst_pad_push (self->srcpad, outbuf);
2108       } else {
2109         ret = GST_FLOW_OK;
2110         gst_buffer_unref (outbuf);
2111       }
2112
2113       outbuf = NULL;
2114       if (ret != GST_FLOW_OK)
2115         return ret;
2116       if (IS_TELECINE (interlacing_mode)
2117           && self->method_id == GST_DEINTERLACE_WEAVE) {
2118         /* pop off the second field */
2119         GST_DEBUG_OBJECT (self, "Removing unused field (count: %d)",
2120             self->history_count);
2121         self->cur_field_idx--;
2122         gst_deinterlace_pop_and_clear (self);
2123         interlacing_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
2124         return ret;
2125       }
2126     }
2127
2128     if (flush_one && !self->drop_orphans) {
2129       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
2130       goto restart;
2131     }
2132   }
2133   /* no calculation done: remove excess field */
2134   else if (self->field_history[self->cur_field_idx].flags ==
2135       PICTURE_INTERLACED_BOTTOM && (self->fields == GST_DEINTERLACE_TF
2136           && !IS_TELECINE (interlacing_mode))) {
2137     GST_DEBUG_OBJECT (self, "Removing unused bottom field");
2138     self->cur_field_idx--;
2139     gst_deinterlace_pop_and_clear (self);
2140
2141     if (flush_one && !self->drop_orphans) {
2142       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
2143       goto restart;
2144     }
2145   }
2146
2147   return ret;
2148
2149 need_more:
2150   {
2151     self->need_more = TRUE;
2152     return ret;
2153   }
2154 no_buffer:
2155   {
2156     GST_DEBUG_OBJECT (self, "could not allocate buffer");
2157     return ret;
2158   }
2159 }
2160
2161 static gboolean
2162 gst_deinterlace_get_latency (GstDeinterlace * self)
2163 {
2164   if (self->locking == GST_DEINTERLACE_LOCKING_AUTO) {
2165     GstQuery *query;
2166
2167     query = gst_query_new_latency ();
2168     if ((gst_pad_peer_query (self->sinkpad, query))) {
2169       gboolean is_live;
2170       /* if upstream is live, we use low-latency passive locking mode
2171        * else high-latency active locking mode */
2172       gst_query_parse_latency (query, &is_live, NULL, NULL);
2173       GST_DEBUG_OBJECT (self, "Latency query indicates stream is %s",
2174           is_live ? "live - using passive locking" :
2175           "not live - using active locking");
2176       gst_query_unref (query);
2177       return is_live;
2178     } else {
2179       /* conservatively use passive locking if the query fails */
2180       GST_WARNING_OBJECT (self,
2181           "Latency query failed - fall back to using passive locking");
2182       gst_query_unref (query);
2183       return TRUE;
2184     }
2185   } else {
2186     return self->locking - 2;
2187   }
2188 }
2189
2190 static GstFlowReturn
2191 gst_deinterlace_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
2192 {
2193   GstDeinterlace *self = GST_DEINTERLACE (parent);
2194   GstFlowReturn ret = GST_FLOW_OK;
2195
2196   GST_OBJECT_LOCK (self);
2197   if (self->reconfigure || gst_pad_check_reconfigure (self->srcpad)) {
2198     GstCaps *caps;
2199
2200     if ((gint) self->new_fields != -1)
2201       self->user_set_fields = self->new_fields;
2202     if ((gint) self->new_mode != -1)
2203       self->mode = self->new_mode;
2204     self->new_mode = -1;
2205     self->new_fields = -1;
2206
2207     self->reconfigure = FALSE;
2208     GST_OBJECT_UNLOCK (self);
2209     caps = gst_pad_get_current_caps (self->sinkpad);
2210     if (caps != NULL) {
2211       if (!gst_deinterlace_setcaps (self, self->sinkpad, caps)) {
2212         gst_pad_mark_reconfigure (self->srcpad);
2213         gst_caps_unref (caps);
2214         if (GST_PAD_IS_FLUSHING (self->srcpad))
2215           return GST_FLOW_FLUSHING;
2216         else
2217           return GST_FLOW_NOT_NEGOTIATED;
2218       }
2219       gst_caps_unref (caps);
2220     } else {
2221       gst_pad_mark_reconfigure (self->srcpad);
2222       return GST_FLOW_FLUSHING;
2223     }
2224   } else {
2225     GST_OBJECT_UNLOCK (self);
2226   }
2227
2228   GST_DEBUG_OBJECT (self,
2229       "[IN] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2230       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
2231       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
2232       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)));
2233
2234   if (self->still_frame_mode || self->passthrough) {
2235     GST_DEBUG_OBJECT (self,
2236         "Frame type: Progressive?; pushing buffer using pass-through");
2237     GST_DEBUG_OBJECT (self,
2238         "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2239         GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
2240         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
2241         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)));
2242
2243     return gst_pad_push (self->srcpad, buf);
2244   }
2245
2246   if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
2247     GST_DEBUG_OBJECT (self, "DISCONT buffer, resetting history");
2248     gst_deinterlace_reset_history (self, FALSE);
2249     self->discont = TRUE;
2250   }
2251
2252   gst_deinterlace_push_history (self, buf);
2253   buf = NULL;
2254
2255   do {
2256     ret = gst_deinterlace_output_frame (self, FALSE);
2257   } while (!self->need_more && self->history_count > 0 && ret == GST_FLOW_OK);
2258
2259   return ret;
2260 }
2261
2262 static gboolean
2263 gst_deinterlace_acceptcaps (GstDeinterlace * self, GstPad * pad, GstCaps * caps)
2264 {
2265   gboolean ret;
2266   GstCaps *ourcaps;
2267
2268   /* In AUTO/DISABLED mode we accept everything that is compatible with
2269    * our template caps. In INTERLACED mode we force deinterlacing, meaning
2270    * we can only possibly support the deinterlace caps.
2271    * In AUTO_STRICT mode we accept all progressive formats, but only those
2272    * interlaced format that we can actually deinterlace */
2273   if (self->mode == GST_DEINTERLACE_MODE_DISABLED
2274       || self->mode == GST_DEINTERLACE_MODE_AUTO) {
2275     ourcaps = gst_pad_get_pad_template_caps (pad);
2276     ret = gst_caps_is_subset (caps, ourcaps);
2277     gst_caps_unref (ourcaps);
2278   } else if (self->mode == GST_DEINTERLACE_MODE_INTERLACED) {
2279     ourcaps = gst_static_caps_get (&deinterlace_caps);
2280     ret = gst_caps_is_subset (caps, ourcaps);
2281     gst_caps_unref (ourcaps);
2282   } else if (self->mode == GST_DEINTERLACE_MODE_AUTO_STRICT) {
2283     ourcaps = gst_static_caps_get (&progressive_caps);
2284     ret = gst_caps_is_subset (caps, ourcaps);
2285     gst_caps_unref (ourcaps);
2286
2287     if (!ret) {
2288       ourcaps = gst_static_caps_get (&deinterlace_caps);
2289       ret = gst_caps_is_subset (caps, ourcaps);
2290       gst_caps_unref (ourcaps);
2291     }
2292   } else {
2293     g_assert_not_reached ();
2294   }
2295
2296   GST_DEBUG_OBJECT (pad, "accept-caps result:%d for caps %" GST_PTR_FORMAT,
2297       ret, caps);
2298
2299   return ret;
2300 }
2301
2302 static gboolean
2303 gst_deinterlace_fraction_double (gint * n_out, gint * d_out, gboolean half)
2304 {
2305   gint n, d, gcd;
2306
2307   n = *n_out;
2308   d = *d_out;
2309
2310   if (d == 0)
2311     return FALSE;
2312
2313   if (n == 0)
2314     return TRUE;
2315
2316   gcd = gst_util_greatest_common_divisor (n, d);
2317   n /= gcd;
2318   d /= gcd;
2319
2320   if (half) {
2321     if (G_MAXINT / 2 >= ABS (d)) {
2322       d *= 2;
2323     } else if (n >= 2 && n != G_MAXINT) {
2324       n /= 2;
2325     } else {
2326       d = G_MAXINT;
2327     }
2328   } else {
2329     if (G_MAXINT / 2 >= ABS (n)) {
2330       n *= 2;
2331     } else if (d >= 2 && d != G_MAXINT) {
2332       d /= 2;
2333     } else {
2334       n = G_MAXINT;
2335     }
2336   }
2337
2338   *n_out = n;
2339   *d_out = d;
2340
2341   return TRUE;
2342 }
2343
2344 static GstCaps *
2345 gst_deinterlace_caps_double_framerate (GstCaps * caps, gboolean half)
2346 {
2347   guint len;
2348
2349   for (len = gst_caps_get_size (caps); len > 0; len--) {
2350     GstStructure *s = gst_caps_get_structure (caps, len - 1);
2351     const GValue *val;
2352
2353     val = gst_structure_get_value (s, "framerate");
2354     if (!val)
2355       continue;
2356
2357     if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) {
2358       gint n, d;
2359
2360       n = gst_value_get_fraction_numerator (val);
2361       d = gst_value_get_fraction_denominator (val);
2362
2363       if (!gst_deinterlace_fraction_double (&n, &d, half)) {
2364         gst_caps_remove_structure (caps, len - 1);
2365         continue;
2366       }
2367
2368       gst_structure_set (s, "framerate", GST_TYPE_FRACTION, n, d, NULL);
2369     } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) {
2370       const GValue *min, *max;
2371       GValue nrange = { 0, }, nmin = {
2372       0,}, nmax = {
2373       0,};
2374       gint n, d;
2375
2376       g_value_init (&nrange, GST_TYPE_FRACTION_RANGE);
2377       g_value_init (&nmin, GST_TYPE_FRACTION);
2378       g_value_init (&nmax, GST_TYPE_FRACTION);
2379
2380       min = gst_value_get_fraction_range_min (val);
2381       max = gst_value_get_fraction_range_max (val);
2382
2383       n = gst_value_get_fraction_numerator (min);
2384       d = gst_value_get_fraction_denominator (min);
2385
2386       if (!gst_deinterlace_fraction_double (&n, &d, half)) {
2387         g_value_unset (&nrange);
2388         g_value_unset (&nmax);
2389         g_value_unset (&nmin);
2390         gst_caps_remove_structure (caps, len - 1);
2391         continue;
2392       }
2393
2394       gst_value_set_fraction (&nmin, n, d);
2395
2396       n = gst_value_get_fraction_numerator (max);
2397       d = gst_value_get_fraction_denominator (max);
2398
2399       if (!gst_deinterlace_fraction_double (&n, &d, half)) {
2400         g_value_unset (&nrange);
2401         g_value_unset (&nmax);
2402         g_value_unset (&nmin);
2403         gst_caps_remove_structure (caps, len - 1);
2404         continue;
2405       }
2406
2407       gst_value_set_fraction (&nmax, n, d);
2408       gst_value_set_fraction_range (&nrange, &nmin, &nmax);
2409
2410       gst_structure_take_value (s, "framerate", &nrange);
2411
2412       g_value_unset (&nmin);
2413       g_value_unset (&nmax);
2414     } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) {
2415       const GValue *lval;
2416       GValue nlist = { 0, };
2417       GValue nval = { 0, };
2418       gint i;
2419
2420       g_value_init (&nlist, GST_TYPE_LIST);
2421       for (i = gst_value_list_get_size (val); i > 0; i--) {
2422         gint n, d;
2423
2424         lval = gst_value_list_get_value (val, i - 1);
2425
2426         if (G_VALUE_TYPE (lval) != GST_TYPE_FRACTION)
2427           continue;
2428
2429         n = gst_value_get_fraction_numerator (lval);
2430         d = gst_value_get_fraction_denominator (lval);
2431
2432         /* Double/Half the framerate but if this fails simply
2433          * skip this value from the list */
2434         if (!gst_deinterlace_fraction_double (&n, &d, half)) {
2435           continue;
2436         }
2437
2438         g_value_init (&nval, GST_TYPE_FRACTION);
2439
2440         gst_value_set_fraction (&nval, n, d);
2441         gst_value_list_append_and_take_value (&nlist, &nval);
2442       }
2443       gst_structure_take_value (s, "framerate", &nlist);
2444     }
2445   }
2446
2447   return caps;
2448 }
2449
2450 static GstCaps *
2451 gst_deinterlace_getcaps (GstDeinterlace * self, GstPad * pad, GstCaps * filter)
2452 {
2453   GstCaps *ret, *caps;
2454   GstPad *otherpad;
2455   gint len;
2456   GstCaps *ourcaps;
2457   GstCaps *peercaps;
2458   GstCaps *tmp, *tmp2;
2459
2460   otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad;
2461
2462   ourcaps = gst_pad_get_pad_template_caps (pad);
2463   peercaps = gst_pad_peer_query_caps (otherpad, NULL);
2464
2465   /* Filter any peercaps that are available with our template
2466    * to get started with the subset of caps we actually support */
2467   if (peercaps) {
2468     GST_DEBUG_OBJECT (pad, "Peer has caps %" GST_PTR_FORMAT, peercaps);
2469     caps = gst_caps_make_writable (gst_caps_intersect (ourcaps, peercaps));
2470     gst_caps_unref (peercaps);
2471     gst_caps_unref (ourcaps);
2472     peercaps = ourcaps = NULL;
2473   } else {
2474     caps = gst_caps_make_writable (ourcaps);
2475     ourcaps = NULL;
2476   }
2477
2478   GST_DEBUG_OBJECT (pad,
2479       "Transforming caps %" GST_PTR_FORMAT " with filter %" GST_PTR_FORMAT,
2480       caps, filter);
2481
2482   /* If deinterlacing is disabled, we just passthrough the
2483    * caps and everything */
2484   if (self->mode == GST_DEINTERLACE_MODE_DISABLED) {
2485     ret = caps;
2486     caps = NULL;
2487     goto done;
2488   }
2489
2490   /* If deinterlacing is enforced, we can only accept the
2491    * caps for which we can actually do deinterlacing */
2492   if (self->mode == GST_DEINTERLACE_MODE_INTERLACED) {
2493     tmp = gst_static_caps_get (&deinterlace_caps);
2494     ret = gst_caps_intersect_full (caps, tmp, GST_CAPS_INTERSECT_FIRST);
2495     gst_caps_unref (tmp);
2496     tmp = NULL;
2497     gst_caps_unref (caps);
2498     caps = NULL;
2499     goto done;
2500   }
2501
2502   g_assert (self->mode == GST_DEINTERLACE_MODE_AUTO
2503       || self->mode == GST_DEINTERLACE_MODE_AUTO_STRICT);
2504
2505   /* For the auto mode we have to do a bit more than that */
2506   ret = gst_caps_new_empty ();
2507
2508   /* We can accept any structure if
2509    * - they are progressive already
2510    *
2511    */
2512   tmp = gst_static_caps_get (&progressive_caps);
2513   tmp2 = gst_caps_intersect_full (caps, tmp, GST_CAPS_INTERSECT_FIRST);
2514   gst_caps_unref (tmp);
2515   tmp = NULL;
2516   ret = gst_caps_merge (ret, tmp2);
2517   tmp2 = NULL;
2518
2519   /* or
2520    * - they have sysmem caps features and a format for which we support
2521    *   deinterlacing
2522    * or
2523    * - they have ANY caps features, in which case we support it for
2524    *   sysmem caps features for formats we support
2525    *
2526    * NOTE: These are the caps where we actually would do deinterlacing
2527    * ourselves. If fields == ALL we would double the framerate so would
2528    * have to half the framerate constraints from downstream here
2529    */
2530   tmp = gst_static_caps_get (&deinterlace_caps);
2531   tmp2 = gst_caps_intersect_full (caps, tmp, GST_CAPS_INTERSECT_FIRST);
2532   gst_caps_unref (tmp);
2533   tmp = NULL;
2534
2535   for (len = gst_caps_get_size (tmp2); len > 0; len--) {
2536     GstStructure *s = gst_caps_get_structure (tmp2, len - 1);
2537
2538     if (pad == self->sinkpad)
2539       gst_structure_remove_field (s, "interlace-mode");
2540     else
2541       gst_structure_set (s, "interlace-mode", G_TYPE_STRING, "progressive",
2542           NULL);
2543   }
2544
2545   if (self->user_set_fields == GST_DEINTERLACE_ALL) {
2546     tmp2 = gst_deinterlace_caps_double_framerate (tmp2, (pad == self->sinkpad));
2547   }
2548   if (self->user_set_fields == GST_DEINTERLACE_FIELDS_AUTO) {
2549     tmp = gst_caps_copy (tmp2);
2550     tmp = gst_deinterlace_caps_double_framerate (tmp, (pad == self->sinkpad));
2551   }
2552
2553   ret = gst_caps_merge (ret, tmp2);
2554   tmp2 = NULL;
2555   if (tmp != NULL) {
2556     ret = gst_caps_merge (ret, tmp);
2557     tmp = NULL;
2558   }
2559
2560   /* or
2561    * - anything else in which case we would just passthrough again if we're
2562    *   only in AUTO and not AUTO_STRICT mode
2563    */
2564   if (self->mode == GST_DEINTERLACE_MODE_AUTO)
2565     ret = gst_caps_merge (ret, gst_caps_copy (caps));
2566
2567   gst_caps_unref (caps);
2568   caps = NULL;
2569
2570 done:
2571
2572   if (filter) {
2573     GstCaps *tmp;
2574
2575     GST_LOG_OBJECT (pad, "intersecting with %" GST_PTR_FORMAT, filter);
2576     tmp = gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
2577     gst_caps_unref (ret);
2578     ret = tmp;
2579   }
2580
2581   GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, ret);
2582
2583   return ret;
2584 }
2585
2586 /* takes ownership of the pool, allocator and query */
2587 static gboolean
2588 gst_deinterlace_set_allocation (GstDeinterlace * self,
2589     GstBufferPool * pool, GstAllocator * allocator,
2590     GstAllocationParams * params)
2591 {
2592   GstAllocator *oldalloc;
2593   GstBufferPool *oldpool;
2594
2595   GST_OBJECT_LOCK (self);
2596   oldpool = self->pool;
2597   self->pool = pool;
2598
2599   oldalloc = self->allocator;
2600   self->allocator = allocator;
2601
2602   if (params)
2603     self->params = *params;
2604   else
2605     gst_allocation_params_init (&self->params);
2606   GST_OBJECT_UNLOCK (self);
2607
2608   if (oldpool) {
2609     GST_DEBUG_OBJECT (self, "deactivating old pool %p", oldpool);
2610     gst_buffer_pool_set_active (oldpool, FALSE);
2611     gst_object_unref (oldpool);
2612   }
2613   if (oldalloc) {
2614     gst_object_unref (oldalloc);
2615   }
2616   if (pool) {
2617     GST_DEBUG_OBJECT (self, "activating new pool %p", pool);
2618     gst_buffer_pool_set_active (pool, TRUE);
2619   }
2620   return TRUE;
2621 }
2622
2623 static gboolean
2624 gst_deinterlace_do_bufferpool (GstDeinterlace * self, GstCaps * outcaps)
2625 {
2626   GstQuery *query;
2627   gboolean result = TRUE;
2628   GstBufferPool *pool;
2629   GstAllocator *allocator;
2630   GstAllocationParams params;
2631   GstStructure *config;
2632   guint size, min, max;
2633
2634   if (self->passthrough) {
2635     /* we are in passthrough, the input buffer is never copied and always passed
2636      * along. We never allocate an output buffer on the srcpad. What we do is
2637      * let the upstream element decide if it wants to use a bufferpool and
2638      * then we will proxy the downstream pool */
2639     GST_DEBUG_OBJECT (self, "we're passthough, delay bufferpool");
2640     gst_deinterlace_set_allocation (self, NULL, NULL, NULL);
2641     return TRUE;
2642   }
2643
2644   /* not passthrough, we need to allocate */
2645   /* find a pool for the negotiated caps now */
2646   GST_DEBUG_OBJECT (self, "doing allocation query");
2647   query = gst_query_new_allocation (outcaps, TRUE);
2648   if (!gst_pad_peer_query (self->srcpad, query)) {
2649     /* not a problem, just debug a little */
2650     GST_DEBUG_OBJECT (self, "peer ALLOCATION query failed");
2651   }
2652
2653   GST_DEBUG_OBJECT (self, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result,
2654       query);
2655
2656   /* we got configuration from our peer or the decide_allocation method,
2657    * parse them */
2658   if (gst_query_get_n_allocation_params (query) > 0) {
2659     gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
2660   } else {
2661     allocator = NULL;
2662     gst_allocation_params_init (&params);
2663   }
2664
2665   if (gst_query_get_n_allocation_pools (query) > 0)
2666     gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
2667   else {
2668     pool = NULL;
2669     size = GST_VIDEO_INFO_SIZE (&self->vinfo);
2670     min =
2671         MAX ((gst_deinterlace_method_get_fields_required (self->method) +
2672             1) / 2 + 1, 4);
2673     max = 0;
2674   }
2675
2676   if (pool == NULL) {
2677     /* no pool, we can make our own */
2678     GST_DEBUG_OBJECT (self, "no pool, making new pool");
2679     pool = gst_video_buffer_pool_new ();
2680   }
2681
2682   /* now configure */
2683   config = gst_buffer_pool_get_config (pool);
2684   gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
2685   gst_buffer_pool_config_set_allocator (config, allocator, &params);
2686   gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
2687   gst_buffer_pool_set_config (pool, config);
2688
2689   /* now store */
2690   result = gst_deinterlace_set_allocation (self, pool, allocator, &params);
2691
2692   gst_query_unref (query);
2693
2694   return result;
2695 }
2696
2697
2698 static gboolean
2699 gst_deinterlace_setcaps (GstDeinterlace * self, GstPad * pad, GstCaps * caps)
2700 {
2701   GstCaps *srccaps = NULL;
2702   GstVideoInterlaceMode interlacing_mode;
2703   gint fps_n, fps_d;
2704   GstCaps *peercaps, *current_caps;
2705
2706   gst_pad_check_reconfigure (self->srcpad);
2707
2708   if ((current_caps = gst_pad_get_current_caps (pad))) {
2709     if (gst_caps_is_equal (caps, current_caps)) {
2710       GST_DEBUG_OBJECT (pad, "Got same caps again, returning");
2711       gst_caps_unref (current_caps);
2712       return TRUE;
2713     }
2714     gst_deinterlace_reset_history (self, FALSE);
2715     gst_caps_unref (current_caps);
2716   }
2717   peercaps = gst_pad_peer_query_caps (self->srcpad, NULL);
2718
2719   /* Make sure the peer caps are compatible with the template caps */
2720   if (peercaps) {
2721     GstCaps *tmp = gst_pad_get_pad_template_caps (self->srcpad);
2722     GstCaps *tmp2 = gst_caps_intersect (peercaps, tmp);
2723
2724     gst_caps_unref (peercaps);
2725     peercaps = NULL;
2726     gst_caps_unref (tmp);
2727
2728     if (gst_caps_is_empty (tmp2)) {
2729       gst_caps_unref (tmp2);
2730       GST_ERROR_OBJECT (self, "Peer caps not compatible with template caps");
2731       goto invalid_caps;
2732     }
2733     peercaps = tmp2;
2734   }
2735
2736   if (self->locking != GST_DEINTERLACE_LOCKING_NONE) {
2737     if (self->low_latency == -1)
2738       self->low_latency = gst_deinterlace_get_latency (self);
2739
2740     if (self->pattern_lock) {
2741       /* refresh has been successful - we have a lock now */
2742       self->pattern_refresh = FALSE;
2743     } else {
2744       /* if we were not refreshing (!pattern_refresh) the caps have changed
2745        * so we need to refresh and we don't have a lock anymore
2746        * otherwise we have pattern_fresh and !pattern_lock anyway */
2747       self->pattern_refresh = TRUE;
2748       self->pattern_lock = FALSE;
2749     }
2750   }
2751
2752   if (!gst_video_info_from_caps (&self->vinfo, caps))
2753     goto invalid_caps;
2754
2755   fps_n = GST_VIDEO_INFO_FPS_N (&self->vinfo);
2756   fps_d = GST_VIDEO_INFO_FPS_D (&self->vinfo);
2757
2758   /* Update passthrough information */
2759   if (self->mode == GST_DEINTERLACE_MODE_DISABLED) {
2760     self->passthrough = TRUE;
2761     GST_DEBUG_OBJECT (self, "Passthrough because mode=disabled");
2762   } else if (self->mode == GST_DEINTERLACE_MODE_INTERLACED) {
2763     GstCaps *tmp = gst_static_caps_get (&deinterlace_caps);
2764
2765     if (!gst_caps_can_intersect (caps, tmp)) {
2766       gst_caps_unref (tmp);
2767       GST_ERROR_OBJECT (self, "Unsupported caps for mode=interlaced");
2768       goto invalid_caps;
2769     }
2770
2771     self->passthrough = FALSE;
2772     GST_DEBUG_OBJECT (self, "Not passthrough because mode=interlaced");
2773   } else if (self->mode == GST_DEINTERLACE_MODE_AUTO
2774       || self->mode == GST_DEINTERLACE_MODE_AUTO_STRICT) {
2775     GstCaps *tmp = gst_static_caps_get (&deinterlace_caps);
2776
2777     /* Already progressive? Passthrough */
2778     if (!GST_VIDEO_INFO_IS_INTERLACED (&self->vinfo)) {
2779       GST_DEBUG_OBJECT (self,
2780           "Passthrough because mode=auto and progressive caps");
2781       self->passthrough = TRUE;
2782     } else if (gst_caps_can_intersect (caps, tmp)) {
2783       if (peercaps) {
2784         GstCaps *allowed_caps;
2785         GstCaps *tmp2;
2786         GstStructure *s;
2787
2788         allowed_caps = gst_caps_intersect (peercaps, tmp);
2789
2790         tmp2 = gst_caps_copy (caps);
2791         s = gst_caps_get_structure (tmp2, 0);
2792         gst_structure_set (s, "interlace-mode", G_TYPE_STRING, "progressive",
2793             NULL);
2794         gst_structure_remove_field (s, "framerate");
2795
2796         /* Downstream does not support progressive caps but supports
2797          * the upstream caps, go passthrough.
2798          * TODO: We might want to check the framerate compatibility
2799          * of the caps too here
2800          */
2801         if (gst_caps_can_intersect (allowed_caps, caps)
2802             && !gst_caps_can_intersect (allowed_caps, tmp2)) {
2803           GST_DEBUG_OBJECT (self,
2804               "Passthrough because mode=auto, "
2805               "downstream does not support progressive caps and interlaced caps");
2806           self->passthrough = TRUE;
2807         } else {
2808           GST_DEBUG_OBJECT (self, "Not passthrough because mode=auto, "
2809               "downstream supports progressive caps and interlaced caps");
2810           self->passthrough = FALSE;
2811         }
2812
2813         gst_caps_unref (allowed_caps);
2814         gst_caps_unref (tmp2);
2815       } else {
2816         GST_DEBUG_OBJECT (self,
2817             "Not passthrough because mode=auto and interlaced caps");
2818         self->passthrough = FALSE;
2819       }
2820     } else {
2821       if (self->mode == GST_DEINTERLACE_MODE_AUTO) {
2822         GST_WARNING_OBJECT (self,
2823             "Passthrough because mode=auto and unsupported interlaced caps");
2824         self->passthrough = TRUE;
2825       } else {
2826         gst_caps_unref (tmp);
2827         GST_ERROR_OBJECT (self,
2828             "Unsupported interlaced caps in mode=auto-strict");
2829         goto invalid_caps;
2830       }
2831     }
2832
2833     gst_caps_unref (tmp);
2834   } else {
2835     g_assert_not_reached ();
2836   }
2837
2838   interlacing_mode = GST_VIDEO_INFO_INTERLACE_MODE (&self->vinfo);
2839
2840   if (!self->passthrough) {
2841     if (self->pattern_lock) {
2842       srccaps = gst_caps_copy (caps);
2843       if (self->pattern != -1
2844           && G_UNLIKELY (!gst_util_fraction_multiply (fps_n, fps_d,
2845                   telecine_patterns[self->pattern].ratio_n,
2846                   telecine_patterns[self->pattern].ratio_d, &fps_n, &fps_d)))
2847         GST_ERROR_OBJECT (self,
2848             "Multiplying the framerate by the telecine pattern ratio overflowed!");
2849       gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, fps_n,
2850           fps_d, NULL);
2851     } else if (self->locking == GST_DEINTERLACE_LOCKING_ACTIVE
2852         || self->low_latency == 0) {
2853       /* in high latency pattern locking mode if we don't have a pattern lock,
2854        * the sink pad caps are the best we know */
2855       srccaps = gst_caps_copy (caps);
2856     } else if (self->low_latency > 0
2857         && interlacing_mode == GST_VIDEO_INTERLACE_MODE_MIXED
2858         && self->pattern == -1) {
2859       /* for initial buffers of a telecine pattern, until there is a lock we
2860        * we output naïvely adjusted timestamps in low-latency pattern locking
2861        * mode */
2862       srccaps = gst_caps_copy (caps);
2863       gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
2864     } else if (self->user_set_fields == GST_DEINTERLACE_FIELDS_AUTO) {
2865       srccaps = gst_caps_copy (caps);
2866       if (peercaps) {
2867         gboolean can_be_tf = FALSE;
2868
2869         /* We already know that we are not passthrough: interlace-mode will
2870          * be progressive */
2871         gst_caps_set_simple (srccaps, "interlace-mode", G_TYPE_STRING,
2872             "progressive", NULL);
2873
2874         if (gst_caps_can_intersect (peercaps, srccaps)) {
2875           GST_DEBUG_OBJECT (self, "Can deinterlace top fields");
2876           can_be_tf = TRUE;
2877         }
2878         srccaps = gst_deinterlace_caps_double_framerate (srccaps, FALSE);
2879         if (!gst_caps_can_intersect (peercaps, srccaps)) {
2880           if (can_be_tf) {
2881             GST_DEBUG_OBJECT (self, "Will deinterlace top fields");
2882             gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, fps_n,
2883                 fps_d, NULL);
2884             self->fields = GST_DEINTERLACE_TF;
2885           } else {
2886             GST_DEBUG_OBJECT (self,
2887                 "Can't negotiate upstream and downstream caps");
2888             gst_caps_unref (srccaps);
2889             goto invalid_caps;
2890           }
2891         } else {
2892           GST_DEBUG_OBJECT (self, "Deinterlacing all fields");
2893           self->fields = GST_DEINTERLACE_ALL;
2894         }
2895       } else {
2896         GST_DEBUG_OBJECT (self,
2897             "No peer caps yet, falling back to deinterlacing all fields");
2898         self->fields = GST_DEINTERLACE_ALL;
2899         srccaps = gst_deinterlace_caps_double_framerate (srccaps, FALSE);
2900       }
2901     } else {
2902       self->fields = self->user_set_fields;
2903       srccaps = gst_caps_copy (caps);
2904       if (self->fields == GST_DEINTERLACE_ALL)
2905         srccaps = gst_deinterlace_caps_double_framerate (srccaps, FALSE);
2906     }
2907
2908     /* If not passthrough, we are going to output progressive content */
2909     gst_caps_set_simple (srccaps, "interlace-mode", G_TYPE_STRING,
2910         "progressive", NULL);
2911
2912     gst_deinterlace_set_method (self, self->method_id);
2913     gst_deinterlace_method_setup (self->method, &self->vinfo);
2914   } else {
2915     srccaps = gst_caps_ref (caps);
2916   }
2917
2918   if (fps_n != 0) {
2919     self->field_duration = gst_util_uint64_scale (GST_SECOND, fps_d, 2 * fps_n);
2920   } else {
2921     self->field_duration = 0;
2922   }
2923
2924   GST_DEBUG_OBJECT (pad, "Sink caps: %" GST_PTR_FORMAT, caps);
2925   GST_DEBUG_OBJECT (pad, "Src  caps: %" GST_PTR_FORMAT, srccaps);
2926
2927   if (!gst_pad_set_caps (self->srcpad, srccaps))
2928     goto set_caps_failed;
2929
2930   if (!gst_deinterlace_do_bufferpool (self, srccaps))
2931     goto no_bufferpool;
2932
2933   if (peercaps)
2934     gst_caps_unref (peercaps);
2935   gst_caps_unref (srccaps);
2936
2937   return TRUE;
2938
2939 invalid_caps:
2940   {
2941     if (peercaps)
2942       gst_caps_unref (peercaps);
2943     GST_ERROR_OBJECT (pad, "Invalid caps: %" GST_PTR_FORMAT, caps);
2944     gst_pad_mark_reconfigure (self->srcpad);
2945     return FALSE;
2946   }
2947 set_caps_failed:
2948   {
2949     GST_ERROR_OBJECT (pad, "Failed to set caps: %" GST_PTR_FORMAT, srccaps);
2950     if (peercaps)
2951       gst_caps_unref (peercaps);
2952     gst_caps_unref (srccaps);
2953     gst_pad_mark_reconfigure (self->srcpad);
2954     return FALSE;
2955   }
2956 no_bufferpool:
2957   {
2958     GST_ERROR_OBJECT (pad, "could not negotiate bufferpool");
2959     if (peercaps)
2960       gst_caps_unref (peercaps);
2961     gst_caps_unref (srccaps);
2962     gst_pad_mark_reconfigure (self->srcpad);
2963     return FALSE;
2964   }
2965 }
2966
2967 static gboolean
2968 gst_deinterlace_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
2969 {
2970   gboolean res = TRUE;
2971   GstDeinterlace *self = GST_DEINTERLACE (parent);
2972
2973   GST_LOG_OBJECT (pad, "received %s event: %" GST_PTR_FORMAT,
2974       GST_EVENT_TYPE_NAME (event), event);
2975
2976   switch (GST_EVENT_TYPE (event)) {
2977     case GST_EVENT_CAPS:
2978     {
2979       GstCaps *caps = NULL;
2980
2981       gst_event_parse_caps (event, &caps);
2982       res = gst_deinterlace_setcaps (self, pad, caps);
2983       gst_event_unref (event);
2984       break;
2985     }
2986     case GST_EVENT_SEGMENT:
2987     {
2988       const GstSegment *segment;
2989
2990       gst_event_parse_segment (event, &segment);
2991
2992       gst_deinterlace_reset_qos (self);
2993       gst_deinterlace_reset_history (self, FALSE);
2994
2995       if (segment->format == GST_FORMAT_TIME) {
2996         GST_DEBUG_OBJECT (pad,
2997             "Got SEGMENT event in TIME format, passing on (%"
2998             GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")",
2999             GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop));
3000         gst_segment_copy_into (segment, &self->segment);
3001       } else {
3002         GST_WARNING_OBJECT (pad, "Got SEGMENT event in %s format",
3003             gst_format_get_name (segment->format));
3004         gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
3005       }
3006
3007       res = gst_pad_push_event (self->srcpad, event);
3008       break;
3009     }
3010     case GST_EVENT_CUSTOM_DOWNSTREAM:{
3011       gboolean still_state;
3012
3013       if (gst_video_event_parse_still_frame (event, &still_state)) {
3014         GST_DEBUG_OBJECT (self, "Received still frame event, state %d",
3015             still_state);
3016
3017         if (still_state) {
3018           GstFlowReturn ret;
3019
3020           GST_DEBUG_OBJECT (self, "Handling still frame");
3021           self->still_frame_mode = TRUE;
3022           gst_deinterlace_reset_history (self, FALSE);
3023           if (self->last_buffer) {
3024             ret =
3025                 gst_pad_push (self->srcpad, gst_buffer_ref (self->last_buffer));
3026             GST_DEBUG_OBJECT (self, "Pushed still frame, result: %s",
3027                 gst_flow_get_name (ret));
3028           } else {
3029             GST_WARNING_OBJECT (self, "No pending buffer!");
3030           }
3031         } else {
3032           GST_DEBUG_OBJECT (self, "Ending still frames");
3033           self->still_frame_mode = FALSE;
3034         }
3035       }
3036
3037       res = gst_pad_push_event (self->srcpad, event);
3038       break;
3039     }
3040     case GST_EVENT_EOS:
3041       self->have_eos = TRUE;
3042       gst_deinterlace_reset_history (self, FALSE);
3043       res = gst_pad_push_event (self->srcpad, event);
3044       break;
3045
3046     case GST_EVENT_FLUSH_STOP:
3047       if (self->still_frame_mode) {
3048         GST_DEBUG_OBJECT (self, "Ending still frames");
3049         self->still_frame_mode = FALSE;
3050       }
3051       self->telecine_tc_warned = FALSE;
3052       gst_deinterlace_reset_qos (self);
3053       res = gst_pad_push_event (self->srcpad, event);
3054       gst_deinterlace_reset_history (self, TRUE);
3055       break;
3056
3057     default:
3058       res = gst_pad_event_default (pad, parent, event);
3059       break;
3060   }
3061
3062   return res;
3063 }
3064
3065 static gboolean
3066 gst_deinterlace_propose_allocation (GstDeinterlace * self, GstQuery * query)
3067 {
3068   GstBufferPool *pool;
3069   GstCaps *caps;
3070   GstVideoInfo info;
3071   guint size;
3072   GstStructure *config;
3073
3074   gst_query_parse_allocation (query, &caps, NULL);
3075
3076   if (caps == NULL)
3077     return FALSE;
3078
3079   if (!gst_video_info_from_caps (&info, caps))
3080     return FALSE;
3081
3082   size = GST_VIDEO_INFO_SIZE (&info);
3083
3084   pool = gst_video_buffer_pool_new ();
3085
3086   gst_query_add_allocation_pool (query, pool, size, 0, 0);
3087
3088   config = gst_buffer_pool_get_config (pool);
3089   gst_buffer_pool_config_set_params (config, caps, size,
3090       (gst_deinterlace_method_get_fields_required (self->method) + 1) / 2 + 1,
3091       0);
3092   gst_buffer_pool_set_config (pool, config);
3093
3094   gst_object_unref (pool);
3095   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
3096
3097   return TRUE;
3098 }
3099
3100 static gboolean
3101 gst_deinterlace_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
3102 {
3103   GstDeinterlace *self = GST_DEINTERLACE (parent);
3104   gboolean res = FALSE;
3105
3106   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
3107
3108   switch (GST_QUERY_TYPE (query)) {
3109     case GST_QUERY_CAPS:
3110     {
3111       GstCaps *filter, *caps;
3112
3113       gst_query_parse_caps (query, &filter);
3114       caps = gst_deinterlace_getcaps (self, pad, filter);
3115       gst_query_set_caps_result (query, caps);
3116       gst_caps_unref (caps);
3117       res = TRUE;
3118       break;
3119     }
3120     case GST_QUERY_ACCEPT_CAPS:
3121     {
3122       GstCaps *caps;
3123       gboolean ret;
3124
3125       gst_query_parse_accept_caps (query, &caps);
3126       ret = gst_deinterlace_acceptcaps (self, pad, caps);
3127       gst_query_set_accept_caps_result (query, ret);
3128       res = TRUE;
3129       break;
3130     }
3131     case GST_QUERY_ALLOCATION:
3132       if (self->passthrough)
3133         res = gst_pad_peer_query (self->srcpad, query);
3134       else
3135         res = gst_deinterlace_propose_allocation (self, query);
3136       break;
3137     default:
3138       res = gst_pad_query_default (pad, parent, query);
3139       break;
3140   }
3141   return res;
3142 }
3143
3144 static GstStateChangeReturn
3145 gst_deinterlace_change_state (GstElement * element, GstStateChange transition)
3146 {
3147   GstStateChangeReturn ret;
3148   GstDeinterlace *self = GST_DEINTERLACE (element);
3149
3150   switch (transition) {
3151     case GST_STATE_CHANGE_NULL_TO_READY:
3152       break;
3153     case GST_STATE_CHANGE_READY_TO_PAUSED:
3154       break;
3155     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3156       break;
3157     default:
3158       break;
3159   }
3160
3161   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3162   if (ret != GST_STATE_CHANGE_SUCCESS)
3163     return ret;
3164
3165   switch (transition) {
3166     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3167       break;
3168     case GST_STATE_CHANGE_PAUSED_TO_READY:
3169       gst_deinterlace_reset (self);
3170       break;
3171     case GST_STATE_CHANGE_READY_TO_NULL:
3172     default:
3173       break;
3174   }
3175
3176   return ret;
3177 }
3178
3179 static gboolean
3180 gst_deinterlace_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
3181 {
3182   GstDeinterlace *self = GST_DEINTERLACE (parent);
3183   gboolean res;
3184
3185   GST_DEBUG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
3186
3187   switch (GST_EVENT_TYPE (event)) {
3188     case GST_EVENT_QOS:{
3189       GstClockTimeDiff diff;
3190       GstClockTime timestamp;
3191       GstQOSType type;
3192       gdouble proportion;
3193
3194       gst_event_parse_qos (event, &type, &proportion, &diff, &timestamp);
3195
3196       gst_deinterlace_update_qos (self, proportion, diff, timestamp);
3197     }
3198       /* fall through */
3199     default:
3200       res = gst_pad_event_default (pad, parent, event);
3201       break;
3202   }
3203
3204   return res;
3205 }
3206
3207 static gboolean
3208 gst_deinterlace_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
3209 {
3210   GstDeinterlace *self = GST_DEINTERLACE (parent);
3211   gboolean res = FALSE;
3212
3213   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
3214
3215   switch (GST_QUERY_TYPE (query)) {
3216     case GST_QUERY_LATENCY:
3217       if (!self->passthrough) {
3218         GstClockTime min, max;
3219         gboolean live;
3220         GstPad *peer;
3221
3222         if ((peer = gst_pad_get_peer (self->sinkpad))) {
3223           if ((res = gst_pad_query (peer, query))) {
3224             GstClockTime latency;
3225             gint fields_required = 0;
3226             gint method_latency = 0;
3227
3228             if (self->method) {
3229               fields_required =
3230                   gst_deinterlace_method_get_fields_required (self->method);
3231               method_latency =
3232                   gst_deinterlace_method_get_latency (self->method);
3233             }
3234
3235             gst_query_parse_latency (query, &live, &min, &max);
3236
3237             GST_DEBUG_OBJECT (self, "Peer latency: min %"
3238                 GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
3239                 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
3240
3241             /* add our own latency */
3242             latency = (fields_required + method_latency) * self->field_duration;
3243
3244             GST_DEBUG_OBJECT (self, "Our latency: min %" GST_TIME_FORMAT
3245                 ", max %" GST_TIME_FORMAT,
3246                 GST_TIME_ARGS (latency), GST_TIME_ARGS (latency));
3247
3248             min += latency;
3249             if (max != GST_CLOCK_TIME_NONE)
3250               max += latency;
3251
3252             GST_DEBUG_OBJECT (self, "Calculated total latency : min %"
3253                 GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
3254                 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
3255
3256             gst_query_set_latency (query, live, min, max);
3257           }
3258           gst_object_unref (peer);
3259         } else {
3260           res = FALSE;
3261         }
3262         break;
3263       }
3264     default:
3265       res = gst_pad_query_default (pad, parent, query);
3266       break;
3267   }
3268
3269   return res;
3270 }
3271
3272 static gboolean
3273 plugin_init (GstPlugin * plugin)
3274 {
3275   GST_DEBUG_CATEGORY_INIT (deinterlace_debug, "deinterlace", 0, "Deinterlacer");
3276
3277 #if HAVE_ORC
3278   orc_init ();
3279 #endif
3280
3281   if (!gst_element_register (plugin, "deinterlace", GST_RANK_NONE,
3282           GST_TYPE_DEINTERLACE)) {
3283     return FALSE;
3284   }
3285
3286   return TRUE;
3287 }
3288
3289 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
3290     GST_VERSION_MINOR,
3291     deinterlace,
3292     "Deinterlacer", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
3293     GST_PACKAGE_ORIGIN);