deinterlace: Timecode pass-through
[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 void
764 gst_deinterlace_reset_history (GstDeinterlace * self, gboolean drop_all)
765 {
766   gint i;
767
768   if (!drop_all) {
769     GST_DEBUG_OBJECT (self, "Flushing history (count %d)", self->history_count);
770     while (self->history_count > 0) {
771       if (gst_deinterlace_output_frame (self, TRUE) != GST_FLOW_OK) {
772         /* Encountered error, or flushing -> skip and drop all remaining */
773         drop_all = TRUE;
774         break;
775       }
776     }
777   }
778   if (drop_all) {
779     GST_DEBUG_OBJECT (self, "Resetting history (count %d)",
780         self->history_count);
781
782     for (i = 0; i < self->history_count; i++) {
783       if (self->field_history[i].frame) {
784         gst_video_frame_unmap_and_free (self->field_history[i].frame);
785         self->field_history[i].frame = NULL;
786         if (self->field_history[i].tc) {
787           gst_video_time_code_free (self->field_history[i].tc);
788         }
789       }
790     }
791   }
792   memset (self->field_history, 0,
793       GST_DEINTERLACE_MAX_FIELD_HISTORY * sizeof (GstDeinterlaceField));
794   self->history_count = 0;
795   memset (self->buf_states, 0,
796       GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY *
797       sizeof (GstDeinterlaceBufferState));
798   self->state_count = 0;
799   self->pattern_lock = FALSE;
800   self->pattern_refresh = TRUE;
801   self->cur_field_idx = -1;
802
803   if (!self->still_frame_mode && self->last_buffer) {
804     gst_buffer_unref (self->last_buffer);
805     self->last_buffer = NULL;
806   }
807 }
808
809 static void
810 gst_deinterlace_reset (GstDeinterlace * self)
811 {
812   GST_DEBUG_OBJECT (self, "Resetting internal state");
813
814   gst_video_info_init (&self->vinfo);
815
816   self->passthrough = FALSE;
817
818   self->reconfigure = FALSE;
819   if ((gint) self->new_mode != -1)
820     self->mode = self->new_mode;
821   if ((gint) self->new_fields != -1)
822     self->user_set_fields = self->new_fields;
823   self->new_mode = -1;
824   self->new_fields = -1;
825
826   gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
827
828   if (self->request_caps)
829     gst_caps_unref (self->request_caps);
830   self->request_caps = NULL;
831
832   gst_deinterlace_reset_history (self, TRUE);
833
834   gst_deinterlace_reset_qos (self);
835
836   self->need_more = FALSE;
837   self->have_eos = FALSE;
838
839   self->discont = TRUE;
840   self->telecine_tc_warned = FALSE;
841
842   gst_deinterlace_set_allocation (self, NULL, NULL, NULL);
843 }
844
845 static void
846 gst_deinterlace_set_property (GObject * object, guint prop_id,
847     const GValue * value, GParamSpec * pspec)
848 {
849   GstDeinterlace *self;
850
851   self = GST_DEINTERLACE (object);
852
853   switch (prop_id) {
854     case PROP_MODE:{
855       gint new_mode;
856
857       GST_OBJECT_LOCK (self);
858       new_mode = g_value_get_enum (value);
859       if (self->mode != new_mode && gst_pad_has_current_caps (self->srcpad)) {
860         self->reconfigure = TRUE;
861         self->new_mode = new_mode;
862       } else {
863         self->mode = new_mode;
864       }
865       GST_OBJECT_UNLOCK (self);
866       break;
867     }
868     case PROP_METHOD:
869       self->user_set_method_id = g_value_get_enum (value);
870       gst_deinterlace_set_method (self, self->user_set_method_id);
871       break;
872     case PROP_FIELDS:{
873       gint new_fields;
874
875       GST_OBJECT_LOCK (self);
876       new_fields = g_value_get_enum (value);
877       if (self->user_set_fields != new_fields
878           && gst_pad_has_current_caps (self->srcpad)) {
879         self->reconfigure = TRUE;
880         self->new_fields = new_fields;
881       } else {
882         self->user_set_fields = new_fields;
883       }
884       GST_OBJECT_UNLOCK (self);
885       break;
886     }
887     case PROP_FIELD_LAYOUT:
888       self->field_layout = g_value_get_enum (value);
889       break;
890     case PROP_LOCKING:
891       self->locking = g_value_get_enum (value);
892       break;
893     case PROP_IGNORE_OBSCURE:
894       self->ignore_obscure = g_value_get_boolean (value);
895       break;
896     case PROP_DROP_ORPHANS:
897       self->drop_orphans = g_value_get_boolean (value);
898       break;
899     default:
900       G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
901   }
902
903 }
904
905 static void
906 gst_deinterlace_get_property (GObject * object, guint prop_id,
907     GValue * value, GParamSpec * pspec)
908 {
909   GstDeinterlace *self;
910
911   self = GST_DEINTERLACE (object);
912
913   switch (prop_id) {
914     case PROP_MODE:
915       g_value_set_enum (value, self->mode);
916       break;
917     case PROP_METHOD:
918       g_value_set_enum (value, self->user_set_method_id);
919       break;
920     case PROP_FIELDS:
921       g_value_set_enum (value, self->user_set_fields);
922       break;
923     case PROP_FIELD_LAYOUT:
924       g_value_set_enum (value, self->field_layout);
925       break;
926     case PROP_LOCKING:
927       g_value_set_enum (value, self->locking);
928       break;
929     case PROP_IGNORE_OBSCURE:
930       g_value_set_boolean (value, self->ignore_obscure);
931       break;
932     case PROP_DROP_ORPHANS:
933       g_value_set_boolean (value, self->drop_orphans);
934       break;
935     default:
936       G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
937   }
938 }
939
940 static void
941 gst_deinterlace_finalize (GObject * object)
942 {
943   GstDeinterlace *self = GST_DEINTERLACE (object);
944
945   gst_deinterlace_reset (self);
946
947   if (self->method) {
948     gst_object_unparent (GST_OBJECT (self->method));
949     self->method = NULL;
950   }
951
952   G_OBJECT_CLASS (parent_class)->finalize (object);
953 }
954
955 static void
956 gst_deinterlace_update_pattern_timestamps (GstDeinterlace * self)
957 {
958   gint state_idx;
959   if (self->low_latency) {
960     /* in low-latency mode the buffer state history contains old buffer
961      * states as well as the current one and perhaps some future ones.
962      * the current buffer's state is given by the number of field pairs
963      * rounded up, minus 1. the below is equivalent */
964     state_idx = (self->history_count - 1) >> 1;
965   } else {
966     /* in high-latency mode state_count - 1 is the current buffer's state */
967     state_idx = self->state_count - 1;
968   }
969
970   self->pattern_base_ts = self->buf_states[state_idx].timestamp;
971   if (self->buf_states[state_idx].state != GST_RFF) {
972     self->pattern_buf_dur =
973         (self->buf_states[state_idx].duration *
974         telecine_patterns[self->pattern].ratio_d) /
975         telecine_patterns[self->pattern].ratio_n;
976   } else {
977     self->pattern_buf_dur =
978         (self->buf_states[state_idx].duration *
979         telecine_patterns[self->pattern].ratio_d * 2) /
980         (telecine_patterns[self->pattern].ratio_n * 3);
981   }
982   GST_DEBUG_OBJECT (self,
983       "Starting a new pattern repeat with base ts %" GST_TIME_FORMAT
984       " and dur %" GST_TIME_FORMAT, GST_TIME_ARGS (self->pattern_base_ts),
985       GST_TIME_ARGS (self->pattern_buf_dur));
986 }
987
988 static GstVideoFrame *
989 gst_deinterlace_pop_history (GstDeinterlace * self)
990 {
991   GstVideoFrame *frame;
992
993   g_return_val_if_fail (self->history_count > 0, NULL);
994
995   GST_DEBUG_OBJECT (self, "Pop last history frame -- current history size %d",
996       self->history_count);
997
998   frame = self->field_history[self->history_count - 1].frame;
999
1000   self->history_count--;
1001   if (self->locking != GST_DEINTERLACE_LOCKING_NONE && (!self->history_count
1002           || GST_VIDEO_FRAME_PLANE_DATA (frame, 0) !=
1003           GST_VIDEO_FRAME_PLANE_DATA (self->field_history[self->history_count -
1004                   1].frame, 0))) {
1005     if (!self->low_latency)
1006       self->state_count--;
1007     if (self->pattern_lock) {
1008       self->pattern_count++;
1009       if (self->pattern != -1
1010           && self->pattern_count >= telecine_patterns[self->pattern].length) {
1011         self->pattern_count = 0;
1012         self->output_count = 0;
1013       }
1014     }
1015   }
1016
1017   GST_DEBUG_OBJECT (self, "Returning frame: %p %" GST_TIME_FORMAT
1018       " with duration %" GST_TIME_FORMAT " and size %" G_GSIZE_FORMAT, frame,
1019       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (frame->buffer)),
1020       GST_TIME_ARGS (GST_BUFFER_DURATION (frame->buffer)),
1021       GST_VIDEO_FRAME_SIZE (frame));
1022
1023   return frame;
1024 }
1025
1026 static void
1027 gst_deinterlace_get_buffer_state (GstDeinterlace * self, GstVideoFrame * frame,
1028     guint8 * state, GstVideoInterlaceMode * i_mode)
1029 {
1030   GstVideoInterlaceMode interlacing_mode;
1031
1032   if (!(i_mode || state))
1033     return;
1034
1035   interlacing_mode = GST_VIDEO_INFO_INTERLACE_MODE (&frame->info);
1036   if (self->mode == GST_DEINTERLACE_MODE_INTERLACED)
1037     interlacing_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
1038
1039   if (state) {
1040     if (interlacing_mode == GST_VIDEO_INTERLACE_MODE_MIXED) {
1041       if (GST_VIDEO_FRAME_IS_RFF (frame)) {
1042         *state = GST_DEINTERLACE_BUFFER_STATE_RFF;
1043       } else if (GST_VIDEO_FRAME_IS_ONEFIELD (frame)) {
1044         /* tc top if tff, tc bottom otherwise */
1045         if (GST_VIDEO_FRAME_IS_TFF (frame)) {
1046           *state = GST_DEINTERLACE_BUFFER_STATE_TC_T;
1047         } else {
1048           *state = GST_DEINTERLACE_BUFFER_STATE_TC_B;
1049         }
1050       } else if (GST_VIDEO_FRAME_IS_INTERLACED (frame)) {
1051         *state = GST_DEINTERLACE_BUFFER_STATE_TC_M;
1052       } else {
1053         *state = GST_DEINTERLACE_BUFFER_STATE_TC_P;
1054       }
1055     } else {
1056       if (interlacing_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED) {
1057         *state = GST_DEINTERLACE_BUFFER_STATE_I;
1058       } else {
1059         *state = GST_DEINTERLACE_BUFFER_STATE_P;
1060       }
1061     }
1062   }
1063
1064   if (i_mode)
1065     *i_mode = interlacing_mode;
1066 }
1067
1068 #define STATE_TO_STRING(s) ((s) == GST_DEINTERLACE_BUFFER_STATE_P ? "P" : \
1069   (s) == GST_DEINTERLACE_BUFFER_STATE_I ? "I" : \
1070   (s) == GST_DEINTERLACE_BUFFER_STATE_TC_B ? "B" : \
1071   (s) == GST_DEINTERLACE_BUFFER_STATE_TC_T ? "T" : \
1072   (s) == GST_DEINTERLACE_BUFFER_STATE_TC_P ? "TCP" : \
1073   (s) == GST_DEINTERLACE_BUFFER_STATE_TC_M ? "TCM" : "RFF")
1074
1075 #define MODE_TO_STRING(m) ((m) == GST_VIDEO_INTERLACE_MODE_MIXED ? "MIXED" : \
1076   (m) == GST_VIDEO_INTERLACE_MODE_INTERLEAVED ? "I" : \
1077   (m) == GST_VIDEO_INTERLACE_MODE_FIELDS ? "FIELDS" : "P")
1078
1079 static void
1080 gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer)
1081 {
1082   int i = 1;
1083   GstDeinterlaceFieldLayout field_layout = self->field_layout;
1084   gboolean tff;
1085   gboolean onefield;
1086   GstVideoFrame *frame = NULL;
1087   GstVideoFrame *field1, *field2 = NULL;
1088   guint fields_to_push;
1089   guint field1_flags, field2_flags;
1090   GstVideoInterlaceMode interlacing_mode;
1091   guint8 buf_state;
1092
1093   /* we will only read from this buffer and write into fresh output buffers
1094    * if this is not the case, change the map flags as appropriate
1095    */
1096   frame = gst_video_frame_new_and_map (&self->vinfo, buffer, GST_MAP_READ);
1097
1098   tff = GST_VIDEO_FRAME_IS_TFF (frame);
1099   onefield = GST_VIDEO_FRAME_IS_ONEFIELD (frame);
1100   fields_to_push = (onefield) ? 1 : 2;
1101
1102   g_return_if_fail (self->history_count <
1103       GST_DEINTERLACE_MAX_FIELD_HISTORY - fields_to_push);
1104
1105   gst_deinterlace_get_buffer_state (self, frame, &buf_state, &interlacing_mode);
1106
1107   GST_DEBUG_OBJECT (self,
1108       "Pushing new frame as %d fields to the history (count before %d): ptr %p at %"
1109       GST_TIME_FORMAT " with duration %" GST_TIME_FORMAT
1110       ", size %" G_GSIZE_FORMAT ", state %s, interlacing mode %s",
1111       fields_to_push, self->history_count, frame,
1112       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1113       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
1114       gst_buffer_get_size (buffer),
1115       STATE_TO_STRING (buf_state), MODE_TO_STRING (interlacing_mode));
1116
1117   /* move up for new state */
1118   memmove (&self->buf_states[1], &self->buf_states[0],
1119       (GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY - 1) *
1120       sizeof (GstDeinterlaceBufferState));
1121   self->buf_states[0].state = buf_state;
1122   self->buf_states[0].timestamp = GST_BUFFER_TIMESTAMP (buffer);
1123   self->buf_states[0].duration = GST_BUFFER_DURATION (buffer);
1124   if (self->state_count < GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY)
1125     self->state_count++;
1126
1127   for (i = GST_DEINTERLACE_MAX_FIELD_HISTORY - 1; i >= fields_to_push; i--) {
1128     self->field_history[i].frame =
1129         self->field_history[i - fields_to_push].frame;
1130     self->field_history[i].flags =
1131         self->field_history[i - fields_to_push].flags;
1132     if (self->field_history[i].tc)
1133       gst_video_time_code_free (self->field_history[i].tc);
1134     if (self->field_history[i - fields_to_push].tc) {
1135       self->field_history[i].tc =
1136           gst_video_time_code_copy (self->field_history[i - fields_to_push].tc);
1137     } else {
1138       self->field_history[i].tc = NULL;
1139     }
1140   }
1141
1142   if (field_layout == GST_DEINTERLACE_LAYOUT_AUTO) {
1143     if (!GST_VIDEO_INFO_IS_INTERLACED (&self->vinfo)) {
1144       GST_WARNING_OBJECT (self, "Can't detect field layout -- assuming TFF");
1145       field_layout = GST_DEINTERLACE_LAYOUT_TFF;
1146     } else if (tff) {
1147       field_layout = GST_DEINTERLACE_LAYOUT_TFF;
1148     } else {
1149       field_layout = GST_DEINTERLACE_LAYOUT_BFF;
1150     }
1151   }
1152
1153   field1 = frame;
1154   field2 = gst_video_frame_new_and_map (&self->vinfo, buffer, GST_MAP_READ);
1155   if (field_layout == GST_DEINTERLACE_LAYOUT_TFF) {
1156     GST_DEBUG_OBJECT (self, "Top field first");
1157     field1_flags = PICTURE_INTERLACED_TOP;
1158     field2_flags = PICTURE_INTERLACED_BOTTOM;
1159   } else {
1160     GST_DEBUG_OBJECT (self, "Bottom field first");
1161     field1_flags = PICTURE_INTERLACED_BOTTOM;
1162     field2_flags = PICTURE_INTERLACED_TOP;
1163   }
1164
1165   /* Swap for reverse playback */
1166   if (self->segment.rate < 0) {
1167     field1_flags = field1_flags ^ field2_flags;
1168     field2_flags = field1_flags ^ field2_flags;
1169     field1_flags = field1_flags ^ field2_flags;
1170   }
1171
1172   if (!onefield) {
1173     GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (buffer);
1174
1175     GST_DEBUG_OBJECT (self, "Two fields");
1176     self->field_history[1].frame = field1;
1177     self->field_history[1].flags = field1_flags;
1178
1179     self->field_history[0].frame = field2;
1180     self->field_history[0].flags = field2_flags;
1181
1182     if (meta) {
1183       self->field_history[0].tc = gst_video_time_code_copy (&meta->tc);
1184       self->field_history[0].tc->config.flags &=
1185           ~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
1186       self->field_history[1].tc = gst_video_time_code_copy (&meta->tc);
1187       self->field_history[1].tc->config.flags &=
1188           ~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
1189     }
1190   } else {                      /* onefield */
1191     GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (buffer);
1192
1193     GST_DEBUG_OBJECT (self, "One field");
1194     self->field_history[0].frame = field1;
1195     self->field_history[0].flags = field1_flags;
1196     if (meta) {
1197       self->field_history[0].tc = gst_video_time_code_copy (&meta->tc);
1198       self->field_history[0].tc->config.flags &=
1199           ~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
1200     }
1201     gst_video_frame_unmap_and_free (field2);
1202   }
1203
1204   /* we can manage the buffer ref count using the maps from here on */
1205   gst_buffer_unref (buffer);
1206
1207   self->history_count += fields_to_push;
1208   self->cur_field_idx += fields_to_push;
1209
1210   GST_DEBUG_OBJECT (self, "Pushed buffer -- current history size %d, index %d",
1211       self->history_count, self->cur_field_idx);
1212
1213   if (self->last_buffer)
1214     gst_buffer_unref (self->last_buffer);
1215   self->last_buffer = gst_buffer_ref (buffer);
1216 }
1217
1218 static void
1219 gst_deinterlace_update_qos (GstDeinterlace * self, gdouble proportion,
1220     GstClockTimeDiff diff, GstClockTime timestamp)
1221 {
1222   GST_DEBUG_OBJECT (self,
1223       "Updating QoS: proportion %lf, diff %" GST_STIME_FORMAT ", timestamp %"
1224       GST_TIME_FORMAT, proportion, GST_STIME_ARGS (diff),
1225       GST_TIME_ARGS (timestamp));
1226
1227   GST_OBJECT_LOCK (self);
1228   self->proportion = proportion;
1229   if (G_LIKELY (timestamp != GST_CLOCK_TIME_NONE)) {
1230     if (G_UNLIKELY (diff > 0))
1231       self->earliest_time =
1232           timestamp + 2 * diff + ((self->fields ==
1233               GST_DEINTERLACE_ALL) ? self->field_duration : 2 *
1234           self->field_duration);
1235     else
1236       self->earliest_time = timestamp + diff;
1237   } else {
1238     self->earliest_time = GST_CLOCK_TIME_NONE;
1239   }
1240   GST_OBJECT_UNLOCK (self);
1241 }
1242
1243 static void
1244 gst_deinterlace_reset_qos (GstDeinterlace * self)
1245 {
1246   gst_deinterlace_update_qos (self, 0.5, 0, GST_CLOCK_TIME_NONE);
1247   self->processed = 0;
1248   self->dropped = 0;
1249 }
1250
1251 static void
1252 gst_deinterlace_read_qos (GstDeinterlace * self, gdouble * proportion,
1253     GstClockTime * time)
1254 {
1255   GST_OBJECT_LOCK (self);
1256   *proportion = self->proportion;
1257   *time = self->earliest_time;
1258   GST_OBJECT_UNLOCK (self);
1259 }
1260
1261 /* Perform qos calculations before processing the next frame. Returns TRUE if
1262  * the frame should be processed, FALSE if the frame can be dropped entirely */
1263 static gboolean
1264 gst_deinterlace_do_qos (GstDeinterlace * self, const GstBuffer * buffer)
1265 {
1266   GstClockTime qostime, earliest_time;
1267   GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
1268   gdouble proportion;
1269
1270   /* no timestamp, can't do QoS => process frame */
1271   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) {
1272     GST_LOG_OBJECT (self, "invalid timestamp, can't do QoS, process frame");
1273     goto keep_frame;
1274   }
1275
1276   /* get latest QoS observation values */
1277   gst_deinterlace_read_qos (self, &proportion, &earliest_time);
1278
1279   /* skip qos if we have no observation (yet) => process frame */
1280   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
1281     GST_LOG_OBJECT (self, "no observation yet, process frame");
1282     goto keep_frame;
1283   }
1284
1285   /* qos is done on running time */
1286   qostime = gst_segment_to_running_time (&self->segment, GST_FORMAT_TIME,
1287       timestamp);
1288
1289   /* see how our next timestamp relates to the latest qos timestamp */
1290   GST_LOG_OBJECT (self, "qostime %" GST_TIME_FORMAT ", earliest %"
1291       GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time));
1292
1293   if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) {
1294     GstClockTime stream_time, jitter;
1295     GstMessage *qos_msg;
1296
1297     GST_DEBUG_OBJECT (self, "we are late, drop frame");
1298     self->dropped++;
1299     stream_time =
1300         gst_segment_to_stream_time (&self->segment, GST_FORMAT_TIME, timestamp);
1301     jitter = GST_CLOCK_DIFF (qostime, earliest_time);
1302     qos_msg =
1303         gst_message_new_qos (GST_OBJECT (self), FALSE, qostime, stream_time,
1304         timestamp, GST_BUFFER_DURATION (buffer));
1305     gst_message_set_qos_values (qos_msg, jitter, proportion, 1000000);
1306     gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS,
1307         self->processed, self->dropped);
1308     gst_element_post_message (GST_ELEMENT (self), qos_msg);
1309     return FALSE;
1310   }
1311
1312   GST_LOG_OBJECT (self, "process frame");
1313 keep_frame:
1314   self->processed++;
1315   return TRUE;
1316 }
1317
1318 static gboolean
1319 gst_deinterlace_fix_timestamps (GstDeinterlace * self,
1320     GstVideoFrame * field1, GstVideoFrame * field2)
1321 {
1322   GstVideoFrame *field3, *field4;
1323   GstVideoInterlaceMode interlacing_mode;
1324
1325   /* FIXME: This is broken for rate < 0 */
1326   if (self->pattern_lock && self->pattern > -1) {
1327     /* accurate pattern-locked timestamp adjustment */
1328     if (!self->pattern_count)
1329       gst_deinterlace_update_pattern_timestamps (self);
1330
1331     GST_BUFFER_TIMESTAMP (field1->buffer) =
1332         self->pattern_base_ts + self->output_count * self->pattern_buf_dur;
1333     GST_BUFFER_DURATION (field1->buffer) = self->pattern_buf_dur;
1334     self->output_count++;
1335   } else {
1336     /* naive (but low-latency) timestamp adjustment based on subsequent
1337      * fields/buffers */
1338     if (field2
1339         && GST_VIDEO_FRAME_PLANE_DATA (field1,
1340             0) != GST_VIDEO_FRAME_PLANE_DATA (field2, 0)) {
1341       if (GST_BUFFER_TIMESTAMP (field1->buffer) +
1342           GST_BUFFER_DURATION (field1->buffer) ==
1343           GST_BUFFER_TIMESTAMP (field2->buffer)) {
1344         GST_BUFFER_TIMESTAMP (field1->buffer) =
1345             GST_BUFFER_TIMESTAMP (field2->buffer) =
1346             (GST_BUFFER_TIMESTAMP (field1->buffer) +
1347             GST_BUFFER_TIMESTAMP (field2->buffer)) / 2;
1348       } else {
1349         GST_BUFFER_TIMESTAMP (field2->buffer) =
1350             GST_BUFFER_TIMESTAMP (field1->buffer);
1351       }
1352     }
1353
1354     if (self->history_count < 3) {
1355       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need 3)",
1356           self->history_count);
1357       return FALSE;
1358     }
1359
1360     field3 = self->field_history[self->history_count - 3].frame;
1361     interlacing_mode = GST_VIDEO_INFO_INTERLACE_MODE (&field3->info);
1362     if (IS_TELECINE (interlacing_mode)) {
1363       if (self->history_count < 4) {
1364         GST_DEBUG_OBJECT (self, "Need more fields (have %d, need 4)",
1365             self->history_count);
1366         return FALSE;
1367       }
1368
1369       field4 = self->field_history[self->history_count - 4].frame;
1370       if (GST_VIDEO_FRAME_PLANE_DATA (field3,
1371               0) != GST_VIDEO_FRAME_PLANE_DATA (field4, 0)) {
1372         /* telecine fields in separate buffers */
1373         GST_BUFFER_TIMESTAMP (field3->buffer) =
1374             (GST_BUFFER_TIMESTAMP (field3->buffer) +
1375             GST_BUFFER_TIMESTAMP (field4->buffer)) / 2;
1376       }
1377     }
1378
1379     GST_BUFFER_DURATION (field1->buffer) =
1380         GST_BUFFER_TIMESTAMP (field3->buffer) -
1381         GST_BUFFER_TIMESTAMP (field1->buffer);
1382   }
1383
1384   GST_DEBUG_OBJECT (self,
1385       "Field 1 adjusted to ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
1386       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1->buffer)),
1387       GST_TIME_ARGS (GST_BUFFER_DURATION (field1->buffer)));
1388   return TRUE;
1389 }
1390
1391 static void
1392 gst_deinterlace_get_pattern_lock (GstDeinterlace * self, gboolean * flush_one)
1393 {
1394   /* loop over all possible patterns and all possible phases
1395    * giving each a score. the highest score gets the lock */
1396   /* the score is calculated as the number of matched buffers in the
1397    * sequence starting at the phase offset with those from the history
1398    * then the longest duration pattern match is taken. if there is more than
1399    * one pattern matching all buffers, we take the longest pattern of those.
1400    * matches to complete patterns are preferred. if no non-trivial pattern is
1401    * matched, trivial patterns are tested. */
1402   gint i, j, k, score, pattern, phase;
1403   const gint state_count = self->state_count;
1404   const gint n_required = self->ignore_obscure ?
1405       GST_DEINTERLACE_OBSCURE_THRESHOLD :
1406       GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY;
1407
1408   /* set unknown pattern as this is used in logic outside this function */
1409   self->pattern = -1;
1410
1411   /* wait for more buffers */
1412   if (!self->have_eos && state_count < n_required) {
1413     GST_DEBUG_OBJECT (self, "Need more buffers in state history - %d/%d",
1414         state_count, n_required);
1415     return;
1416   }
1417
1418   score = pattern = phase = -1;
1419
1420   /* loop over all patterns */
1421   for (i = 0; i < G_N_ELEMENTS (telecine_patterns); i++) {
1422     const guint8 length = telecine_patterns[i].length;
1423
1424     if (self->ignore_obscure && i >= GST_DEINTERLACE_OBSCURE_THRESHOLD)
1425       break;
1426
1427     if (state_count < length)
1428       continue;
1429
1430     /* loop over all phases */
1431     for (j = 0; j < length; j++) {
1432       /* low-latency mode looks at past buffers, high latency at future buffers */
1433       const gint state_idx =
1434           self->low_latency ? (self->history_count - 1) >> 1 : state_count - 1;
1435       /* loop over history, breaking on differing buffer states */
1436       for (k = 0; k < length && k < state_count; k++) {
1437         const guint8 hist = self->buf_states[state_idx - k].state;
1438         const guint8 patt = telecine_patterns[i].states[(j + k) % length];
1439         if (!(hist & patt))
1440           break;
1441       }
1442
1443       /* make complete matches more signficant */
1444       if (k == length)
1445         k += GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY;
1446
1447       /* take as new best pattern if the number of matched buffers is more than
1448        * for other patterns */
1449       if (k > score) {
1450         score = k;
1451         pattern = i;
1452         phase = j;
1453       }
1454     }
1455   }
1456
1457   if (pattern < 0) {
1458     GST_WARNING_OBJECT (self, "Failed to select a pattern");
1459     return;
1460   }
1461
1462   GST_DEBUG_OBJECT (self,
1463       "Final pattern match result: pa %d, ph %d, l %d, s %d", pattern, phase,
1464       telecine_patterns[pattern].length, score);
1465   self->pattern = pattern;
1466   self->pattern_phase = phase;
1467   self->pattern_count = 0;
1468   self->output_count = 0;
1469   self->pattern_lock = TRUE;
1470
1471   for (i = 0; i < telecine_patterns[pattern].length; i++) {
1472     gint state_idx =
1473         self->low_latency ? (self->history_count - 1) >> 1 : self->state_count -
1474         1;
1475     state_idx -= i;
1476     GST_LOG_OBJECT (self, "buf[%d] %s", i,
1477         STATE_TO_STRING (self->buf_states[state_idx].state));
1478   }
1479
1480   /* check for the case that the first field of the pattern is an orphan */
1481   if (pattern > 1
1482       && telecine_patterns[pattern].states[phase] & (GST_ONE | GST_INT)) {
1483     gint i = phase, field_count = 0;
1484     guint8 state = telecine_patterns[pattern].states[i];
1485
1486     do {
1487       if (state & GST_ONE) {
1488         field_count++;
1489 #if 0
1490       } else if (!(state & GST_DRP)) {
1491 #endif
1492       } else {
1493         field_count += 2;
1494       }
1495       i++;
1496       i %= telecine_patterns[pattern].length;
1497       state = telecine_patterns[pattern].states[i];
1498     } while (!(state & GST_PRG));
1499
1500     /* if field_count is odd, we have an orphan field at the beginning of the
1501      * sequence
1502      * note - don't do this in low-latency mode as we are somewhere within the
1503      * pattern already */
1504     if (!self->low_latency && (*flush_one = field_count & 1)) {
1505       GST_DEBUG_OBJECT (self, "Orphan field detected at the beginning of the "
1506           "pattern - it will be deinterlaced.");
1507     }
1508   }
1509 }
1510
1511 static GstFlowReturn
1512 gst_deinterlace_output_frame (GstDeinterlace * self, gboolean flushing)
1513 {
1514   GstClockTime timestamp;
1515   GstFlowReturn ret;
1516   gint fields_required;
1517   GstBuffer *buf, *outbuf;
1518   GstVideoFrame *outframe = NULL;
1519   GstDeinterlaceField *field1, *field2;
1520   GstVideoInterlaceMode interlacing_mode;
1521   guint8 buf_state;
1522   gboolean hl_no_lock;          /* indicates high latency timestamp adjustment but no pattern lock (could be ONEF or I) */
1523   gboolean same_buffer;         /* are field1 and field2 in the same buffer? */
1524   gboolean flush_one;           /* used for flushing one field when in high latency mode and not locked */
1525   TelecinePattern pattern;
1526   guint8 phase, count;
1527   const GstDeinterlaceLocking locking = self->locking;
1528
1529   memset (&pattern, 0, sizeof (pattern));
1530
1531 restart:
1532   ret = GST_FLOW_OK;
1533   hl_no_lock = FALSE;
1534   flush_one = FALSE;
1535   self->need_more = FALSE;
1536   phase = self->pattern_phase;
1537   count = self->pattern_count;
1538
1539   if (!self->history_count) {
1540     GST_DEBUG_OBJECT (self, "History is empty, waiting for more buffers!");
1541     goto need_more;
1542   }
1543
1544   field1 = &self->field_history[self->history_count - 1];
1545
1546   if (locking != GST_DEINTERLACE_LOCKING_NONE) {
1547     GstCaps *sinkcaps;
1548
1549     if (!self->state_count) {
1550       GST_ERROR_OBJECT (self,
1551           "BROKEN! Fields in history + no states should not happen!");
1552       return GST_FLOW_ERROR;
1553     }
1554
1555     gst_deinterlace_get_buffer_state (self, field1->frame, &buf_state,
1556         &interlacing_mode);
1557
1558     if (self->pattern != -1)
1559       pattern = telecine_patterns[self->pattern];
1560
1561     /* patterns 0 and 1 are interlaced, the rest are telecine */
1562     if (self->pattern > 1)
1563       interlacing_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
1564
1565     if (self->pattern == -1 || self->pattern_refresh
1566         || !(buf_state & pattern.states[(phase + count) % pattern.length])) {
1567       if (self->pattern == -1) {
1568         GST_DEBUG_OBJECT (self, "No pattern lock - refresh lock");
1569       } else if (self->pattern_refresh) {
1570         GST_DEBUG_OBJECT (self, "Pattern refresh - refresh lock");
1571       } else {
1572         GST_DEBUG_OBJECT (self, "Unexpected buffer state - refresh lock");
1573       }
1574       /* no pattern, pattern refresh set or unexpected buffer state */
1575       self->pattern_lock = FALSE;
1576       self->pattern_refresh = TRUE;
1577
1578       /* refresh pattern lock */
1579       gst_deinterlace_get_pattern_lock (self, &flush_one);
1580
1581       if (self->pattern != -1) {
1582         /* locked onto a valid pattern so refresh complete */
1583         GST_DEBUG_OBJECT (self, "Pattern locked! %s starting at %d",
1584             telecine_patterns[self->pattern].nick, self->pattern_phase);
1585         self->pattern_refresh = FALSE;
1586       } else if (!self->low_latency) {
1587         if (!self->pattern_lock) {
1588           goto need_more;
1589         } else {
1590           hl_no_lock = TRUE;
1591         }
1592       }
1593
1594       /* setcaps on sink and src pads */
1595       sinkcaps = gst_pad_get_current_caps (self->sinkpad);
1596       if (!sinkcaps || !gst_deinterlace_setcaps (self, self->sinkpad, sinkcaps)) {
1597         if (sinkcaps)
1598           gst_caps_unref (sinkcaps);
1599         return GST_FLOW_NOT_NEGOTIATED;
1600       }
1601
1602       gst_caps_unref (sinkcaps);
1603
1604       if (flush_one && self->drop_orphans) {
1605         GST_DEBUG_OBJECT (self, "Dropping orphan first field");
1606         self->cur_field_idx--;
1607         gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
1608         goto restart;
1609       }
1610     }
1611   } else {
1612     gst_deinterlace_get_buffer_state (self, field1->frame, NULL,
1613         &interlacing_mode);
1614   }
1615
1616   same_buffer = self->history_count >= 2
1617       && (GST_VIDEO_FRAME_PLANE_DATA (field1->frame, 0) ==
1618       GST_VIDEO_FRAME_PLANE_DATA (self->field_history[self->history_count -
1619               2].frame, 0));
1620
1621   if ((flushing && self->history_count == 1) || (flush_one
1622           && !self->drop_orphans) || (hl_no_lock && (self->history_count == 1
1623               || !same_buffer))) {
1624     /* This case is for flushing a single field:
1625      * - flushing and 1 field in the history
1626      * - flush one (due to orphans in the pattern) and do not drop orphans
1627      * - high-latency pattern locking with no possible lock given the current
1628      *   state and either only one field in the history or the tip two fields
1629      *   are in separate buffers */
1630     GST_DEBUG_OBJECT (self, "Flushing one field using linear method");
1631     gst_deinterlace_set_method (self, GST_DEINTERLACE_LINEAR);
1632     fields_required = gst_deinterlace_method_get_fields_required (self->method);
1633   } else if (interlacing_mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE ||
1634       (interlacing_mode == GST_VIDEO_INTERLACE_MODE_MIXED &&
1635           !GST_VIDEO_FRAME_IS_INTERLACED (field1->frame))) {
1636     /* This case is for processing progressive buffers, telecine or plain
1637      * progressive */
1638     GstVideoFrame *field1_frame;
1639     GstBuffer *field1_buffer;
1640
1641     /* progressive */
1642     fields_required = 2;
1643
1644     /* Not enough fields in the history */
1645     if (!flushing && self->history_count < fields_required) {
1646       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1647           self->history_count, self->cur_field_idx + fields_required);
1648       goto need_more;
1649     }
1650
1651     field2 = &self->field_history[self->history_count - 2];
1652     if (GST_VIDEO_FRAME_PLANE_DATA (field1->frame,
1653             0) != GST_VIDEO_FRAME_PLANE_DATA (field2->frame, 0)) {
1654       /* ERROR - next two fields in field history are not one progressive buffer - weave? */
1655       GST_ERROR_OBJECT (self,
1656           "Progressive buffer but two fields at tip aren't in the same buffer!");
1657     }
1658
1659     if (IS_TELECINE (interlacing_mode)
1660         && !gst_deinterlace_fix_timestamps (self, field1->frame, field2->frame)
1661         && !flushing)
1662       goto need_more;
1663
1664     GST_DEBUG_OBJECT (self,
1665         "Frame type: Progressive; pushing buffer as a frame");
1666     /* pop and push */
1667     self->cur_field_idx--;
1668     field1_frame = gst_deinterlace_pop_history (self);
1669     field1_buffer = field1_frame->buffer;
1670     gst_buffer_ref (field1_buffer);
1671     gst_video_frame_unmap_and_free (field1_frame);
1672     /* field2 is the same buffer as field1, but we need to remove it from the
1673      * history anyway */
1674     self->cur_field_idx--;
1675     gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
1676     GST_DEBUG_OBJECT (self,
1677         "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1678         GST_TIME_FORMAT,
1679         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1_buffer)),
1680         GST_TIME_ARGS (GST_BUFFER_DURATION (field1_buffer)),
1681         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (field1_buffer) +
1682             GST_BUFFER_DURATION (field1_buffer)));
1683     if (self->discont) {
1684       GST_BUFFER_FLAG_SET (field1_buffer, GST_BUFFER_FLAG_DISCONT);
1685       self->discont = FALSE;
1686     }
1687     return gst_pad_push (self->srcpad, field1_buffer);
1688   } else if (IS_TELECINE (interlacing_mode)
1689       && GST_VIDEO_FRAME_IS_INTERLACED (field1->frame) && !same_buffer) {
1690     /* This case needs to identify telecine mixed buffers that require weaving
1691      * of two fields in different buffers.
1692      * - interlacing mode is mixed
1693      * - locked on to a telecine pattern
1694      * - frame is interlaced
1695      * - fields are in separate buffers
1696      * If we don't yet have a pattern lock, we will have to deinterlace as we
1697      * don't explicitly know we have a telecine sequence and so we drop through
1698      * to the plain deinterlace case */
1699     fields_required = 2;
1700     if (!flushing && self->history_count < fields_required) {
1701       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1702           self->history_count, self->cur_field_idx + fields_required);
1703       goto need_more;
1704     }
1705
1706     field2 = &self->field_history[self->history_count - 2];
1707     if (!gst_deinterlace_fix_timestamps (self, field1->frame, field2->frame)
1708         && !flushing)
1709       goto need_more;
1710
1711     /* check field1 and field2 buffer caps and flags are corresponding */
1712     if (field1->flags == field2->flags) {
1713       /* ERROR - fields are of same parity - what should be done here?
1714        * perhaps deinterlace the tip field and start again? */
1715       GST_ERROR_OBJECT (self, "Telecine mixed with fields of same parity!");
1716     }
1717     GST_DEBUG_OBJECT (self,
1718         "Frame type: Telecine Mixed; weaving tip two fields into a frame");
1719     /* set method to WEAVE */
1720     gst_deinterlace_set_method (self, GST_DEINTERLACE_WEAVE);
1721   } else {
1722     /* This is the final catch-all case that applies the selected deinterlacing
1723      * method. At this point the fields to be processed are either definitely
1724      * interlaced or we do not yet know that we have a telecine pattern lock
1725      * and so the best we can do is to deinterlace the fields. */
1726     gst_deinterlace_set_method (self, self->user_set_method_id);
1727     fields_required = gst_deinterlace_method_get_fields_required (self->method);
1728     if (flushing && self->history_count < fields_required) {
1729       /* note: we already checked for flushing with history count == 1 above
1730        * so we must have 2 or more fields in here */
1731       gst_deinterlace_set_method (self, GST_DEINTERLACE_VFIR);
1732       fields_required =
1733           gst_deinterlace_method_get_fields_required (self->method);
1734       GST_DEBUG_OBJECT (self, "Flushing field(s) using %s method",
1735           methods_types[self->method_id].value_nick);
1736     }
1737
1738     /* Not enough fields in the history */
1739     if (!flushing && self->history_count < fields_required) {
1740       GST_DEBUG_OBJECT (self, "Need more fields (have %d, need %d)",
1741           self->history_count, self->cur_field_idx + fields_required);
1742       goto need_more;
1743     }
1744
1745     GST_DEBUG_OBJECT (self,
1746         "Frame type: Interlaced; deinterlacing using %s method",
1747         methods_types[self->method_id].value_nick);
1748   }
1749
1750   if (!flushing && self->cur_field_idx < 1) {
1751     goto need_more;
1752   } else if (self->cur_field_idx < 0 && flushing) {
1753     self->cur_field_idx++;
1754   }
1755
1756   if (self->fields == GST_DEINTERLACE_ALL || IS_TELECINE (interlacing_mode))
1757     GST_DEBUG_OBJECT (self, "All fields");
1758   else if (self->fields == GST_DEINTERLACE_TF)
1759     GST_DEBUG_OBJECT (self, "Top fields");
1760   else if (self->fields == GST_DEINTERLACE_BF)
1761     GST_DEBUG_OBJECT (self, "Bottom fields");
1762
1763   if ((self->field_history[self->cur_field_idx].flags == PICTURE_INTERLACED_TOP
1764           && (self->fields == GST_DEINTERLACE_TF
1765               || IS_TELECINE (interlacing_mode)))
1766       || (self->fields == GST_DEINTERLACE_ALL
1767           && !IS_TELECINE (interlacing_mode))) {
1768     gint index;
1769
1770     GST_DEBUG_OBJECT (self, "deinterlacing top field");
1771
1772     /* create new buffer */
1773     ret = gst_buffer_pool_acquire_buffer (self->pool, &outbuf, NULL);
1774     if (ret != GST_FLOW_OK)
1775       goto no_buffer;
1776
1777     g_return_val_if_fail (self->history_count >=
1778         1 + gst_deinterlace_method_get_latency (self->method), GST_FLOW_ERROR);
1779
1780     index =
1781         self->history_count - 1 -
1782         gst_deinterlace_method_get_latency (self->method);
1783     buf = self->field_history[index].frame->buffer;
1784
1785     if (self->field_history[index].tc) {
1786       gst_buffer_add_video_time_code_meta (outbuf,
1787           self->field_history[index].tc);
1788     }
1789     if (IS_TELECINE (interlacing_mode) && !self->telecine_tc_warned) {
1790       self->telecine_tc_warned = TRUE;
1791       GST_FIXME_OBJECT (self,
1792           "Detected telecine timecodes when deinterlacing. This is not "
1793           "supported yet. Resulting timecode may be wrong");
1794     }
1795     if (self->fields == GST_DEINTERLACE_ALL) {
1796       GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (outbuf);
1797       if (meta) {
1798         meta->tc.config.fps_n = 2 * meta->tc.config.fps_n;
1799         meta->tc.frames = 2 * meta->tc.frames;
1800       }
1801     }
1802     if (!IS_TELECINE (interlacing_mode)) {
1803       timestamp = GST_BUFFER_TIMESTAMP (buf);
1804
1805       if (self->fields == GST_DEINTERLACE_ALL) {
1806         if (self->segment.rate < 0)
1807           GST_BUFFER_TIMESTAMP (outbuf) = timestamp + self->field_duration;
1808         else
1809           GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1810         GST_BUFFER_DURATION (outbuf) = self->field_duration;
1811       } else {
1812         GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1813         GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration;
1814       }
1815       GST_DEBUG_OBJECT (self,
1816           "[ADJUST] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1817           GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1818           GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
1819           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
1820               GST_BUFFER_DURATION (outbuf)));
1821     } else {
1822       GST_BUFFER_TIMESTAMP (outbuf) =
1823           GST_BUFFER_TIMESTAMP (field1->frame->buffer);
1824       GST_BUFFER_DURATION (outbuf) =
1825           GST_BUFFER_DURATION (field1->frame->buffer);
1826     }
1827
1828     /* Check if we need to drop the frame because of QoS */
1829     if (!gst_deinterlace_do_qos (self, buf)) {
1830       self->cur_field_idx--;
1831       gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
1832       gst_buffer_unref (outbuf);
1833       outbuf = NULL;
1834       ret = GST_FLOW_OK;
1835     } else {
1836       if (self->cur_field_idx < 0 && flushing) {
1837         if (self->history_count == 1) {
1838           gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
1839           goto need_more;
1840         }
1841         self->cur_field_idx++;
1842       }
1843       if (self->cur_field_idx < 0) {
1844         goto need_more;
1845       }
1846       if (!flushing && self->cur_field_idx < 1) {
1847         goto need_more;
1848       }
1849
1850       /* map the frame so the deinterlace methods can write the data to the
1851        * correct memory locations */
1852       outframe =
1853           gst_video_frame_new_and_map (&self->vinfo, outbuf, GST_MAP_WRITE);
1854
1855       /* do magic calculus */
1856       gst_deinterlace_method_deinterlace_frame (self->method,
1857           self->field_history, self->history_count, outframe,
1858           self->cur_field_idx);
1859
1860       gst_video_frame_unmap_and_free (outframe);
1861
1862       self->cur_field_idx--;
1863       /* need to remove the field in the telecine weaving case */
1864       if ((IS_TELECINE (interlacing_mode)
1865               && self->method_id == GST_DEINTERLACE_WEAVE)
1866           || self->cur_field_idx + 1 +
1867           gst_deinterlace_method_get_latency (self->method) <
1868           self->history_count || flushing) {
1869         gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
1870       }
1871
1872       if (gst_deinterlace_clip_buffer (self, outbuf)) {
1873         GST_DEBUG_OBJECT (self,
1874             "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1875             GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1876             GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
1877             GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
1878                 GST_BUFFER_DURATION (outbuf)));
1879         if (self->discont) {
1880           GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1881           self->discont = FALSE;
1882         }
1883         ret = gst_pad_push (self->srcpad, outbuf);
1884       } else {
1885         ret = GST_FLOW_OK;
1886         gst_buffer_unref (outbuf);
1887       }
1888
1889       outbuf = NULL;
1890       if (ret != GST_FLOW_OK)
1891         return ret;
1892       if (IS_TELECINE (interlacing_mode)
1893           && self->method_id == GST_DEINTERLACE_WEAVE) {
1894         /* pop off the second field */
1895         GST_DEBUG_OBJECT (self, "Removing unused field (count: %d)",
1896             self->history_count);
1897         self->cur_field_idx--;
1898         gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
1899         interlacing_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
1900         return ret;
1901       }
1902     }
1903
1904     if (flush_one && !self->drop_orphans) {
1905       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
1906       goto restart;
1907     }
1908   }
1909   /* no calculation done: remove excess field */
1910   else if (self->field_history[self->cur_field_idx].flags ==
1911       PICTURE_INTERLACED_TOP && (self->fields == GST_DEINTERLACE_BF
1912           && !IS_TELECINE (interlacing_mode))) {
1913     GST_DEBUG_OBJECT (self, "Removing unused top field");
1914     self->cur_field_idx--;
1915     gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
1916
1917     if (flush_one && !self->drop_orphans) {
1918       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
1919       goto restart;
1920     }
1921   }
1922
1923   if (self->history_count < fields_required)
1924     return ret;
1925
1926   if (self->cur_field_idx < 0)
1927     return ret;
1928
1929   /* deinterlace bottom_field */
1930   if ((self->field_history[self->cur_field_idx].flags ==
1931           PICTURE_INTERLACED_BOTTOM && (self->fields == GST_DEINTERLACE_BF
1932               || IS_TELECINE (interlacing_mode)))
1933       || (self->fields == GST_DEINTERLACE_ALL
1934           && !IS_TELECINE (interlacing_mode))) {
1935     gint index;
1936
1937     GST_DEBUG_OBJECT (self, "deinterlacing bottom field");
1938
1939     /* create new buffer */
1940     ret = gst_buffer_pool_acquire_buffer (self->pool, &outbuf, NULL);
1941     if (ret != GST_FLOW_OK)
1942       goto no_buffer;
1943
1944     g_return_val_if_fail (self->history_count >=
1945         gst_deinterlace_method_get_latency (self->method) + 1, GST_FLOW_ERROR);
1946
1947     index =
1948         self->history_count - 1 -
1949         gst_deinterlace_method_get_latency (self->method);
1950     buf = self->field_history[index].frame->buffer;
1951
1952     if (self->field_history[index].tc) {
1953       gst_buffer_add_video_time_code_meta (outbuf,
1954           self->field_history[index].tc);
1955     }
1956     if (IS_TELECINE (interlacing_mode) && !self->telecine_tc_warned) {
1957       self->telecine_tc_warned = TRUE;
1958       GST_FIXME_OBJECT (self,
1959           "Detected telecine timecodes when deinterlacing. This is not "
1960           "supported yet. Resulting timecode may be wrong");
1961     }
1962     if (self->fields == GST_DEINTERLACE_ALL) {
1963       GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (outbuf);
1964       if (meta) {
1965         meta->tc.config.fps_n = 2 * meta->tc.config.fps_n;
1966         meta->tc.frames = 2 * meta->tc.frames + 1;
1967       }
1968     }
1969     if (!IS_TELECINE (interlacing_mode)) {
1970       timestamp = GST_BUFFER_TIMESTAMP (buf);
1971
1972       if (self->fields == GST_DEINTERLACE_ALL) {
1973         if (self->segment.rate < 0)
1974           GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1975         else
1976           GST_BUFFER_TIMESTAMP (outbuf) = timestamp + self->field_duration;
1977         GST_BUFFER_DURATION (outbuf) = self->field_duration;
1978       } else {
1979         GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1980         GST_BUFFER_DURATION (outbuf) = 2 * self->field_duration;
1981       }
1982       GST_DEBUG_OBJECT (self,
1983           "[ADJUST] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
1984           GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1985           GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
1986           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
1987               GST_BUFFER_DURATION (outbuf)));
1988     } else {
1989       GST_BUFFER_TIMESTAMP (outbuf) =
1990           GST_BUFFER_TIMESTAMP (field1->frame->buffer);
1991       GST_BUFFER_DURATION (outbuf) =
1992           GST_BUFFER_DURATION (field1->frame->buffer);
1993     }
1994
1995     /* Check if we need to drop the frame because of QoS */
1996     if (!gst_deinterlace_do_qos (self, buf)) {
1997       self->cur_field_idx--;
1998       gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
1999       gst_buffer_unref (outbuf);
2000       outbuf = NULL;
2001       ret = GST_FLOW_OK;
2002     } else {
2003       /* map the frame so the deinterlace methods can write the data to the
2004        * correct memory locations */
2005       outframe =
2006           gst_video_frame_new_and_map (&self->vinfo, outbuf, GST_MAP_WRITE);
2007
2008       /* do magic calculus */
2009       gst_deinterlace_method_deinterlace_frame (self->method,
2010           self->field_history, self->history_count, outframe,
2011           self->cur_field_idx);
2012
2013       gst_video_frame_unmap_and_free (outframe);
2014
2015       self->cur_field_idx--;
2016       /* need to remove the field in the telecine weaving case */
2017       if ((IS_TELECINE (interlacing_mode)
2018               && self->method_id == GST_DEINTERLACE_WEAVE)
2019           || self->cur_field_idx + 1 +
2020           gst_deinterlace_method_get_latency (self->method) <
2021           self->history_count) {
2022         gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
2023       }
2024
2025       if (gst_deinterlace_clip_buffer (self, outbuf)) {
2026         GST_DEBUG_OBJECT (self,
2027             "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2028             GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
2029             GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
2030             GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf) +
2031                 GST_BUFFER_DURATION (outbuf)));
2032         ret = gst_pad_push (self->srcpad, outbuf);
2033       } else {
2034         ret = GST_FLOW_OK;
2035         gst_buffer_unref (outbuf);
2036       }
2037
2038       outbuf = NULL;
2039       if (ret != GST_FLOW_OK)
2040         return ret;
2041       if (IS_TELECINE (interlacing_mode)
2042           && self->method_id == GST_DEINTERLACE_WEAVE) {
2043         /* pop off the second field */
2044         GST_DEBUG_OBJECT (self, "Removing unused field (count: %d)",
2045             self->history_count);
2046         self->cur_field_idx--;
2047         gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
2048         interlacing_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
2049         return ret;
2050       }
2051     }
2052
2053     if (flush_one && !self->drop_orphans) {
2054       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
2055       goto restart;
2056     }
2057   }
2058   /* no calculation done: remove excess field */
2059   else if (self->field_history[self->cur_field_idx].flags ==
2060       PICTURE_INTERLACED_BOTTOM && (self->fields == GST_DEINTERLACE_TF
2061           && !IS_TELECINE (interlacing_mode))) {
2062     GST_DEBUG_OBJECT (self, "Removing unused bottom field");
2063     self->cur_field_idx--;
2064     gst_video_frame_unmap_and_free (gst_deinterlace_pop_history (self));
2065
2066     if (flush_one && !self->drop_orphans) {
2067       GST_DEBUG_OBJECT (self, "Orphan field deinterlaced - reconfiguring");
2068       goto restart;
2069     }
2070   }
2071
2072   return ret;
2073
2074 need_more:
2075   {
2076     self->need_more = TRUE;
2077     return ret;
2078   }
2079 no_buffer:
2080   {
2081     GST_DEBUG_OBJECT (self, "could not allocate buffer");
2082     return ret;
2083   }
2084 }
2085
2086 static gboolean
2087 gst_deinterlace_get_latency (GstDeinterlace * self)
2088 {
2089   if (self->locking == GST_DEINTERLACE_LOCKING_AUTO) {
2090     GstQuery *query;
2091
2092     query = gst_query_new_latency ();
2093     if ((gst_pad_peer_query (self->sinkpad, query))) {
2094       gboolean is_live;
2095       /* if upstream is live, we use low-latency passive locking mode
2096        * else high-latency active locking mode */
2097       gst_query_parse_latency (query, &is_live, NULL, NULL);
2098       GST_DEBUG_OBJECT (self, "Latency query indicates stream is %s",
2099           is_live ? "live - using passive locking" :
2100           "not live - using active locking");
2101       gst_query_unref (query);
2102       return is_live;
2103     } else {
2104       /* conservatively use passive locking if the query fails */
2105       GST_WARNING_OBJECT (self,
2106           "Latency query failed - fall back to using passive locking");
2107       gst_query_unref (query);
2108       return TRUE;
2109     }
2110   } else {
2111     return self->locking - 2;
2112   }
2113 }
2114
2115 static GstFlowReturn
2116 gst_deinterlace_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
2117 {
2118   GstDeinterlace *self = GST_DEINTERLACE (parent);
2119   GstFlowReturn ret = GST_FLOW_OK;
2120
2121   GST_OBJECT_LOCK (self);
2122   if (self->reconfigure || gst_pad_check_reconfigure (self->srcpad)) {
2123     GstCaps *caps;
2124
2125     if ((gint) self->new_fields != -1)
2126       self->user_set_fields = self->new_fields;
2127     if ((gint) self->new_mode != -1)
2128       self->mode = self->new_mode;
2129     self->new_mode = -1;
2130     self->new_fields = -1;
2131
2132     self->reconfigure = FALSE;
2133     GST_OBJECT_UNLOCK (self);
2134     caps = gst_pad_get_current_caps (self->sinkpad);
2135     if (caps != NULL) {
2136       if (!gst_deinterlace_setcaps (self, self->sinkpad, caps)) {
2137         gst_pad_mark_reconfigure (self->srcpad);
2138         gst_caps_unref (caps);
2139         if (GST_PAD_IS_FLUSHING (self->srcpad))
2140           return GST_FLOW_FLUSHING;
2141         else
2142           return GST_FLOW_NOT_NEGOTIATED;
2143       }
2144       gst_caps_unref (caps);
2145     } else {
2146       gst_pad_mark_reconfigure (self->srcpad);
2147       return GST_FLOW_FLUSHING;
2148     }
2149   } else {
2150     GST_OBJECT_UNLOCK (self);
2151   }
2152
2153   GST_DEBUG_OBJECT (self,
2154       "[IN] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2155       GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
2156       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
2157       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)));
2158
2159   if (self->still_frame_mode || self->passthrough) {
2160     GST_DEBUG_OBJECT (self,
2161         "Frame type: Progressive?; pushing buffer using pass-through");
2162     GST_DEBUG_OBJECT (self,
2163         "[OUT] ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", end %"
2164         GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
2165         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
2166         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)));
2167
2168     return gst_pad_push (self->srcpad, buf);
2169   }
2170
2171   if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
2172     GST_DEBUG_OBJECT (self, "DISCONT buffer, resetting history");
2173     gst_deinterlace_reset_history (self, FALSE);
2174     self->discont = TRUE;
2175   }
2176
2177   gst_deinterlace_push_history (self, buf);
2178   buf = NULL;
2179
2180   do {
2181     ret = gst_deinterlace_output_frame (self, FALSE);
2182   } while (!self->need_more && self->history_count > 0 && ret == GST_FLOW_OK);
2183
2184   return ret;
2185 }
2186
2187 static gboolean
2188 gst_deinterlace_acceptcaps (GstDeinterlace * self, GstPad * pad, GstCaps * caps)
2189 {
2190   gboolean ret;
2191   GstCaps *ourcaps;
2192
2193   /* In AUTO/DISABLED mode we accept everything that is compatible with
2194    * our template caps. In INTERLACED mode we force deinterlacing, meaning
2195    * we can only possibly support the deinterlace caps.
2196    * In AUTO_STRICT mode we accept all progressive formats, but only those
2197    * interlaced format that we can actually deinterlace */
2198   if (self->mode == GST_DEINTERLACE_MODE_DISABLED
2199       || self->mode == GST_DEINTERLACE_MODE_AUTO) {
2200     ourcaps = gst_pad_get_pad_template_caps (pad);
2201     ret = gst_caps_is_subset (caps, ourcaps);
2202     gst_caps_unref (ourcaps);
2203   } else if (self->mode == GST_DEINTERLACE_MODE_INTERLACED) {
2204     ourcaps = gst_static_caps_get (&deinterlace_caps);
2205     ret = gst_caps_is_subset (caps, ourcaps);
2206     gst_caps_unref (ourcaps);
2207   } else if (self->mode == GST_DEINTERLACE_MODE_AUTO_STRICT) {
2208     ourcaps = gst_static_caps_get (&progressive_caps);
2209     ret = gst_caps_is_subset (caps, ourcaps);
2210     gst_caps_unref (ourcaps);
2211
2212     if (!ret) {
2213       ourcaps = gst_static_caps_get (&deinterlace_caps);
2214       ret = gst_caps_is_subset (caps, ourcaps);
2215       gst_caps_unref (ourcaps);
2216     }
2217   } else {
2218     g_assert_not_reached ();
2219   }
2220
2221   GST_DEBUG_OBJECT (pad, "accept-caps result:%d for caps %" GST_PTR_FORMAT,
2222       ret, caps);
2223
2224   return ret;
2225 }
2226
2227 static gboolean
2228 gst_deinterlace_fraction_double (gint * n_out, gint * d_out, gboolean half)
2229 {
2230   gint n, d, gcd;
2231
2232   n = *n_out;
2233   d = *d_out;
2234
2235   if (d == 0)
2236     return FALSE;
2237
2238   if (n == 0)
2239     return TRUE;
2240
2241   gcd = gst_util_greatest_common_divisor (n, d);
2242   n /= gcd;
2243   d /= gcd;
2244
2245   if (half) {
2246     if (G_MAXINT / 2 >= ABS (d)) {
2247       d *= 2;
2248     } else if (n >= 2 && n != G_MAXINT) {
2249       n /= 2;
2250     } else {
2251       d = G_MAXINT;
2252     }
2253   } else {
2254     if (G_MAXINT / 2 >= ABS (n)) {
2255       n *= 2;
2256     } else if (d >= 2 && d != G_MAXINT) {
2257       d /= 2;
2258     } else {
2259       n = G_MAXINT;
2260     }
2261   }
2262
2263   *n_out = n;
2264   *d_out = d;
2265
2266   return TRUE;
2267 }
2268
2269 static GstCaps *
2270 gst_deinterlace_caps_double_framerate (GstCaps * caps, gboolean half)
2271 {
2272   guint len;
2273
2274   for (len = gst_caps_get_size (caps); len > 0; len--) {
2275     GstStructure *s = gst_caps_get_structure (caps, len - 1);
2276     const GValue *val;
2277
2278     val = gst_structure_get_value (s, "framerate");
2279     if (!val)
2280       continue;
2281
2282     if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) {
2283       gint n, d;
2284
2285       n = gst_value_get_fraction_numerator (val);
2286       d = gst_value_get_fraction_denominator (val);
2287
2288       if (!gst_deinterlace_fraction_double (&n, &d, half)) {
2289         gst_caps_remove_structure (caps, len - 1);
2290         continue;
2291       }
2292
2293       gst_structure_set (s, "framerate", GST_TYPE_FRACTION, n, d, NULL);
2294     } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) {
2295       const GValue *min, *max;
2296       GValue nrange = { 0, }, nmin = {
2297       0,}, nmax = {
2298       0,};
2299       gint n, d;
2300
2301       g_value_init (&nrange, GST_TYPE_FRACTION_RANGE);
2302       g_value_init (&nmin, GST_TYPE_FRACTION);
2303       g_value_init (&nmax, GST_TYPE_FRACTION);
2304
2305       min = gst_value_get_fraction_range_min (val);
2306       max = gst_value_get_fraction_range_max (val);
2307
2308       n = gst_value_get_fraction_numerator (min);
2309       d = gst_value_get_fraction_denominator (min);
2310
2311       if (!gst_deinterlace_fraction_double (&n, &d, half)) {
2312         g_value_unset (&nrange);
2313         g_value_unset (&nmax);
2314         g_value_unset (&nmin);
2315         gst_caps_remove_structure (caps, len - 1);
2316         continue;
2317       }
2318
2319       gst_value_set_fraction (&nmin, n, d);
2320
2321       n = gst_value_get_fraction_numerator (max);
2322       d = gst_value_get_fraction_denominator (max);
2323
2324       if (!gst_deinterlace_fraction_double (&n, &d, half)) {
2325         g_value_unset (&nrange);
2326         g_value_unset (&nmax);
2327         g_value_unset (&nmin);
2328         gst_caps_remove_structure (caps, len - 1);
2329         continue;
2330       }
2331
2332       gst_value_set_fraction (&nmax, n, d);
2333       gst_value_set_fraction_range (&nrange, &nmin, &nmax);
2334
2335       gst_structure_take_value (s, "framerate", &nrange);
2336
2337       g_value_unset (&nmin);
2338       g_value_unset (&nmax);
2339     } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) {
2340       const GValue *lval;
2341       GValue nlist = { 0, };
2342       GValue nval = { 0, };
2343       gint i;
2344
2345       g_value_init (&nlist, GST_TYPE_LIST);
2346       for (i = gst_value_list_get_size (val); i > 0; i--) {
2347         gint n, d;
2348
2349         lval = gst_value_list_get_value (val, i - 1);
2350
2351         if (G_VALUE_TYPE (lval) != GST_TYPE_FRACTION)
2352           continue;
2353
2354         n = gst_value_get_fraction_numerator (lval);
2355         d = gst_value_get_fraction_denominator (lval);
2356
2357         /* Double/Half the framerate but if this fails simply
2358          * skip this value from the list */
2359         if (!gst_deinterlace_fraction_double (&n, &d, half)) {
2360           continue;
2361         }
2362
2363         g_value_init (&nval, GST_TYPE_FRACTION);
2364
2365         gst_value_set_fraction (&nval, n, d);
2366         gst_value_list_append_and_take_value (&nlist, &nval);
2367       }
2368       gst_structure_take_value (s, "framerate", &nlist);
2369     }
2370   }
2371
2372   return caps;
2373 }
2374
2375 static GstCaps *
2376 gst_deinterlace_getcaps (GstDeinterlace * self, GstPad * pad, GstCaps * filter)
2377 {
2378   GstCaps *ret, *caps;
2379   GstPad *otherpad;
2380   gint len;
2381   GstCaps *ourcaps;
2382   GstCaps *peercaps;
2383   GstCaps *tmp, *tmp2;
2384
2385   otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad;
2386
2387   ourcaps = gst_pad_get_pad_template_caps (pad);
2388   peercaps = gst_pad_peer_query_caps (otherpad, NULL);
2389
2390   /* Filter any peercaps that are available with our template
2391    * to get started with the subset of caps we actually support */
2392   if (peercaps) {
2393     GST_DEBUG_OBJECT (pad, "Peer has caps %" GST_PTR_FORMAT, peercaps);
2394     caps = gst_caps_make_writable (gst_caps_intersect (ourcaps, peercaps));
2395     gst_caps_unref (peercaps);
2396     gst_caps_unref (ourcaps);
2397     peercaps = ourcaps = NULL;
2398   } else {
2399     caps = gst_caps_make_writable (ourcaps);
2400     ourcaps = NULL;
2401   }
2402
2403   GST_DEBUG_OBJECT (pad,
2404       "Transforming caps %" GST_PTR_FORMAT " with filter %" GST_PTR_FORMAT,
2405       caps, filter);
2406
2407   /* If deinterlacing is disabled, we just passthrough the
2408    * caps and everything */
2409   if (self->mode == GST_DEINTERLACE_MODE_DISABLED) {
2410     ret = caps;
2411     caps = NULL;
2412     goto done;
2413   }
2414
2415   /* If deinterlacing is enforced, we can only accept the
2416    * caps for which we can actually do deinterlacing */
2417   if (self->mode == GST_DEINTERLACE_MODE_INTERLACED) {
2418     tmp = gst_static_caps_get (&deinterlace_caps);
2419     ret = gst_caps_intersect_full (caps, tmp, GST_CAPS_INTERSECT_FIRST);
2420     gst_caps_unref (tmp);
2421     tmp = NULL;
2422     gst_caps_unref (caps);
2423     caps = NULL;
2424     goto done;
2425   }
2426
2427   g_assert (self->mode == GST_DEINTERLACE_MODE_AUTO
2428       || self->mode == GST_DEINTERLACE_MODE_AUTO_STRICT);
2429
2430   /* For the auto mode we have to do a bit more than that */
2431   ret = gst_caps_new_empty ();
2432
2433   /* We can accept any structure if
2434    * - they are progressive already
2435    *
2436    */
2437   tmp = gst_static_caps_get (&progressive_caps);
2438   tmp2 = gst_caps_intersect_full (caps, tmp, GST_CAPS_INTERSECT_FIRST);
2439   gst_caps_unref (tmp);
2440   tmp = NULL;
2441   ret = gst_caps_merge (ret, tmp2);
2442   tmp2 = NULL;
2443
2444   /* or
2445    * - they have sysmem caps features and a format for which we support
2446    *   deinterlacing
2447    * or
2448    * - they have ANY caps features, in which case we support it for
2449    *   sysmem caps features for formats we support
2450    *
2451    * NOTE: These are the caps where we actually would do deinterlacing
2452    * ourselves. If fields == ALL we would double the framerate so would
2453    * have to half the framerate constraints from downstream here
2454    */
2455   tmp = gst_static_caps_get (&deinterlace_caps);
2456   tmp2 = gst_caps_intersect_full (caps, tmp, GST_CAPS_INTERSECT_FIRST);
2457   gst_caps_unref (tmp);
2458   tmp = NULL;
2459
2460   for (len = gst_caps_get_size (tmp2); len > 0; len--) {
2461     GstStructure *s = gst_caps_get_structure (tmp2, len - 1);
2462
2463     if (pad == self->sinkpad)
2464       gst_structure_remove_field (s, "interlace-mode");
2465     else
2466       gst_structure_set (s, "interlace-mode", G_TYPE_STRING, "progressive",
2467           NULL);
2468   }
2469
2470   if (self->user_set_fields == GST_DEINTERLACE_ALL) {
2471     tmp2 = gst_deinterlace_caps_double_framerate (tmp2, (pad == self->sinkpad));
2472   }
2473   if (self->user_set_fields == GST_DEINTERLACE_FIELDS_AUTO) {
2474     tmp = gst_caps_copy (tmp2);
2475     tmp = gst_deinterlace_caps_double_framerate (tmp, (pad == self->sinkpad));
2476   }
2477
2478   ret = gst_caps_merge (ret, tmp2);
2479   tmp2 = NULL;
2480   if (tmp != NULL) {
2481     ret = gst_caps_merge (ret, tmp);
2482     tmp = NULL;
2483   }
2484
2485   /* or
2486    * - anything else in which case we would just passthrough again if we're
2487    *   only in AUTO and not AUTO_STRICT mode
2488    */
2489   if (self->mode == GST_DEINTERLACE_MODE_AUTO)
2490     ret = gst_caps_merge (ret, gst_caps_copy (caps));
2491
2492   gst_caps_unref (caps);
2493   caps = NULL;
2494
2495 done:
2496
2497   if (filter) {
2498     GstCaps *tmp;
2499
2500     GST_LOG_OBJECT (pad, "intersecting with %" GST_PTR_FORMAT, filter);
2501     tmp = gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
2502     gst_caps_unref (ret);
2503     ret = tmp;
2504   }
2505
2506   GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, ret);
2507
2508   return ret;
2509 }
2510
2511 /* takes ownership of the pool, allocator and query */
2512 static gboolean
2513 gst_deinterlace_set_allocation (GstDeinterlace * self,
2514     GstBufferPool * pool, GstAllocator * allocator,
2515     GstAllocationParams * params)
2516 {
2517   GstAllocator *oldalloc;
2518   GstBufferPool *oldpool;
2519
2520   GST_OBJECT_LOCK (self);
2521   oldpool = self->pool;
2522   self->pool = pool;
2523
2524   oldalloc = self->allocator;
2525   self->allocator = allocator;
2526
2527   if (params)
2528     self->params = *params;
2529   else
2530     gst_allocation_params_init (&self->params);
2531   GST_OBJECT_UNLOCK (self);
2532
2533   if (oldpool) {
2534     GST_DEBUG_OBJECT (self, "deactivating old pool %p", oldpool);
2535     gst_buffer_pool_set_active (oldpool, FALSE);
2536     gst_object_unref (oldpool);
2537   }
2538   if (oldalloc) {
2539     gst_object_unref (oldalloc);
2540   }
2541   if (pool) {
2542     GST_DEBUG_OBJECT (self, "activating new pool %p", pool);
2543     gst_buffer_pool_set_active (pool, TRUE);
2544   }
2545   return TRUE;
2546 }
2547
2548 static gboolean
2549 gst_deinterlace_do_bufferpool (GstDeinterlace * self, GstCaps * outcaps)
2550 {
2551   GstQuery *query;
2552   gboolean result = TRUE;
2553   GstBufferPool *pool;
2554   GstAllocator *allocator;
2555   GstAllocationParams params;
2556   GstStructure *config;
2557   guint size, min, max;
2558
2559   if (self->passthrough) {
2560     /* we are in passthrough, the input buffer is never copied and always passed
2561      * along. We never allocate an output buffer on the srcpad. What we do is
2562      * let the upstream element decide if it wants to use a bufferpool and
2563      * then we will proxy the downstream pool */
2564     GST_DEBUG_OBJECT (self, "we're passthough, delay bufferpool");
2565     gst_deinterlace_set_allocation (self, NULL, NULL, NULL);
2566     return TRUE;
2567   }
2568
2569   /* not passthrough, we need to allocate */
2570   /* find a pool for the negotiated caps now */
2571   GST_DEBUG_OBJECT (self, "doing allocation query");
2572   query = gst_query_new_allocation (outcaps, TRUE);
2573   if (!gst_pad_peer_query (self->srcpad, query)) {
2574     /* not a problem, just debug a little */
2575     GST_DEBUG_OBJECT (self, "peer ALLOCATION query failed");
2576   }
2577
2578   GST_DEBUG_OBJECT (self, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result,
2579       query);
2580
2581   /* we got configuration from our peer or the decide_allocation method,
2582    * parse them */
2583   if (gst_query_get_n_allocation_params (query) > 0) {
2584     gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
2585   } else {
2586     allocator = NULL;
2587     gst_allocation_params_init (&params);
2588   }
2589
2590   if (gst_query_get_n_allocation_pools (query) > 0)
2591     gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
2592   else {
2593     pool = NULL;
2594     size = GST_VIDEO_INFO_SIZE (&self->vinfo);
2595     min =
2596         MAX ((gst_deinterlace_method_get_fields_required (self->method) +
2597             1) / 2 + 1, 4);
2598     max = 0;
2599   }
2600
2601   if (pool == NULL) {
2602     /* no pool, we can make our own */
2603     GST_DEBUG_OBJECT (self, "no pool, making new pool");
2604     pool = gst_video_buffer_pool_new ();
2605   }
2606
2607   /* now configure */
2608   config = gst_buffer_pool_get_config (pool);
2609   gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
2610   gst_buffer_pool_config_set_allocator (config, allocator, &params);
2611   gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
2612   gst_buffer_pool_set_config (pool, config);
2613
2614   /* now store */
2615   result = gst_deinterlace_set_allocation (self, pool, allocator, &params);
2616
2617   gst_query_unref (query);
2618
2619   return result;
2620 }
2621
2622
2623 static gboolean
2624 gst_deinterlace_setcaps (GstDeinterlace * self, GstPad * pad, GstCaps * caps)
2625 {
2626   GstCaps *srccaps = NULL;
2627   GstVideoInterlaceMode interlacing_mode;
2628   gint fps_n, fps_d;
2629   GstCaps *peercaps, *current_caps;
2630
2631   gst_pad_check_reconfigure (self->srcpad);
2632
2633   if ((current_caps = gst_pad_get_current_caps (pad))) {
2634     if (gst_caps_is_equal (caps, current_caps)) {
2635       GST_DEBUG_OBJECT (pad, "Got same caps again, returning");
2636       gst_caps_unref (current_caps);
2637       return TRUE;
2638     }
2639     gst_deinterlace_reset_history (self, FALSE);
2640     gst_caps_unref (current_caps);
2641   }
2642   peercaps = gst_pad_peer_query_caps (self->srcpad, NULL);
2643
2644   /* Make sure the peer caps are compatible with the template caps */
2645   if (peercaps) {
2646     GstCaps *tmp = gst_pad_get_pad_template_caps (self->srcpad);
2647     GstCaps *tmp2 = gst_caps_intersect (peercaps, tmp);
2648
2649     gst_caps_unref (peercaps);
2650     peercaps = NULL;
2651     gst_caps_unref (tmp);
2652
2653     if (gst_caps_is_empty (tmp2)) {
2654       gst_caps_unref (tmp2);
2655       GST_ERROR_OBJECT (self, "Peer caps not compatible with template caps");
2656       goto invalid_caps;
2657     }
2658     peercaps = tmp2;
2659   }
2660
2661   if (self->locking != GST_DEINTERLACE_LOCKING_NONE) {
2662     if (self->low_latency == -1)
2663       self->low_latency = gst_deinterlace_get_latency (self);
2664
2665     if (self->pattern_lock) {
2666       /* refresh has been successful - we have a lock now */
2667       self->pattern_refresh = FALSE;
2668     } else {
2669       /* if we were not refreshing (!pattern_refresh) the caps have changed
2670        * so we need to refresh and we don't have a lock anymore
2671        * otherwise we have pattern_fresh and !pattern_lock anyway */
2672       self->pattern_refresh = TRUE;
2673       self->pattern_lock = FALSE;
2674     }
2675   }
2676
2677   if (!gst_video_info_from_caps (&self->vinfo, caps))
2678     goto invalid_caps;
2679
2680   fps_n = GST_VIDEO_INFO_FPS_N (&self->vinfo);
2681   fps_d = GST_VIDEO_INFO_FPS_D (&self->vinfo);
2682
2683   /* Update passthrough information */
2684   if (self->mode == GST_DEINTERLACE_MODE_DISABLED) {
2685     self->passthrough = TRUE;
2686     GST_DEBUG_OBJECT (self, "Passthrough because mode=disabled");
2687   } else if (self->mode == GST_DEINTERLACE_MODE_INTERLACED) {
2688     GstCaps *tmp = gst_static_caps_get (&deinterlace_caps);
2689
2690     if (!gst_caps_can_intersect (caps, tmp)) {
2691       gst_caps_unref (tmp);
2692       GST_ERROR_OBJECT (self, "Unsupported caps for mode=interlaced");
2693       goto invalid_caps;
2694     }
2695
2696     self->passthrough = FALSE;
2697     GST_DEBUG_OBJECT (self, "Not passthrough because mode=interlaced");
2698   } else if (self->mode == GST_DEINTERLACE_MODE_AUTO
2699       || self->mode == GST_DEINTERLACE_MODE_AUTO_STRICT) {
2700     GstCaps *tmp = gst_static_caps_get (&deinterlace_caps);
2701
2702     /* Already progressive? Passthrough */
2703     if (!GST_VIDEO_INFO_IS_INTERLACED (&self->vinfo)) {
2704       GST_DEBUG_OBJECT (self,
2705           "Passthrough because mode=auto and progressive caps");
2706       self->passthrough = TRUE;
2707     } else if (gst_caps_can_intersect (caps, tmp)) {
2708       if (peercaps) {
2709         GstCaps *allowed_caps;
2710         GstCaps *tmp2;
2711         GstStructure *s;
2712
2713         allowed_caps = gst_caps_intersect (peercaps, tmp);
2714
2715         tmp2 = gst_caps_copy (caps);
2716         s = gst_caps_get_structure (tmp2, 0);
2717         gst_structure_set (s, "interlace-mode", G_TYPE_STRING, "progressive",
2718             NULL);
2719         gst_structure_remove_field (s, "framerate");
2720
2721         /* Downstream does not support progressive caps but supports
2722          * the upstream caps, go passthrough.
2723          * TODO: We might want to check the framerate compatibility
2724          * of the caps too here
2725          */
2726         if (gst_caps_can_intersect (allowed_caps, caps)
2727             && !gst_caps_can_intersect (allowed_caps, tmp2)) {
2728           GST_DEBUG_OBJECT (self,
2729               "Passthrough because mode=auto, "
2730               "downstream does not support progressive caps and interlaced caps");
2731           self->passthrough = TRUE;
2732         } else {
2733           GST_DEBUG_OBJECT (self, "Not passthrough because mode=auto, "
2734               "downstream supports progressive caps and interlaced caps");
2735           self->passthrough = FALSE;
2736         }
2737
2738         gst_caps_unref (allowed_caps);
2739         gst_caps_unref (tmp2);
2740       } else {
2741         GST_DEBUG_OBJECT (self,
2742             "Not passthrough because mode=auto and interlaced caps");
2743         self->passthrough = FALSE;
2744       }
2745     } else {
2746       if (self->mode == GST_DEINTERLACE_MODE_AUTO) {
2747         GST_WARNING_OBJECT (self,
2748             "Passthrough because mode=auto and unsupported interlaced caps");
2749         self->passthrough = TRUE;
2750       } else {
2751         gst_caps_unref (tmp);
2752         GST_ERROR_OBJECT (self,
2753             "Unsupported interlaced caps in mode=auto-strict");
2754         goto invalid_caps;
2755       }
2756     }
2757
2758     gst_caps_unref (tmp);
2759   } else {
2760     g_assert_not_reached ();
2761   }
2762
2763   interlacing_mode = GST_VIDEO_INFO_INTERLACE_MODE (&self->vinfo);
2764
2765   if (!self->passthrough) {
2766     if (self->pattern_lock) {
2767       srccaps = gst_caps_copy (caps);
2768       if (self->pattern != -1
2769           && G_UNLIKELY (!gst_util_fraction_multiply (fps_n, fps_d,
2770                   telecine_patterns[self->pattern].ratio_n,
2771                   telecine_patterns[self->pattern].ratio_d, &fps_n, &fps_d)))
2772         GST_ERROR_OBJECT (self,
2773             "Multiplying the framerate by the telecine pattern ratio overflowed!");
2774       gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, fps_n,
2775           fps_d, NULL);
2776     } else if (self->locking == GST_DEINTERLACE_LOCKING_ACTIVE
2777         || self->low_latency == 0) {
2778       /* in high latency pattern locking mode if we don't have a pattern lock,
2779        * the sink pad caps are the best we know */
2780       srccaps = gst_caps_copy (caps);
2781     } else if (self->low_latency > 0
2782         && interlacing_mode == GST_VIDEO_INTERLACE_MODE_MIXED
2783         && self->pattern == -1) {
2784       /* for initial buffers of a telecine pattern, until there is a lock we
2785        * we output naïvely adjusted timestamps in low-latency pattern locking
2786        * mode */
2787       srccaps = gst_caps_copy (caps);
2788       gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
2789     } else if (self->user_set_fields == GST_DEINTERLACE_FIELDS_AUTO) {
2790       srccaps = gst_caps_copy (caps);
2791       if (peercaps) {
2792         gboolean can_be_tf = FALSE;
2793
2794         /* We already know that we are not passthrough: interlace-mode will
2795          * be progressive */
2796         gst_caps_set_simple (srccaps, "interlace-mode", G_TYPE_STRING,
2797             "progressive", NULL);
2798
2799         if (gst_caps_can_intersect (peercaps, srccaps)) {
2800           GST_DEBUG_OBJECT (self, "Can deinterlace top fields");
2801           can_be_tf = TRUE;
2802         }
2803         srccaps = gst_deinterlace_caps_double_framerate (srccaps, FALSE);
2804         if (!gst_caps_can_intersect (peercaps, srccaps)) {
2805           if (can_be_tf) {
2806             GST_DEBUG_OBJECT (self, "Will deinterlace top fields");
2807             gst_caps_set_simple (srccaps, "framerate", GST_TYPE_FRACTION, fps_n,
2808                 fps_d, NULL);
2809             self->fields = GST_DEINTERLACE_TF;
2810           } else {
2811             GST_DEBUG_OBJECT (self,
2812                 "Can't negotiate upstream and downstream caps");
2813             gst_caps_unref (srccaps);
2814             goto invalid_caps;
2815           }
2816         } else {
2817           GST_DEBUG_OBJECT (self, "Deinterlacing all fields");
2818           self->fields = GST_DEINTERLACE_ALL;
2819         }
2820       } else {
2821         GST_DEBUG_OBJECT (self,
2822             "No peer caps yet, falling back to deinterlacing all fields");
2823         self->fields = GST_DEINTERLACE_ALL;
2824         srccaps = gst_deinterlace_caps_double_framerate (srccaps, FALSE);
2825       }
2826     } else {
2827       self->fields = self->user_set_fields;
2828       srccaps = gst_caps_copy (caps);
2829       if (self->fields == GST_DEINTERLACE_ALL)
2830         srccaps = gst_deinterlace_caps_double_framerate (srccaps, FALSE);
2831     }
2832
2833     /* If not passthrough, we are going to output progressive content */
2834     gst_caps_set_simple (srccaps, "interlace-mode", G_TYPE_STRING,
2835         "progressive", NULL);
2836
2837     gst_deinterlace_set_method (self, self->method_id);
2838     gst_deinterlace_method_setup (self->method, &self->vinfo);
2839   } else {
2840     srccaps = gst_caps_ref (caps);
2841   }
2842
2843   if (fps_n != 0) {
2844     self->field_duration = gst_util_uint64_scale (GST_SECOND, fps_d, 2 * fps_n);
2845   } else {
2846     self->field_duration = 0;
2847   }
2848
2849   GST_DEBUG_OBJECT (pad, "Sink caps: %" GST_PTR_FORMAT, caps);
2850   GST_DEBUG_OBJECT (pad, "Src  caps: %" GST_PTR_FORMAT, srccaps);
2851
2852   if (!gst_pad_set_caps (self->srcpad, srccaps))
2853     goto set_caps_failed;
2854
2855   if (!gst_deinterlace_do_bufferpool (self, srccaps))
2856     goto no_bufferpool;
2857
2858   if (peercaps)
2859     gst_caps_unref (peercaps);
2860   gst_caps_unref (srccaps);
2861
2862   return TRUE;
2863
2864 invalid_caps:
2865   {
2866     if (peercaps)
2867       gst_caps_unref (peercaps);
2868     GST_ERROR_OBJECT (pad, "Invalid caps: %" GST_PTR_FORMAT, caps);
2869     gst_pad_mark_reconfigure (self->srcpad);
2870     return FALSE;
2871   }
2872 set_caps_failed:
2873   {
2874     GST_ERROR_OBJECT (pad, "Failed to set caps: %" GST_PTR_FORMAT, srccaps);
2875     if (peercaps)
2876       gst_caps_unref (peercaps);
2877     gst_caps_unref (srccaps);
2878     gst_pad_mark_reconfigure (self->srcpad);
2879     return FALSE;
2880   }
2881 no_bufferpool:
2882   {
2883     GST_ERROR_OBJECT (pad, "could not negotiate bufferpool");
2884     if (peercaps)
2885       gst_caps_unref (peercaps);
2886     gst_caps_unref (srccaps);
2887     gst_pad_mark_reconfigure (self->srcpad);
2888     return FALSE;
2889   }
2890 }
2891
2892 static gboolean
2893 gst_deinterlace_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
2894 {
2895   gboolean res = TRUE;
2896   GstDeinterlace *self = GST_DEINTERLACE (parent);
2897
2898   GST_LOG_OBJECT (pad, "received %s event: %" GST_PTR_FORMAT,
2899       GST_EVENT_TYPE_NAME (event), event);
2900
2901   switch (GST_EVENT_TYPE (event)) {
2902     case GST_EVENT_CAPS:
2903     {
2904       GstCaps *caps = NULL;
2905
2906       gst_event_parse_caps (event, &caps);
2907       res = gst_deinterlace_setcaps (self, pad, caps);
2908       gst_event_unref (event);
2909       break;
2910     }
2911     case GST_EVENT_SEGMENT:
2912     {
2913       const GstSegment *segment;
2914
2915       gst_event_parse_segment (event, &segment);
2916
2917       gst_deinterlace_reset_qos (self);
2918       gst_deinterlace_reset_history (self, FALSE);
2919
2920       if (segment->format == GST_FORMAT_TIME) {
2921         GST_DEBUG_OBJECT (pad,
2922             "Got SEGMENT event in TIME format, passing on (%"
2923             GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")",
2924             GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop));
2925         gst_segment_copy_into (segment, &self->segment);
2926       } else {
2927         GST_WARNING_OBJECT (pad, "Got SEGMENT event in %s format",
2928             gst_format_get_name (segment->format));
2929         gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
2930       }
2931
2932       res = gst_pad_push_event (self->srcpad, event);
2933       break;
2934     }
2935     case GST_EVENT_CUSTOM_DOWNSTREAM:{
2936       gboolean still_state;
2937
2938       if (gst_video_event_parse_still_frame (event, &still_state)) {
2939         GST_DEBUG_OBJECT (self, "Received still frame event, state %d",
2940             still_state);
2941
2942         if (still_state) {
2943           GstFlowReturn ret;
2944
2945           GST_DEBUG_OBJECT (self, "Handling still frame");
2946           self->still_frame_mode = TRUE;
2947           gst_deinterlace_reset_history (self, FALSE);
2948           if (self->last_buffer) {
2949             ret =
2950                 gst_pad_push (self->srcpad, gst_buffer_ref (self->last_buffer));
2951             GST_DEBUG_OBJECT (self, "Pushed still frame, result: %s",
2952                 gst_flow_get_name (ret));
2953           } else {
2954             GST_WARNING_OBJECT (self, "No pending buffer!");
2955           }
2956         } else {
2957           GST_DEBUG_OBJECT (self, "Ending still frames");
2958           self->still_frame_mode = FALSE;
2959         }
2960       }
2961
2962       res = gst_pad_push_event (self->srcpad, event);
2963       break;
2964     }
2965     case GST_EVENT_EOS:
2966       self->have_eos = TRUE;
2967       gst_deinterlace_reset_history (self, FALSE);
2968       res = gst_pad_push_event (self->srcpad, event);
2969       break;
2970
2971     case GST_EVENT_FLUSH_STOP:
2972       if (self->still_frame_mode) {
2973         GST_DEBUG_OBJECT (self, "Ending still frames");
2974         self->still_frame_mode = FALSE;
2975       }
2976       self->telecine_tc_warned = FALSE;
2977       gst_deinterlace_reset_qos (self);
2978       res = gst_pad_push_event (self->srcpad, event);
2979       gst_deinterlace_reset_history (self, TRUE);
2980       break;
2981
2982     default:
2983       res = gst_pad_event_default (pad, parent, event);
2984       break;
2985   }
2986
2987   return res;
2988 }
2989
2990 static gboolean
2991 gst_deinterlace_propose_allocation (GstDeinterlace * self, GstQuery * query)
2992 {
2993   GstBufferPool *pool;
2994   GstCaps *caps;
2995   GstVideoInfo info;
2996   guint size;
2997   GstStructure *config;
2998
2999   gst_query_parse_allocation (query, &caps, NULL);
3000
3001   if (caps == NULL)
3002     return FALSE;
3003
3004   if (!gst_video_info_from_caps (&info, caps))
3005     return FALSE;
3006
3007   size = GST_VIDEO_INFO_SIZE (&info);
3008
3009   pool = gst_video_buffer_pool_new ();
3010
3011   gst_query_add_allocation_pool (query, pool, size, 0, 0);
3012
3013   config = gst_buffer_pool_get_config (pool);
3014   gst_buffer_pool_config_set_params (config, caps, size,
3015       (gst_deinterlace_method_get_fields_required (self->method) + 1) / 2 + 1,
3016       0);
3017   gst_buffer_pool_set_config (pool, config);
3018
3019   gst_object_unref (pool);
3020   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
3021
3022   return TRUE;
3023 }
3024
3025 static gboolean
3026 gst_deinterlace_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
3027 {
3028   GstDeinterlace *self = GST_DEINTERLACE (parent);
3029   gboolean res = FALSE;
3030
3031   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
3032
3033   switch (GST_QUERY_TYPE (query)) {
3034     case GST_QUERY_CAPS:
3035     {
3036       GstCaps *filter, *caps;
3037
3038       gst_query_parse_caps (query, &filter);
3039       caps = gst_deinterlace_getcaps (self, pad, filter);
3040       gst_query_set_caps_result (query, caps);
3041       gst_caps_unref (caps);
3042       res = TRUE;
3043       break;
3044     }
3045     case GST_QUERY_ACCEPT_CAPS:
3046     {
3047       GstCaps *caps;
3048       gboolean ret;
3049
3050       gst_query_parse_accept_caps (query, &caps);
3051       ret = gst_deinterlace_acceptcaps (self, pad, caps);
3052       gst_query_set_accept_caps_result (query, ret);
3053       res = TRUE;
3054       break;
3055     }
3056     case GST_QUERY_ALLOCATION:
3057       if (self->passthrough)
3058         res = gst_pad_peer_query (self->srcpad, query);
3059       else
3060         res = gst_deinterlace_propose_allocation (self, query);
3061       break;
3062     default:
3063       res = gst_pad_query_default (pad, parent, query);
3064       break;
3065   }
3066   return res;
3067 }
3068
3069 static GstStateChangeReturn
3070 gst_deinterlace_change_state (GstElement * element, GstStateChange transition)
3071 {
3072   GstStateChangeReturn ret;
3073   GstDeinterlace *self = GST_DEINTERLACE (element);
3074
3075   switch (transition) {
3076     case GST_STATE_CHANGE_NULL_TO_READY:
3077       break;
3078     case GST_STATE_CHANGE_READY_TO_PAUSED:
3079       break;
3080     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3081       break;
3082     default:
3083       break;
3084   }
3085
3086   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3087   if (ret != GST_STATE_CHANGE_SUCCESS)
3088     return ret;
3089
3090   switch (transition) {
3091     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3092       break;
3093     case GST_STATE_CHANGE_PAUSED_TO_READY:
3094       gst_deinterlace_reset (self);
3095       break;
3096     case GST_STATE_CHANGE_READY_TO_NULL:
3097     default:
3098       break;
3099   }
3100
3101   return ret;
3102 }
3103
3104 static gboolean
3105 gst_deinterlace_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
3106 {
3107   GstDeinterlace *self = GST_DEINTERLACE (parent);
3108   gboolean res;
3109
3110   GST_DEBUG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
3111
3112   switch (GST_EVENT_TYPE (event)) {
3113     case GST_EVENT_QOS:{
3114       GstClockTimeDiff diff;
3115       GstClockTime timestamp;
3116       GstQOSType type;
3117       gdouble proportion;
3118
3119       gst_event_parse_qos (event, &type, &proportion, &diff, &timestamp);
3120
3121       gst_deinterlace_update_qos (self, proportion, diff, timestamp);
3122     }
3123       /* fall through */
3124     default:
3125       res = gst_pad_event_default (pad, parent, event);
3126       break;
3127   }
3128
3129   return res;
3130 }
3131
3132 static gboolean
3133 gst_deinterlace_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
3134 {
3135   GstDeinterlace *self = GST_DEINTERLACE (parent);
3136   gboolean res = FALSE;
3137
3138   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
3139
3140   switch (GST_QUERY_TYPE (query)) {
3141     case GST_QUERY_LATENCY:
3142       if (!self->passthrough) {
3143         GstClockTime min, max;
3144         gboolean live;
3145         GstPad *peer;
3146
3147         if ((peer = gst_pad_get_peer (self->sinkpad))) {
3148           if ((res = gst_pad_query (peer, query))) {
3149             GstClockTime latency;
3150             gint fields_required = 0;
3151             gint method_latency = 0;
3152
3153             if (self->method) {
3154               fields_required =
3155                   gst_deinterlace_method_get_fields_required (self->method);
3156               method_latency =
3157                   gst_deinterlace_method_get_latency (self->method);
3158             }
3159
3160             gst_query_parse_latency (query, &live, &min, &max);
3161
3162             GST_DEBUG_OBJECT (self, "Peer latency: min %"
3163                 GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
3164                 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
3165
3166             /* add our own latency */
3167             latency = (fields_required + method_latency) * self->field_duration;
3168
3169             GST_DEBUG_OBJECT (self, "Our latency: min %" GST_TIME_FORMAT
3170                 ", max %" GST_TIME_FORMAT,
3171                 GST_TIME_ARGS (latency), GST_TIME_ARGS (latency));
3172
3173             min += latency;
3174             if (max != GST_CLOCK_TIME_NONE)
3175               max += latency;
3176
3177             GST_DEBUG_OBJECT (self, "Calculated total latency : min %"
3178                 GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
3179                 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
3180
3181             gst_query_set_latency (query, live, min, max);
3182           }
3183           gst_object_unref (peer);
3184         } else {
3185           res = FALSE;
3186         }
3187         break;
3188       }
3189     default:
3190       res = gst_pad_query_default (pad, parent, query);
3191       break;
3192   }
3193
3194   return res;
3195 }
3196
3197 static gboolean
3198 plugin_init (GstPlugin * plugin)
3199 {
3200   GST_DEBUG_CATEGORY_INIT (deinterlace_debug, "deinterlace", 0, "Deinterlacer");
3201
3202 #if HAVE_ORC
3203   orc_init ();
3204 #endif
3205
3206   if (!gst_element_register (plugin, "deinterlace", GST_RANK_NONE,
3207           GST_TYPE_DEINTERLACE)) {
3208     return FALSE;
3209   }
3210
3211   return TRUE;
3212 }
3213
3214 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
3215     GST_VERSION_MINOR,
3216     deinterlace,
3217     "Deinterlacer", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
3218     GST_PACKAGE_ORIGIN);