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