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