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