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