Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / ext / theora / gsttheoraenc.c
1 /* GStreamer
2  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:element-theoraenc
22  * @see_also: theoradec, oggmux
23  *
24  * This element encodes raw video into a Theora stream.
25  * <ulink url="http://www.theora.org/">Theora</ulink> is a royalty-free
26  * video codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
27  * Foundation</ulink>, based on the VP3 codec.
28  *
29  * The theora codec internally only supports encoding of images that are a
30  * multiple of 16 pixels in both X and Y direction. It is however perfectly
31  * possible to encode images with other dimensions because an arbitrary
32  * rectangular cropping region can be set up. This element will automatically
33  * set up a correct cropping region if the dimensions are not multiples of 16
34  * pixels.
35  *
36  * To control the quality of the encoding, the #GstTheoraEnc::bitrate and
37  * #GstTheoraEnc::quality properties can be used. These two properties are
38  * mutualy exclusive. Setting the bitrate property will produce a constant
39  * bitrate (CBR) stream while setting the quality property will produce a
40  * variable bitrate (VBR) stream.
41  *
42  * <refsect2>
43  * <title>Example pipeline</title>
44  * |[
45  * gst-launch -v videotestsrc num-buffers=1000 ! theoraenc ! oggmux ! filesink location=videotestsrc.ogg
46  * ]| This example pipeline will encode a test video source to theora muxed in an
47  * ogg container. Refer to the theoradec documentation to decode the create
48  * stream.
49  * </refsect2>
50  *
51  * Last reviewed on 2006-03-01 (0.10.4)
52  */
53
54 #ifdef HAVE_CONFIG_H
55 #include "config.h"
56 #endif
57
58 #include "gsttheoraenc.h"
59
60 #include <string.h>
61 #include <stdlib.h>             /* free */
62
63 #include <gst/tag/tag.h>
64 #include <gst/video/video.h>
65
66 #define GST_CAT_DEFAULT theoraenc_debug
67 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
68
69 #define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
70 static GType
71 gst_border_mode_get_type (void)
72 {
73   static GType border_mode_type = 0;
74   static const GEnumValue border_mode[] = {
75     {BORDER_NONE, "No Border", "none"},
76     {BORDER_BLACK, "Black Border", "black"},
77     {BORDER_MIRROR, "Mirror image in borders", "mirror"},
78     {0, NULL, NULL},
79   };
80
81   if (!border_mode_type) {
82     border_mode_type =
83         g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
84   }
85   return border_mode_type;
86 }
87
88 #define GST_TYPE_MULTIPASS_MODE (gst_multipass_mode_get_type())
89 static GType
90 gst_multipass_mode_get_type (void)
91 {
92   static GType multipass_mode_type = 0;
93   static const GEnumValue multipass_mode[] = {
94     {MULTIPASS_MODE_SINGLE_PASS, "Single pass", "single-pass"},
95     {MULTIPASS_MODE_FIRST_PASS, "First pass", "first-pass"},
96     {MULTIPASS_MODE_SECOND_PASS, "Second pass", "second-pass"},
97     {0, NULL, NULL},
98   };
99
100   if (!multipass_mode_type) {
101     multipass_mode_type =
102         g_enum_register_static ("GstTheoraEncMultipassMode", multipass_mode);
103   }
104   return multipass_mode_type;
105 }
106
107 /* taken from theora/lib/toplevel.c */
108 static int
109 _ilog (unsigned int v)
110 {
111   int ret = 0;
112
113   while (v) {
114     ret++;
115     v >>= 1;
116   }
117   return (ret);
118 }
119
120 #define THEORA_DEF_BITRATE              0
121 #define THEORA_DEF_QUALITY              48
122 #define THEORA_DEF_KEYFRAME_AUTO        TRUE
123 #define THEORA_DEF_KEYFRAME_FREQ        64
124 #define THEORA_DEF_KEYFRAME_FREQ_FORCE  64
125 #define THEORA_DEF_SPEEDLEVEL           1
126 #define THEORA_DEF_VP3_COMPATIBLE       FALSE
127 #define THEORA_DEF_DROP_FRAMES          TRUE
128 #define THEORA_DEF_CAP_OVERFLOW         TRUE
129 #define THEORA_DEF_CAP_UNDERFLOW        FALSE
130 #define THEORA_DEF_RATE_BUFFER          0
131 #define THEORA_DEF_MULTIPASS_CACHE_FILE NULL
132 #define THEORA_DEF_MULTIPASS_MODE       MULTIPASS_MODE_SINGLE_PASS
133 enum
134 {
135   PROP_0,
136   PROP_CENTER,
137   PROP_BORDER,
138   PROP_BITRATE,
139   PROP_QUALITY,
140   PROP_QUICK,
141   PROP_KEYFRAME_AUTO,
142   PROP_KEYFRAME_FREQ,
143   PROP_KEYFRAME_FREQ_FORCE,
144   PROP_KEYFRAME_THRESHOLD,
145   PROP_KEYFRAME_MINDISTANCE,
146   PROP_NOISE_SENSITIVITY,
147   PROP_SHARPNESS,
148   PROP_SPEEDLEVEL,
149   PROP_VP3_COMPATIBLE,
150   PROP_DROP_FRAMES,
151   PROP_CAP_OVERFLOW,
152   PROP_CAP_UNDERFLOW,
153   PROP_RATE_BUFFER,
154   PROP_MULTIPASS_CACHE_FILE,
155   PROP_MULTIPASS_MODE
156       /* FILL ME */
157 };
158
159 /* this function does a straight granulepos -> timestamp conversion */
160 static GstClockTime
161 granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos)
162 {
163   guint64 iframe, pframe;
164   int shift = theoraenc->info.keyframe_granule_shift;
165
166   if (granulepos < 0)
167     return GST_CLOCK_TIME_NONE;
168
169   iframe = granulepos >> shift;
170   pframe = granulepos - (iframe << shift);
171
172   /* num and den are 32 bit, so we can safely multiply with GST_SECOND */
173   return gst_util_uint64_scale ((guint64) (iframe + pframe),
174       GST_SECOND * theoraenc->info.fps_denominator,
175       theoraenc->info.fps_numerator);
176 }
177
178 /* Generate a dummy encoder context for use in th_encode_ctl queries
179    Release with th_encode_free()
180    This and the next routine from theora/examples/libtheora_info.c */
181 static th_enc_ctx *
182 dummy_encode_ctx (void)
183 {
184   th_enc_ctx *ctx;
185   th_info info;
186
187   /* set the minimal video parameters */
188   th_info_init (&info);
189   info.frame_width = 320;
190   info.frame_height = 240;
191   info.fps_numerator = 1;
192   info.fps_denominator = 1;
193
194   /* allocate and initialize a context object */
195   ctx = th_encode_alloc (&info);
196   if (!ctx)
197     GST_WARNING ("Failed to allocate dummy encoder context.");
198
199   /* clear the info struct */
200   th_info_clear (&info);
201
202   return ctx;
203 }
204
205 /* Query the current and maximum values for the 'speed level' setting.
206    This can be used to ask the encoder to trade off encoding quality
207    vs. performance cost, for example to adapt to realtime constraints. */
208 static int
209 check_speed_level (th_enc_ctx * ctx, int *current, int *max)
210 {
211   int ret;
212
213   /* query the current speed level */
214   ret = th_encode_ctl (ctx, TH_ENCCTL_GET_SPLEVEL, current, sizeof (int));
215   if (ret) {
216     GST_WARNING ("Error %d getting current speed level.", ret);
217     return ret;
218   }
219   /* query the maximum speed level, which varies by encoder version */
220   ret = th_encode_ctl (ctx, TH_ENCCTL_GET_SPLEVEL_MAX, max, sizeof (int));
221   if (ret) {
222     GST_WARNING ("Error %d getting maximum speed level.", ret);
223     return ret;
224   }
225
226   return 0;
227 }
228
229 static GstStaticPadTemplate theora_enc_sink_factory =
230 GST_STATIC_PAD_TEMPLATE ("sink",
231     GST_PAD_SINK,
232     GST_PAD_ALWAYS,
233     GST_STATIC_CAPS ("video/x-raw-yuv, "
234         "format = (fourcc) { I420, Y42B, Y444 }, "
235         "framerate = (fraction) [1/MAX, MAX], "
236         "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
237     );
238
239 static GstStaticPadTemplate theora_enc_src_factory =
240 GST_STATIC_PAD_TEMPLATE ("src",
241     GST_PAD_SRC,
242     GST_PAD_ALWAYS,
243     GST_STATIC_CAPS ("video/x-theora")
244     );
245
246 static void
247 _do_init (GType object_type)
248 {
249   const GInterfaceInfo preset_interface_info = {
250     NULL,                       /* interface_init */
251     NULL,                       /* interface_finalize */
252     NULL                        /* interface_data */
253   };
254
255   g_type_add_interface_static (object_type, GST_TYPE_PRESET,
256       &preset_interface_info);
257 }
258
259 GST_BOILERPLATE_FULL (GstTheoraEnc, gst_theora_enc, GstElement,
260     GST_TYPE_ELEMENT, _do_init);
261
262 static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
263 static gboolean theora_enc_src_event (GstPad * pad, GstEvent * event);
264 static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
265 static GstStateChangeReturn theora_enc_change_state (GstElement * element,
266     GstStateChange transition);
267 static GstCaps *theora_enc_sink_getcaps (GstPad * pad);
268 static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
269 static void theora_enc_get_property (GObject * object, guint prop_id,
270     GValue * value, GParamSpec * pspec);
271 static void theora_enc_set_property (GObject * object, guint prop_id,
272     const GValue * value, GParamSpec * pspec);
273 static void theora_enc_finalize (GObject * object);
274
275 static gboolean theora_enc_write_multipass_cache (GstTheoraEnc * enc,
276     gboolean begin, gboolean eos);
277
278 static void
279 gst_theora_enc_base_init (gpointer g_class)
280 {
281   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
282
283   gst_element_class_add_pad_template (element_class,
284       gst_static_pad_template_get (&theora_enc_src_factory));
285   gst_element_class_add_pad_template (element_class,
286       gst_static_pad_template_get (&theora_enc_sink_factory));
287   gst_element_class_set_details_simple (element_class,
288       "Theora video encoder", "Codec/Encoder/Video",
289       "encode raw YUV video to a theora stream",
290       "Wim Taymans <wim@fluendo.com>");
291 }
292
293 static void
294 gst_theora_enc_class_init (GstTheoraEncClass * klass)
295 {
296   GObjectClass *gobject_class = (GObjectClass *) klass;
297   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
298
299   /* query runtime encoder properties */
300   th_enc_ctx *th_ctx;
301   int default_speed_level = THEORA_DEF_SPEEDLEVEL;
302   int max_speed_level = default_speed_level;
303
304   GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
305
306   th_ctx = dummy_encode_ctx ();
307   if (th_ctx) {
308     if (!check_speed_level (th_ctx, &default_speed_level, &max_speed_level))
309       GST_WARNING
310           ("Failed to determine settings for the speed-level property.");
311     th_encode_free (th_ctx);
312   }
313
314   gobject_class->set_property = theora_enc_set_property;
315   gobject_class->get_property = theora_enc_get_property;
316   gobject_class->finalize = theora_enc_finalize;
317
318   g_object_class_install_property (gobject_class, PROP_CENTER,
319       g_param_spec_boolean ("center", "Center",
320           "ignored and kept for API compat only", TRUE,
321           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
322   g_object_class_install_property (gobject_class, PROP_BORDER,
323       g_param_spec_enum ("border", "Border",
324           "ignored and kept for API compat only",
325           GST_TYPE_BORDER_MODE, BORDER_BLACK,
326           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
327   /* general encoding stream options */
328   g_object_class_install_property (gobject_class, PROP_BITRATE,
329       g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
330           0, (1 << 24) - 1, THEORA_DEF_BITRATE,
331           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
332           GST_PARAM_MUTABLE_PLAYING));
333   g_object_class_install_property (gobject_class, PROP_QUALITY,
334       g_param_spec_int ("quality", "Quality", "Video quality", 0, 63,
335           THEORA_DEF_QUALITY,
336           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
337           GST_PARAM_MUTABLE_PLAYING));
338   g_object_class_install_property (gobject_class, PROP_QUICK,
339       g_param_spec_boolean ("quick", "Quick",
340           "ignored and kept for API compat only", TRUE,
341           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
342   g_object_class_install_property (gobject_class, PROP_KEYFRAME_AUTO,
343       g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
344           "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
345           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
346   g_object_class_install_property (gobject_class, PROP_KEYFRAME_FREQ,
347       g_param_spec_int ("keyframe-freq", "Keyframe frequency",
348           "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
349           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
350   g_object_class_install_property (gobject_class, PROP_KEYFRAME_FREQ_FORCE,
351       g_param_spec_int ("keyframe-force", "Keyframe force",
352           "Force keyframe every N frames", 1, 32768,
353           THEORA_DEF_KEYFRAME_FREQ_FORCE,
354           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
355   g_object_class_install_property (gobject_class, PROP_KEYFRAME_THRESHOLD,
356       g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
357           "ignored and kept for API compat only", 0, 32768, 80,
358           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
359   g_object_class_install_property (gobject_class, PROP_KEYFRAME_MINDISTANCE,
360       g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
361           "ignored and kept for API compat only", 1, 32768, 8,
362           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
363   g_object_class_install_property (gobject_class, PROP_NOISE_SENSITIVITY,
364       g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
365           "ignored and kept for API compat only", 0, 32768, 1,
366           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
367   g_object_class_install_property (gobject_class, PROP_SHARPNESS,
368       g_param_spec_int ("sharpness", "Sharpness",
369           "ignored and kept for API compat only", 0, 2, 0,
370           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
371   g_object_class_install_property (gobject_class, PROP_SPEEDLEVEL,
372       g_param_spec_int ("speed-level", "Speed level",
373           "Controls the amount of analysis performed when encoding."
374           " Higher values trade compression quality for speed."
375           " This property requires libtheora version >= 1.0"
376           ", and the maximum value may vary based on encoder version.",
377           0, max_speed_level, default_speed_level,
378           (GParamFlags) G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
379           G_PARAM_STATIC_STRINGS));
380   g_object_class_install_property (gobject_class, PROP_VP3_COMPATIBLE,
381       g_param_spec_boolean ("vp3-compatible", "VP3 Compatible",
382           "Disables non-VP3 compatible features",
383           THEORA_DEF_VP3_COMPATIBLE,
384           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
385   g_object_class_install_property (gobject_class, PROP_DROP_FRAMES,
386       g_param_spec_boolean ("drop-frames", "VP3 Compatible",
387           "Allow or disallow frame dropping",
388           THEORA_DEF_DROP_FRAMES,
389           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
390   g_object_class_install_property (gobject_class, PROP_CAP_OVERFLOW,
391       g_param_spec_boolean ("cap-overflow", "VP3 Compatible",
392           "Enable capping of bit reservoir overflows",
393           THEORA_DEF_CAP_OVERFLOW,
394           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
395   g_object_class_install_property (gobject_class, PROP_CAP_UNDERFLOW,
396       g_param_spec_boolean ("cap-underflow", "VP3 Compatible",
397           "Enable capping of bit reservoir underflows",
398           THEORA_DEF_CAP_UNDERFLOW,
399           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
400   g_object_class_install_property (gobject_class, PROP_RATE_BUFFER,
401       g_param_spec_int ("rate-buffer", "Rate Control Buffer",
402           "Sets the size of the rate control buffer, in units of frames.  "
403           "The default value of 0 instructs the encoder to automatically "
404           "select an appropriate value",
405           0, 1000, THEORA_DEF_RATE_BUFFER,
406           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
407   g_object_class_install_property (gobject_class, PROP_MULTIPASS_CACHE_FILE,
408       g_param_spec_string ("multipass-cache-file", "Multipass Cache File",
409           "Multipass cache file", THEORA_DEF_MULTIPASS_CACHE_FILE,
410           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
411   g_object_class_install_property (gobject_class, PROP_MULTIPASS_MODE,
412       g_param_spec_enum ("multipass-mode", "Multipass mode",
413           "Single pass or first/second pass", GST_TYPE_MULTIPASS_MODE,
414           THEORA_DEF_MULTIPASS_MODE,
415           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
416
417   gstelement_class->change_state = theora_enc_change_state;
418 }
419
420 static void
421 gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
422 {
423   enc->sinkpad =
424       gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink");
425   gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
426   gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
427   gst_pad_set_getcaps_function (enc->sinkpad, theora_enc_sink_getcaps);
428   gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
429   gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
430
431   enc->srcpad =
432       gst_pad_new_from_static_template (&theora_enc_src_factory, "src");
433   gst_pad_set_event_function (enc->srcpad, theora_enc_src_event);
434   gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
435
436   gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED);
437
438   enc->video_bitrate = THEORA_DEF_BITRATE;
439   enc->video_quality = THEORA_DEF_QUALITY;
440   enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
441   enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
442   enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
443
444   enc->expected_ts = GST_CLOCK_TIME_NONE;
445
446   /* enc->speed_level is set to the libtheora default by the constructor */
447   enc->vp3_compatible = THEORA_DEF_VP3_COMPATIBLE;
448   enc->drop_frames = THEORA_DEF_DROP_FRAMES;
449   enc->cap_overflow = THEORA_DEF_CAP_OVERFLOW;
450   enc->cap_underflow = THEORA_DEF_CAP_UNDERFLOW;
451   enc->rate_buffer = THEORA_DEF_RATE_BUFFER;
452
453   enc->multipass_mode = THEORA_DEF_MULTIPASS_MODE;
454   enc->multipass_cache_file = THEORA_DEF_MULTIPASS_CACHE_FILE;
455 }
456
457 static void
458 theora_enc_clear_multipass_cache (GstTheoraEnc * enc)
459 {
460   if (enc->multipass_cache_fd) {
461     g_io_channel_shutdown (enc->multipass_cache_fd, TRUE, NULL);
462     g_io_channel_unref (enc->multipass_cache_fd);
463     enc->multipass_cache_fd = NULL;
464   }
465
466   if (enc->multipass_cache_adapter) {
467     gst_object_unref (enc->multipass_cache_adapter);
468     enc->multipass_cache_adapter = NULL;
469   }
470 }
471
472 static void
473 theora_enc_finalize (GObject * object)
474 {
475   GstTheoraEnc *enc = GST_THEORA_ENC (object);
476
477   GST_DEBUG_OBJECT (enc, "Finalizing");
478   if (enc->encoder)
479     th_encode_free (enc->encoder);
480   th_comment_clear (&enc->comment);
481   th_info_clear (&enc->info);
482   g_free (enc->multipass_cache_file);
483
484   theora_enc_clear_multipass_cache (enc);
485
486   G_OBJECT_CLASS (parent_class)->finalize (object);
487 }
488
489 static void
490 theora_enc_reset (GstTheoraEnc * enc)
491 {
492   ogg_uint32_t keyframe_force;
493   int rate_flags;
494
495   GST_OBJECT_LOCK (enc);
496   enc->info.target_bitrate = enc->video_bitrate;
497   enc->info.quality = enc->video_quality;
498   enc->bitrate_changed = FALSE;
499   enc->quality_changed = FALSE;
500   GST_OBJECT_UNLOCK (enc);
501
502   if (enc->encoder)
503     th_encode_free (enc->encoder);
504   enc->encoder = th_encode_alloc (&enc->info);
505   /* We ensure this function cannot fail. */
506   g_assert (enc->encoder != NULL);
507   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level,
508       sizeof (enc->speed_level));
509   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_VP3_COMPATIBLE,
510       &enc->vp3_compatible, sizeof (enc->vp3_compatible));
511
512   rate_flags = 0;
513   if (enc->drop_frames)
514     rate_flags |= TH_RATECTL_DROP_FRAMES;
515   if (enc->drop_frames)
516     rate_flags |= TH_RATECTL_CAP_OVERFLOW;
517   if (enc->drop_frames)
518     rate_flags |= TH_RATECTL_CAP_UNDERFLOW;
519   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_FLAGS,
520       &rate_flags, sizeof (rate_flags));
521
522   if (enc->rate_buffer) {
523     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_BUFFER,
524         &enc->rate_buffer, sizeof (enc->rate_buffer));
525   } else {
526     /* FIXME */
527   }
528
529   keyframe_force = enc->keyframe_auto ?
530       enc->keyframe_force : enc->keyframe_freq;
531   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
532       &keyframe_force, sizeof (keyframe_force));
533
534   /* Get placeholder data */
535   if (enc->multipass_cache_fd
536       && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS)
537     theora_enc_write_multipass_cache (enc, TRUE, FALSE);
538 }
539
540 static void
541 theora_enc_clear (GstTheoraEnc * enc)
542 {
543   enc->packetno = 0;
544   enc->bytes_out = 0;
545   enc->granulepos_offset = 0;
546   enc->timestamp_offset = 0;
547
548   enc->next_ts = GST_CLOCK_TIME_NONE;
549   enc->next_discont = FALSE;
550   enc->expected_ts = GST_CLOCK_TIME_NONE;
551 }
552
553 static char *
554 theora_enc_get_supported_formats (void)
555 {
556   th_enc_ctx *encoder;
557   th_info info;
558   struct
559   {
560     th_pixel_fmt pixelformat;
561     const char *fourcc;
562   } formats[] = {
563     {
564     TH_PF_420, "I420"}, {
565     TH_PF_422, "Y42B"}, {
566     TH_PF_444, "Y444"}
567   };
568   GString *string = NULL;
569   guint i;
570
571   th_info_init (&info);
572   info.frame_width = 16;
573   info.frame_height = 16;
574   info.fps_numerator = 25;
575   info.fps_denominator = 1;
576   for (i = 0; i < G_N_ELEMENTS (formats); i++) {
577     info.pixel_fmt = formats[i].pixelformat;
578
579     encoder = th_encode_alloc (&info);
580     if (encoder == NULL)
581       continue;
582
583     GST_LOG ("format %s is supported", formats[i].fourcc);
584     th_encode_free (encoder);
585
586     if (string == NULL) {
587       string = g_string_new (formats[i].fourcc);
588     } else {
589       g_string_append (string, ", ");
590       g_string_append (string, formats[i].fourcc);
591     }
592   }
593   th_info_clear (&info);
594
595   return string == NULL ? NULL : g_string_free (string, FALSE);
596 }
597
598 static GstCaps *
599 theora_enc_sink_getcaps (GstPad * pad)
600 {
601   GstCaps *caps;
602   char *supported_formats, *caps_string;
603
604   supported_formats = theora_enc_get_supported_formats ();
605   if (!supported_formats) {
606     GST_WARNING ("no supported formats found. Encoder disabled?");
607     return gst_caps_new_empty ();
608   }
609
610   caps_string = g_strdup_printf ("video/x-raw-yuv, "
611       "format = (fourcc) { %s }, "
612       "framerate = (fraction) [1/MAX, MAX], "
613       "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]",
614       supported_formats);
615   caps = gst_caps_from_string (caps_string);
616   g_free (caps_string);
617   g_free (supported_formats);
618   GST_DEBUG ("Supported caps: %" GST_PTR_FORMAT, caps);
619
620   return caps;
621 }
622
623 static gboolean
624 theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
625 {
626   GstStructure *structure = gst_caps_get_structure (caps, 0);
627   GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
628   guint32 fourcc;
629   const GValue *par;
630   gint fps_n, fps_d;
631
632   gst_structure_get_fourcc (structure, "format", &fourcc);
633   gst_structure_get_int (structure, "width", &enc->width);
634   gst_structure_get_int (structure, "height", &enc->height);
635   gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
636   par = gst_structure_get_value (structure, "pixel-aspect-ratio");
637
638   th_info_clear (&enc->info);
639   th_info_init (&enc->info);
640   /* Theora has a divisible-by-sixteen restriction for the encoded video size but
641    * we can define a picture area using pic_width/pic_height */
642   enc->info.frame_width = GST_ROUND_UP_16 (enc->width);
643   enc->info.frame_height = GST_ROUND_UP_16 (enc->height);
644   enc->info.pic_width = enc->width;
645   enc->info.pic_height = enc->height;
646   switch (fourcc) {
647     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
648       enc->info.pixel_fmt = TH_PF_420;
649       break;
650     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
651       enc->info.pixel_fmt = TH_PF_422;
652       break;
653     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
654       enc->info.pixel_fmt = TH_PF_444;
655       break;
656     default:
657       g_assert_not_reached ();
658   }
659
660   enc->info.fps_numerator = enc->fps_n = fps_n;
661   enc->info.fps_denominator = enc->fps_d = fps_d;
662   if (par) {
663     enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
664     enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
665   } else {
666     /* setting them to 0 indicates that the decoder can chose a good aspect
667      * ratio, defaulting to 1/1 */
668     enc->info.aspect_numerator = 0;
669     enc->info.aspect_denominator = 0;
670   }
671
672   enc->info.colorspace = TH_CS_UNSPECIFIED;
673
674   /* as done in theora */
675   enc->info.keyframe_granule_shift = _ilog (enc->keyframe_force - 1);
676   GST_DEBUG_OBJECT (enc,
677       "keyframe_frequency_force is %d, granule shift is %d",
678       enc->keyframe_force, enc->info.keyframe_granule_shift);
679
680   theora_enc_reset (enc);
681   enc->initialised = TRUE;
682
683   gst_object_unref (enc);
684
685   return TRUE;
686 }
687
688 static guint64
689 granulepos_add (guint64 granulepos, guint64 addend, gint shift)
690 {
691   guint64 iframe, pframe;
692
693   iframe = granulepos >> shift;
694   pframe = granulepos - (iframe << shift);
695   iframe += addend;
696
697   return (iframe << shift) + pframe;
698 }
699
700 /* prepare a buffer for transmission by passing data through libtheora */
701 static GstFlowReturn
702 theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
703     GstClockTime timestamp, GstClockTime running_time,
704     GstClockTime duration, GstBuffer ** buffer)
705 {
706   GstBuffer *buf;
707   GstFlowReturn ret = GST_FLOW_OK;
708
709   buf = gst_buffer_new_and_alloc (packet->bytes);
710   if (!buf) {
711     GST_WARNING_OBJECT (enc, "Could not allocate buffer");
712     ret = GST_FLOW_ERROR;
713     goto done;
714   }
715
716   memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
717   gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
718   /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
719    * time representation */
720   GST_BUFFER_OFFSET_END (buf) =
721       granulepos_add (packet->granulepos, enc->granulepos_offset,
722       enc->info.keyframe_granule_shift);
723   GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc,
724       GST_BUFFER_OFFSET_END (buf));
725
726   GST_BUFFER_TIMESTAMP (buf) = timestamp;
727   GST_BUFFER_DURATION (buf) = duration;
728
729   if (enc->next_discont) {
730     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
731     enc->next_discont = FALSE;
732   }
733
734   /* the second most significant bit of the first data byte is cleared
735    * for keyframes */
736   if (packet->bytes > 0 && (packet->packet[0] & 0x40) == 0) {
737     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
738   } else {
739     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
740   }
741   enc->packetno++;
742
743 done:
744   *buffer = buf;
745   return ret;
746 }
747
748 /* push out the buffer and do internal bookkeeping */
749 static GstFlowReturn
750 theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
751 {
752   GstFlowReturn ret;
753
754   enc->bytes_out += GST_BUFFER_SIZE (buffer);
755
756   ret = gst_pad_push (enc->srcpad, buffer);
757
758   return ret;
759 }
760
761 static GstFlowReturn
762 theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
763     GstClockTime timestamp, GstClockTime running_time, GstClockTime duration)
764 {
765   GstBuffer *buf;
766   GstFlowReturn ret;
767
768   ret =
769       theora_buffer_from_packet (enc, packet, timestamp, running_time, duration,
770       &buf);
771   if (ret == GST_FLOW_OK)
772     ret = theora_push_buffer (enc, buf);
773
774   return ret;
775 }
776
777 static GstCaps *
778 theora_set_header_on_caps (GstCaps * caps, GSList * buffers)
779 {
780   GstStructure *structure;
781   GValue array = { 0 };
782   GValue value = { 0 };
783   GstBuffer *buffer;
784   GSList *walk;
785
786   caps = gst_caps_make_writable (caps);
787   structure = gst_caps_get_structure (caps, 0);
788
789   /* put copies of the buffers in a fixed list */
790   g_value_init (&array, GST_TYPE_ARRAY);
791
792   for (walk = buffers; walk; walk = walk->next) {
793     buffer = walk->data;
794
795     /* mark buffer */
796     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
797
798     /* Copy buffer, because we can't use the original -
799      * it creates a circular refcount with the caps<->buffers */
800     buffer = gst_buffer_copy (buffer);
801
802     g_value_init (&value, GST_TYPE_BUFFER);
803     gst_value_set_buffer (&value, buffer);
804     gst_value_array_append_value (&array, &value);
805     g_value_unset (&value);
806
807     /* Unref our copy */
808     gst_buffer_unref (buffer);
809   }
810
811   gst_structure_set_value (structure, "streamheader", &array);
812   g_value_unset (&array);
813
814   return caps;
815 }
816
817 static void
818 theora_enc_force_keyframe (GstTheoraEnc * enc)
819 {
820   GstClockTime next_ts;
821
822   /* make sure timestamps increment after resetting the decoder */
823   next_ts = enc->next_ts + enc->timestamp_offset;
824
825   theora_enc_reset (enc);
826   enc->granulepos_offset =
827       gst_util_uint64_scale (next_ts, enc->fps_n, GST_SECOND * enc->fps_d);
828   enc->timestamp_offset = next_ts;
829   enc->next_ts = 0;
830 }
831
832 static gboolean
833 theora_enc_sink_event (GstPad * pad, GstEvent * event)
834 {
835   GstTheoraEnc *enc;
836   ogg_packet op;
837   gboolean res;
838
839   enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
840
841   switch (GST_EVENT_TYPE (event)) {
842     case GST_EVENT_NEWSEGMENT:
843     {
844       gboolean update;
845       gdouble rate, applied_rate;
846       GstFormat format;
847       gint64 start, stop, time;
848
849       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
850           &format, &start, &stop, &time);
851
852       gst_segment_set_newsegment_full (&enc->segment, update, rate,
853           applied_rate, format, start, stop, time);
854
855       res = gst_pad_push_event (enc->srcpad, event);
856       break;
857     }
858     case GST_EVENT_EOS:
859       if (enc->initialised) {
860         /* push last packet with eos flag, should not be called */
861         while (th_encode_packetout (enc->encoder, 1, &op)) {
862           GstClockTime next_time =
863               th_granule_time (enc->encoder, op.granulepos) * GST_SECOND;
864
865           theora_push_packet (enc, &op, GST_CLOCK_TIME_NONE, enc->next_ts,
866               next_time - enc->next_ts);
867           enc->next_ts = next_time;
868         }
869       }
870       if (enc->initialised && enc->multipass_cache_fd
871           && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS)
872         theora_enc_write_multipass_cache (enc, TRUE, TRUE);
873
874       theora_enc_clear_multipass_cache (enc);
875
876       res = gst_pad_push_event (enc->srcpad, event);
877       break;
878     case GST_EVENT_FLUSH_STOP:
879       gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED);
880       res = gst_pad_push_event (enc->srcpad, event);
881       break;
882     case GST_EVENT_CUSTOM_DOWNSTREAM:
883     {
884       const GstStructure *s;
885
886       s = gst_event_get_structure (event);
887
888       if (gst_structure_has_name (s, "GstForceKeyUnit"))
889         theora_enc_force_keyframe (enc);
890       res = gst_pad_push_event (enc->srcpad, event);
891       break;
892     }
893     default:
894       res = gst_pad_push_event (enc->srcpad, event);
895       break;
896   }
897   return res;
898 }
899
900 static gboolean
901 theora_enc_src_event (GstPad * pad, GstEvent * event)
902 {
903   GstTheoraEnc *enc;
904   gboolean res = TRUE;
905
906   enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
907
908   switch (GST_EVENT_TYPE (event)) {
909     case GST_EVENT_CUSTOM_UPSTREAM:
910     {
911       const GstStructure *s;
912
913       s = gst_event_get_structure (event);
914
915       if (gst_structure_has_name (s, "GstForceKeyUnit")) {
916         GST_OBJECT_LOCK (enc);
917         enc->force_keyframe = TRUE;
918         GST_OBJECT_UNLOCK (enc);
919         /* consume the event */
920         res = TRUE;
921         gst_event_unref (event);
922       } else {
923         res = gst_pad_push_event (enc->sinkpad, event);
924       }
925       break;
926     }
927     default:
928       res = gst_pad_push_event (enc->sinkpad, event);
929       break;
930   }
931
932   return res;
933 }
934
935 static gboolean
936 theora_enc_is_discontinuous (GstTheoraEnc * enc, GstClockTime timestamp,
937     GstClockTime duration)
938 {
939   GstClockTimeDiff max_diff;
940   gboolean ret = FALSE;
941
942   /* Allow 3/4 a frame off */
943   max_diff = (enc->info.fps_denominator * GST_SECOND * 3) /
944       (enc->info.fps_numerator * 4);
945
946   if (timestamp != GST_CLOCK_TIME_NONE
947       && enc->expected_ts != GST_CLOCK_TIME_NONE) {
948     if ((GstClockTimeDiff) (timestamp - enc->expected_ts) > max_diff) {
949       GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT
950           " exceeds expected value %" GST_TIME_FORMAT
951           " by too much, marking discontinuity",
952           GST_TIME_ARGS (timestamp), GST_TIME_ARGS (enc->expected_ts));
953       ret = TRUE;
954     }
955   }
956
957   if (GST_CLOCK_TIME_IS_VALID (duration))
958     enc->expected_ts = timestamp + duration;
959   else
960     enc->expected_ts = GST_CLOCK_TIME_NONE;
961
962   return ret;
963 }
964
965 static void
966 theora_enc_init_buffer (th_ycbcr_buffer buf, th_info * info, guint8 * data)
967 {
968   GstVideoFormat format;
969   guint i;
970
971   switch (info->pixel_fmt) {
972     case TH_PF_444:
973       format = GST_VIDEO_FORMAT_Y444;
974       break;
975     case TH_PF_420:
976       format = GST_VIDEO_FORMAT_I420;
977       break;
978     case TH_PF_422:
979       format = GST_VIDEO_FORMAT_Y42B;
980       break;
981     default:
982       g_assert_not_reached ();
983   }
984
985   /* According to Theora developer Timothy Terriberry, the Theora 
986    * encoder will not use memory outside of pic_width/height, even when
987    * the frame size is bigger. The values outside this region will be encoded
988    * to default values.
989    * Due to this, setting the frame's width/height as the buffer width/height
990    * is perfectly ok, even though it does not strictly look ok.
991    */
992   for (i = 0; i < 3; i++) {
993     buf[i].width =
994         gst_video_format_get_component_width (format, i, info->frame_width);
995     buf[i].height =
996         gst_video_format_get_component_height (format, i, info->frame_height);
997
998     buf[i].data =
999         data + gst_video_format_get_component_offset (format, i,
1000         info->pic_width, info->pic_height);
1001     buf[i].stride =
1002         gst_video_format_get_row_stride (format, i, info->pic_width);
1003   }
1004 }
1005
1006 static gboolean
1007 theora_enc_read_multipass_cache (GstTheoraEnc * enc)
1008 {
1009   GstBuffer *cache_buf;
1010   const guint8 *cache_data;
1011   gsize bytes_read = 0, bytes_consumed = 0;
1012   GIOStatus stat = G_IO_STATUS_NORMAL;
1013   gboolean done = FALSE;
1014
1015   while (!done) {
1016     if (gst_adapter_available (enc->multipass_cache_adapter) == 0) {
1017       cache_buf = gst_buffer_new_and_alloc (512);
1018       stat = g_io_channel_read_chars (enc->multipass_cache_fd,
1019           (gchar *) GST_BUFFER_DATA (cache_buf), GST_BUFFER_SIZE (cache_buf),
1020           &bytes_read, NULL);
1021
1022       if (bytes_read <= 0) {
1023         gst_buffer_unref (cache_buf);
1024         break;
1025       } else {
1026         GST_BUFFER_SIZE (cache_buf) = bytes_read;
1027
1028         gst_adapter_push (enc->multipass_cache_adapter, cache_buf);
1029       }
1030     }
1031     if (gst_adapter_available (enc->multipass_cache_adapter) == 0)
1032       break;
1033
1034     bytes_read =
1035         MIN (gst_adapter_available (enc->multipass_cache_adapter), 512);
1036
1037     cache_data = gst_adapter_peek (enc->multipass_cache_adapter, bytes_read);
1038
1039     bytes_consumed =
1040         th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_IN, (guint8 *) cache_data,
1041         bytes_read);
1042     done = bytes_consumed <= 0;
1043     if (bytes_consumed > 0)
1044       gst_adapter_flush (enc->multipass_cache_adapter, bytes_consumed);
1045   }
1046
1047   if (stat == G_IO_STATUS_ERROR || (stat == G_IO_STATUS_EOF && bytes_read == 0)
1048       || bytes_consumed < 0) {
1049     GST_ELEMENT_ERROR (enc, RESOURCE, READ, (NULL),
1050         ("Failed to read multipass cache file"));
1051     return FALSE;
1052   }
1053   return TRUE;
1054 }
1055
1056 static gboolean
1057 theora_enc_write_multipass_cache (GstTheoraEnc * enc, gboolean begin,
1058     gboolean eos)
1059 {
1060   GError *err = NULL;
1061   GIOStatus stat = G_IO_STATUS_NORMAL;
1062   gint bytes_read = 0;
1063   gsize bytes_written = 0;
1064   gchar *buf;
1065
1066   if (begin)
1067     stat = g_io_channel_seek_position (enc->multipass_cache_fd, 0, G_SEEK_SET,
1068         &err);
1069   if (stat != G_IO_STATUS_ERROR) {
1070     do {
1071       bytes_read =
1072           th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_OUT, &buf, sizeof (buf));
1073       if (bytes_read > 0)
1074         g_io_channel_write_chars (enc->multipass_cache_fd, buf, bytes_read,
1075             &bytes_written, NULL);
1076     } while (bytes_read > 0 && bytes_written > 0);
1077
1078   }
1079
1080   if (stat == G_IO_STATUS_ERROR || bytes_read < 0 || bytes_written < 0) {
1081     if (begin) {
1082       if (eos)
1083         GST_ELEMENT_WARNING (enc, RESOURCE, WRITE, (NULL),
1084             ("Failed to seek to beginning of multipass cache file: %s",
1085                 err->message));
1086       else
1087         GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
1088             ("Failed to seek to beginning of multipass cache file: %s",
1089                 err->message));
1090     } else {
1091       GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
1092           ("Failed to write multipass cache file"));
1093     }
1094     if (err)
1095       g_error_free (err);
1096
1097     return FALSE;
1098   }
1099   return TRUE;
1100 }
1101
1102 static GstFlowReturn
1103 theora_enc_chain (GstPad * pad, GstBuffer * buffer)
1104 {
1105   GstTheoraEnc *enc;
1106   ogg_packet op;
1107   GstClockTime timestamp, duration, running_time;
1108   GstFlowReturn ret;
1109   gboolean force_keyframe;
1110
1111   enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
1112
1113   /* we keep track of two timelines.
1114    * - The timestamps from the incomming buffers, which we copy to the outgoing
1115    *   encoded buffers as-is. We need to do this as we simply forward the
1116    *   newsegment events.
1117    * - The running_time of the buffers, which we use to construct the granulepos
1118    *   in the packets.
1119    */
1120   timestamp = GST_BUFFER_TIMESTAMP (buffer);
1121   duration = GST_BUFFER_DURATION (buffer);
1122
1123   running_time =
1124       gst_segment_to_running_time (&enc->segment, GST_FORMAT_TIME, timestamp);
1125   if ((gint64) running_time < 0) {
1126     GST_DEBUG_OBJECT (enc, "Dropping buffer, timestamp: %" GST_TIME_FORMAT,
1127         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
1128     gst_buffer_unref (buffer);
1129     return GST_FLOW_OK;
1130   }
1131
1132   GST_OBJECT_LOCK (enc);
1133   if (enc->bitrate_changed) {
1134     long int bitrate = enc->video_bitrate;
1135
1136     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_BITRATE, &bitrate,
1137         sizeof (long int));
1138     enc->bitrate_changed = FALSE;
1139   }
1140
1141   if (enc->quality_changed) {
1142     long int quality = enc->video_quality;
1143
1144     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_QUALITY, &quality,
1145         sizeof (long int));
1146     enc->quality_changed = FALSE;
1147   }
1148
1149   /* see if we need to schedule a keyframe */
1150   force_keyframe = enc->force_keyframe;
1151   enc->force_keyframe = FALSE;
1152   GST_OBJECT_UNLOCK (enc);
1153
1154   if (force_keyframe) {
1155     GstClockTime stream_time;
1156     GstStructure *s;
1157
1158     stream_time = gst_segment_to_stream_time (&enc->segment,
1159         GST_FORMAT_TIME, timestamp);
1160
1161     s = gst_structure_new ("GstForceKeyUnit",
1162         "timestamp", G_TYPE_UINT64, timestamp,
1163         "stream-time", G_TYPE_UINT64, stream_time,
1164         "running-time", G_TYPE_UINT64, running_time, NULL);
1165
1166     theora_enc_force_keyframe (enc);
1167
1168     gst_pad_push_event (enc->srcpad,
1169         gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s));
1170   }
1171
1172   /* make sure we copy the discont flag to the next outgoing buffer when it's
1173    * set on the incomming buffer */
1174   if (GST_BUFFER_IS_DISCONT (buffer)) {
1175     enc->next_discont = TRUE;
1176   }
1177
1178   if (enc->packetno == 0) {
1179     /* no packets written yet, setup headers */
1180     GstCaps *caps;
1181     GstBuffer *buf;
1182     GSList *buffers = NULL;
1183     int result;
1184
1185     enc->granulepos_offset = 0;
1186     enc->timestamp_offset = 0;
1187
1188     GST_DEBUG_OBJECT (enc, "output headers");
1189     /* Theora streams begin with three headers; the initial header (with
1190        most of the codec setup parameters) which is mandated by the Ogg
1191        bitstream spec.  The second header holds any comment fields.  The
1192        third header holds the bitstream codebook.  We merely need to
1193        make the headers, then pass them to libtheora one at a time;
1194        libtheora handles the additional Ogg bitstream constraints */
1195
1196     /* create the remaining theora headers */
1197     th_comment_clear (&enc->comment);
1198     th_comment_init (&enc->comment);
1199
1200     while ((result =
1201             th_encode_flushheader (enc->encoder, &enc->comment, &op)) > 0) {
1202       ret =
1203           theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
1204           GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf);
1205       if (ret != GST_FLOW_OK) {
1206         goto header_buffer_alloc;
1207       }
1208       buffers = g_slist_prepend (buffers, buf);
1209     }
1210     if (result < 0) {
1211       g_slist_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
1212       g_slist_free (buffers);
1213       goto encoder_disabled;
1214     }
1215
1216     buffers = g_slist_reverse (buffers);
1217
1218     /* mark buffers and put on caps */
1219     caps = gst_pad_get_caps (enc->srcpad);
1220     caps = theora_set_header_on_caps (caps, buffers);
1221     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
1222     gst_pad_set_caps (enc->srcpad, caps);
1223
1224     g_slist_foreach (buffers, (GFunc) gst_buffer_set_caps, caps);
1225
1226     gst_caps_unref (caps);
1227
1228     /* push out the header buffers */
1229     while (buffers) {
1230       buf = buffers->data;
1231       buffers = g_slist_delete_link (buffers, buffers);
1232       if ((ret = theora_push_buffer (enc, buf)) != GST_FLOW_OK) {
1233         g_slist_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
1234         g_slist_free (buffers);
1235         goto header_push;
1236       }
1237     }
1238
1239     enc->granulepos_offset =
1240         gst_util_uint64_scale (running_time, enc->fps_n,
1241         GST_SECOND * enc->fps_d);
1242     enc->timestamp_offset = running_time;
1243     enc->next_ts = 0;
1244   }
1245
1246   {
1247     th_ycbcr_buffer ycbcr;
1248     gint res;
1249
1250     theora_enc_init_buffer (ycbcr, &enc->info, GST_BUFFER_DATA (buffer));
1251
1252     if (theora_enc_is_discontinuous (enc, running_time, duration)) {
1253       theora_enc_reset (enc);
1254       enc->granulepos_offset =
1255           gst_util_uint64_scale (running_time, enc->fps_n,
1256           GST_SECOND * enc->fps_d);
1257       enc->timestamp_offset = running_time;
1258       enc->next_ts = 0;
1259       enc->next_discont = TRUE;
1260     }
1261
1262     if (enc->multipass_cache_fd
1263         && enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS) {
1264       if (!theora_enc_read_multipass_cache (enc)) {
1265         ret = GST_FLOW_ERROR;
1266         goto multipass_read_failed;
1267       }
1268     }
1269
1270     res = th_encode_ycbcr_in (enc->encoder, ycbcr);
1271     /* none of the failure cases can happen here */
1272     g_assert (res == 0);
1273
1274     if (enc->multipass_cache_fd
1275         && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS) {
1276       if (!theora_enc_write_multipass_cache (enc, FALSE, FALSE)) {
1277         ret = GST_FLOW_ERROR;
1278         goto multipass_write_failed;
1279       }
1280     }
1281
1282     ret = GST_FLOW_OK;
1283     while (th_encode_packetout (enc->encoder, 0, &op)) {
1284       GstClockTime next_time;
1285
1286       next_time = th_granule_time (enc->encoder, op.granulepos) * GST_SECOND;
1287
1288       ret =
1289           theora_push_packet (enc, &op, timestamp, enc->next_ts,
1290           next_time - enc->next_ts);
1291
1292       enc->next_ts = next_time;
1293       if (ret != GST_FLOW_OK)
1294         goto data_push;
1295     }
1296     gst_buffer_unref (buffer);
1297   }
1298
1299   return ret;
1300
1301   /* ERRORS */
1302 multipass_read_failed:
1303   {
1304     gst_buffer_unref (buffer);
1305     return ret;
1306   }
1307 multipass_write_failed:
1308   {
1309     gst_buffer_unref (buffer);
1310     return ret;
1311   }
1312 header_buffer_alloc:
1313   {
1314     gst_buffer_unref (buffer);
1315     return ret;
1316   }
1317 header_push:
1318   {
1319     gst_buffer_unref (buffer);
1320     return ret;
1321   }
1322 data_push:
1323   {
1324     gst_buffer_unref (buffer);
1325     return ret;
1326   }
1327 encoder_disabled:
1328   {
1329     GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1330         ("libtheora has been compiled with the encoder disabled"));
1331     gst_buffer_unref (buffer);
1332     return GST_FLOW_ERROR;
1333   }
1334 }
1335
1336 static GstStateChangeReturn
1337 theora_enc_change_state (GstElement * element, GstStateChange transition)
1338 {
1339   GstTheoraEnc *enc;
1340   GstStateChangeReturn ret;
1341
1342   enc = GST_THEORA_ENC (element);
1343
1344   switch (transition) {
1345     case GST_STATE_CHANGE_NULL_TO_READY:
1346       break;
1347     case GST_STATE_CHANGE_READY_TO_PAUSED:
1348       GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state");
1349       th_info_init (&enc->info);
1350       th_comment_init (&enc->comment);
1351       enc->packetno = 0;
1352       enc->force_keyframe = FALSE;
1353
1354       if (enc->multipass_mode >= MULTIPASS_MODE_FIRST_PASS) {
1355         GError *err = NULL;
1356
1357         if (!enc->multipass_cache_file) {
1358           ret = GST_STATE_CHANGE_FAILURE;
1359           GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL), (NULL));
1360           return ret;
1361         }
1362         enc->multipass_cache_fd =
1363             g_io_channel_new_file (enc->multipass_cache_file,
1364             (enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS ? "w" : "r"),
1365             &err);
1366
1367         if (enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS)
1368           enc->multipass_cache_adapter = gst_adapter_new ();
1369
1370         if (!enc->multipass_cache_fd) {
1371           ret = GST_STATE_CHANGE_FAILURE;
1372           GST_ELEMENT_ERROR (enc, RESOURCE, OPEN_READ, (NULL),
1373               ("Failed to open multipass cache file: %s", err->message));
1374           g_error_free (err);
1375           return ret;
1376         }
1377
1378         g_io_channel_set_encoding (enc->multipass_cache_fd, NULL, NULL);
1379       }
1380       break;
1381     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1382       break;
1383     default:
1384       break;
1385   }
1386
1387   ret = parent_class->change_state (element, transition);
1388
1389   switch (transition) {
1390     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1391       break;
1392     case GST_STATE_CHANGE_PAUSED_TO_READY:
1393       GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state");
1394       if (enc->encoder) {
1395         th_encode_free (enc->encoder);
1396         enc->encoder = NULL;
1397       }
1398       th_comment_clear (&enc->comment);
1399       th_info_clear (&enc->info);
1400
1401       theora_enc_clear (enc);
1402       enc->initialised = FALSE;
1403       break;
1404     case GST_STATE_CHANGE_READY_TO_NULL:
1405       break;
1406     default:
1407       break;
1408   }
1409
1410   return ret;
1411 }
1412
1413 static void
1414 theora_enc_set_property (GObject * object, guint prop_id,
1415     const GValue * value, GParamSpec * pspec)
1416 {
1417   GstTheoraEnc *enc = GST_THEORA_ENC (object);
1418
1419   switch (prop_id) {
1420     case PROP_CENTER:
1421     case PROP_BORDER:
1422     case PROP_QUICK:
1423     case PROP_KEYFRAME_THRESHOLD:
1424     case PROP_KEYFRAME_MINDISTANCE:
1425     case PROP_NOISE_SENSITIVITY:
1426     case PROP_SHARPNESS:
1427       /* kept for API compat, but ignored */
1428       break;
1429     case PROP_BITRATE:
1430       GST_OBJECT_LOCK (enc);
1431       enc->video_bitrate = g_value_get_int (value) * 1000;
1432       enc->bitrate_changed = TRUE;
1433       GST_OBJECT_UNLOCK (enc);
1434       break;
1435     case PROP_QUALITY:
1436       GST_OBJECT_LOCK (enc);
1437       if (GST_STATE (enc) >= GST_STATE_PAUSED && enc->video_bitrate > 0) {
1438         GST_WARNING_OBJECT (object, "Can't change from bitrate to quality mode"
1439             " while playing");
1440       } else {
1441         enc->video_quality = g_value_get_int (value);
1442         enc->video_bitrate = 0;
1443         enc->quality_changed = TRUE;
1444       }
1445       GST_OBJECT_UNLOCK (enc);
1446       break;
1447     case PROP_KEYFRAME_AUTO:
1448       enc->keyframe_auto = g_value_get_boolean (value);
1449       break;
1450     case PROP_KEYFRAME_FREQ:
1451       enc->keyframe_freq = g_value_get_int (value);
1452       break;
1453     case PROP_KEYFRAME_FREQ_FORCE:
1454       enc->keyframe_force = g_value_get_int (value);
1455       break;
1456     case PROP_SPEEDLEVEL:
1457       enc->speed_level = g_value_get_int (value);
1458       if (enc->encoder) {
1459         th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level,
1460             sizeof (enc->speed_level));
1461       }
1462       break;
1463     case PROP_VP3_COMPATIBLE:
1464       enc->vp3_compatible = g_value_get_boolean (value);
1465       break;
1466     case PROP_DROP_FRAMES:
1467       enc->drop_frames = g_value_get_boolean (value);
1468       break;
1469     case PROP_CAP_OVERFLOW:
1470       enc->cap_overflow = g_value_get_boolean (value);
1471       break;
1472     case PROP_CAP_UNDERFLOW:
1473       enc->cap_underflow = g_value_get_boolean (value);
1474       break;
1475     case PROP_RATE_BUFFER:
1476       enc->rate_buffer = g_value_get_int (value);
1477       break;
1478     case PROP_MULTIPASS_CACHE_FILE:
1479       enc->multipass_cache_file = g_value_dup_string (value);
1480       break;
1481     case PROP_MULTIPASS_MODE:
1482       enc->multipass_mode = g_value_get_enum (value);
1483       break;
1484     default:
1485       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1486       break;
1487   }
1488 }
1489
1490 static void
1491 theora_enc_get_property (GObject * object, guint prop_id,
1492     GValue * value, GParamSpec * pspec)
1493 {
1494   GstTheoraEnc *enc = GST_THEORA_ENC (object);
1495
1496   switch (prop_id) {
1497     case PROP_CENTER:
1498       g_value_set_boolean (value, TRUE);
1499       break;
1500     case PROP_BORDER:
1501       g_value_set_enum (value, BORDER_BLACK);
1502       break;
1503     case PROP_BITRATE:
1504       GST_OBJECT_LOCK (enc);
1505       g_value_set_int (value, enc->video_bitrate / 1000);
1506       GST_OBJECT_UNLOCK (enc);
1507       break;
1508     case PROP_QUALITY:
1509       GST_OBJECT_LOCK (enc);
1510       g_value_set_int (value, enc->video_quality);
1511       GST_OBJECT_UNLOCK (enc);
1512       break;
1513     case PROP_QUICK:
1514       g_value_set_boolean (value, TRUE);
1515       break;
1516     case PROP_KEYFRAME_AUTO:
1517       g_value_set_boolean (value, enc->keyframe_auto);
1518       break;
1519     case PROP_KEYFRAME_FREQ:
1520       g_value_set_int (value, enc->keyframe_freq);
1521       break;
1522     case PROP_KEYFRAME_FREQ_FORCE:
1523       g_value_set_int (value, enc->keyframe_force);
1524       break;
1525     case PROP_KEYFRAME_THRESHOLD:
1526       g_value_set_int (value, 80);
1527       break;
1528     case PROP_KEYFRAME_MINDISTANCE:
1529       g_value_set_int (value, 8);
1530       break;
1531     case PROP_NOISE_SENSITIVITY:
1532       g_value_set_int (value, 1);
1533       break;
1534     case PROP_SHARPNESS:
1535       g_value_set_int (value, 0);
1536       break;
1537     case PROP_SPEEDLEVEL:
1538       g_value_set_int (value, enc->speed_level);
1539       break;
1540     case PROP_VP3_COMPATIBLE:
1541       g_value_set_boolean (value, enc->vp3_compatible);
1542       break;
1543     case PROP_DROP_FRAMES:
1544       g_value_set_boolean (value, enc->drop_frames);
1545       break;
1546     case PROP_CAP_OVERFLOW:
1547       g_value_set_boolean (value, enc->cap_overflow);
1548       break;
1549     case PROP_CAP_UNDERFLOW:
1550       g_value_set_boolean (value, enc->cap_underflow);
1551       break;
1552     case PROP_RATE_BUFFER:
1553       g_value_set_int (value, enc->rate_buffer);
1554       break;
1555     case PROP_MULTIPASS_CACHE_FILE:
1556       g_value_set_string (value, enc->multipass_cache_file);
1557       break;
1558     case PROP_MULTIPASS_MODE:
1559       g_value_set_enum (value, enc->multipass_mode);
1560       break;
1561     default:
1562       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1563       break;
1564   }
1565 }