tizen 2.3 release
[framework/multimedia/gst-plugins-base0.10.git] / 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 GstCaps *theora_enc_src_caps;
247
248 static void
249 _do_init (GType object_type)
250 {
251   const GInterfaceInfo preset_interface_info = {
252     NULL,                       /* interface_init */
253     NULL,                       /* interface_finalize */
254     NULL                        /* interface_data */
255   };
256
257   g_type_add_interface_static (object_type, GST_TYPE_PRESET,
258       &preset_interface_info);
259 }
260
261 GST_BOILERPLATE_FULL (GstTheoraEnc, gst_theora_enc, GstElement,
262     GST_TYPE_ELEMENT, _do_init);
263
264 static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
265 static gboolean theora_enc_src_event (GstPad * pad, GstEvent * event);
266 static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
267 static GstStateChangeReturn theora_enc_change_state (GstElement * element,
268     GstStateChange transition);
269 static GstCaps *theora_enc_sink_getcaps (GstPad * pad);
270 static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
271 static void theora_enc_get_property (GObject * object, guint prop_id,
272     GValue * value, GParamSpec * pspec);
273 static void theora_enc_set_property (GObject * object, guint prop_id,
274     const GValue * value, GParamSpec * pspec);
275 static void theora_enc_finalize (GObject * object);
276
277 static gboolean theora_enc_write_multipass_cache (GstTheoraEnc * enc,
278     gboolean begin, gboolean eos);
279
280 static char *theora_enc_get_supported_formats (void);
281
282 static void
283 gst_theora_enc_base_init (gpointer g_class)
284 {
285   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
286
287   gst_element_class_add_static_pad_template (element_class,
288       &theora_enc_src_factory);
289   gst_element_class_add_static_pad_template (element_class,
290       &theora_enc_sink_factory);
291   gst_element_class_set_details_simple (element_class,
292       "Theora video encoder", "Codec/Encoder/Video",
293       "encode raw YUV video to a theora stream",
294       "Wim Taymans <wim@fluendo.com>");
295 }
296
297 static void
298 gst_theora_enc_class_init (GstTheoraEncClass * klass)
299 {
300   GObjectClass *gobject_class = (GObjectClass *) klass;
301   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
302   char *caps_string;
303
304   /* query runtime encoder properties */
305   th_enc_ctx *th_ctx;
306   int default_speed_level = THEORA_DEF_SPEEDLEVEL;
307   int max_speed_level = default_speed_level;
308
309   GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
310
311   th_ctx = dummy_encode_ctx ();
312   if (th_ctx) {
313     if (check_speed_level (th_ctx, &default_speed_level, &max_speed_level))
314       GST_WARNING
315           ("Failed to determine settings for the speed-level property.");
316     th_encode_free (th_ctx);
317   }
318
319   gobject_class->set_property = theora_enc_set_property;
320   gobject_class->get_property = theora_enc_get_property;
321   gobject_class->finalize = theora_enc_finalize;
322
323   g_object_class_install_property (gobject_class, PROP_CENTER,
324       g_param_spec_boolean ("center", "Center",
325           "ignored and kept for API compat only", TRUE,
326           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
327   g_object_class_install_property (gobject_class, PROP_BORDER,
328       g_param_spec_enum ("border", "Border",
329           "ignored and kept for API compat only",
330           GST_TYPE_BORDER_MODE, BORDER_BLACK,
331           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
332   /* general encoding stream options */
333   g_object_class_install_property (gobject_class, PROP_BITRATE,
334       g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
335           0, (1 << 24) - 1, THEORA_DEF_BITRATE,
336           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
337           GST_PARAM_MUTABLE_PLAYING));
338   g_object_class_install_property (gobject_class, PROP_QUALITY,
339       g_param_spec_int ("quality", "Quality", "Video quality", 0, 63,
340           THEORA_DEF_QUALITY,
341           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
342           GST_PARAM_MUTABLE_PLAYING));
343   g_object_class_install_property (gobject_class, PROP_QUICK,
344       g_param_spec_boolean ("quick", "Quick",
345           "ignored and kept for API compat only", TRUE,
346           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
347   g_object_class_install_property (gobject_class, PROP_KEYFRAME_AUTO,
348       g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
349           "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
350           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
351   g_object_class_install_property (gobject_class, PROP_KEYFRAME_FREQ,
352       g_param_spec_int ("keyframe-freq", "Keyframe frequency",
353           "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
354           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
355   g_object_class_install_property (gobject_class, PROP_KEYFRAME_FREQ_FORCE,
356       g_param_spec_int ("keyframe-force", "Keyframe force",
357           "Force keyframe every N frames", 1, 32768,
358           THEORA_DEF_KEYFRAME_FREQ_FORCE,
359           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
360   g_object_class_install_property (gobject_class, PROP_KEYFRAME_THRESHOLD,
361       g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
362           "ignored and kept for API compat only", 0, 32768, 80,
363           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
364   g_object_class_install_property (gobject_class, PROP_KEYFRAME_MINDISTANCE,
365       g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
366           "ignored and kept for API compat only", 1, 32768, 8,
367           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
368   g_object_class_install_property (gobject_class, PROP_NOISE_SENSITIVITY,
369       g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
370           "ignored and kept for API compat only", 0, 32768, 1,
371           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
372   g_object_class_install_property (gobject_class, PROP_SHARPNESS,
373       g_param_spec_int ("sharpness", "Sharpness",
374           "ignored and kept for API compat only", 0, 2, 0,
375           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
376   g_object_class_install_property (gobject_class, PROP_SPEEDLEVEL,
377       g_param_spec_int ("speed-level", "Speed level",
378           "Controls the amount of analysis performed when encoding."
379           " Higher values trade compression quality for speed."
380           " This property requires libtheora version >= 1.0"
381           ", and the maximum value may vary based on encoder version.",
382           0, max_speed_level, default_speed_level,
383           (GParamFlags) G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
384           G_PARAM_STATIC_STRINGS));
385   g_object_class_install_property (gobject_class, PROP_VP3_COMPATIBLE,
386       g_param_spec_boolean ("vp3-compatible", "VP3 Compatible",
387           "Disables non-VP3 compatible features",
388           THEORA_DEF_VP3_COMPATIBLE,
389           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
390   g_object_class_install_property (gobject_class, PROP_DROP_FRAMES,
391       g_param_spec_boolean ("drop-frames", "Drop Frames",
392           "Allow or disallow frame dropping",
393           THEORA_DEF_DROP_FRAMES,
394           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
395   g_object_class_install_property (gobject_class, PROP_CAP_OVERFLOW,
396       g_param_spec_boolean ("cap-overflow", "Cap Overflow",
397           "Enable capping of bit reservoir overflows",
398           THEORA_DEF_CAP_OVERFLOW,
399           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
400   g_object_class_install_property (gobject_class, PROP_CAP_UNDERFLOW,
401       g_param_spec_boolean ("cap-underflow", "Cap Underflow",
402           "Enable capping of bit reservoir underflows",
403           THEORA_DEF_CAP_UNDERFLOW,
404           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
405   g_object_class_install_property (gobject_class, PROP_RATE_BUFFER,
406       g_param_spec_int ("rate-buffer", "Rate Control Buffer",
407           "Sets the size of the rate control buffer, in units of frames.  "
408           "The default value of 0 instructs the encoder to automatically "
409           "select an appropriate value",
410           0, 1000, THEORA_DEF_RATE_BUFFER,
411           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
412   g_object_class_install_property (gobject_class, PROP_MULTIPASS_CACHE_FILE,
413       g_param_spec_string ("multipass-cache-file", "Multipass Cache File",
414           "Multipass cache file", THEORA_DEF_MULTIPASS_CACHE_FILE,
415           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
416   g_object_class_install_property (gobject_class, PROP_MULTIPASS_MODE,
417       g_param_spec_enum ("multipass-mode", "Multipass mode",
418           "Single pass or first/second pass", GST_TYPE_MULTIPASS_MODE,
419           THEORA_DEF_MULTIPASS_MODE,
420           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
421
422   caps_string = g_strdup_printf ("video/x-raw-yuv, "
423       "format = (fourcc) { %s }, "
424       "framerate = (fraction) [1/MAX, MAX], "
425       "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]",
426       theora_enc_get_supported_formats ());
427   theora_enc_src_caps = gst_caps_from_string (caps_string);
428   g_free (caps_string);
429
430   gstelement_class->change_state = theora_enc_change_state;
431 }
432
433 static void
434 gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
435 {
436   enc->sinkpad =
437       gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink");
438   gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
439   gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
440   gst_pad_set_getcaps_function (enc->sinkpad, theora_enc_sink_getcaps);
441   gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
442   gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
443
444   enc->srcpad =
445       gst_pad_new_from_static_template (&theora_enc_src_factory, "src");
446   gst_pad_set_event_function (enc->srcpad, theora_enc_src_event);
447   gst_pad_use_fixed_caps (enc->srcpad);
448   gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
449
450   gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED);
451
452   enc->video_bitrate = THEORA_DEF_BITRATE;
453   enc->video_quality = THEORA_DEF_QUALITY;
454   enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
455   enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
456   enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
457
458   enc->expected_ts = GST_CLOCK_TIME_NONE;
459
460   /* enc->speed_level is set to the libtheora default by the constructor */
461   enc->vp3_compatible = THEORA_DEF_VP3_COMPATIBLE;
462   enc->drop_frames = THEORA_DEF_DROP_FRAMES;
463   enc->cap_overflow = THEORA_DEF_CAP_OVERFLOW;
464   enc->cap_underflow = THEORA_DEF_CAP_UNDERFLOW;
465   enc->rate_buffer = THEORA_DEF_RATE_BUFFER;
466
467   enc->multipass_mode = THEORA_DEF_MULTIPASS_MODE;
468   enc->multipass_cache_file = THEORA_DEF_MULTIPASS_CACHE_FILE;
469 }
470
471 static void
472 theora_enc_clear_multipass_cache (GstTheoraEnc * enc)
473 {
474   if (enc->multipass_cache_fd) {
475     g_io_channel_shutdown (enc->multipass_cache_fd, TRUE, NULL);
476     g_io_channel_unref (enc->multipass_cache_fd);
477     enc->multipass_cache_fd = NULL;
478   }
479
480   if (enc->multipass_cache_adapter) {
481     gst_object_unref (enc->multipass_cache_adapter);
482     enc->multipass_cache_adapter = NULL;
483   }
484 }
485
486 static void
487 theora_enc_finalize (GObject * object)
488 {
489   GstTheoraEnc *enc = GST_THEORA_ENC (object);
490
491   GST_DEBUG_OBJECT (enc, "Finalizing");
492   if (enc->encoder)
493     th_encode_free (enc->encoder);
494   th_comment_clear (&enc->comment);
495   th_info_clear (&enc->info);
496   g_free (enc->multipass_cache_file);
497
498   theora_enc_clear_multipass_cache (enc);
499
500   G_OBJECT_CLASS (parent_class)->finalize (object);
501 }
502
503 static void
504 theora_enc_reset (GstTheoraEnc * enc)
505 {
506   ogg_uint32_t keyframe_force;
507   int rate_flags;
508
509   GST_OBJECT_LOCK (enc);
510   enc->info.target_bitrate = enc->video_bitrate;
511   if (enc->quality_changed) {
512     enc->info.quality = enc->video_quality;
513   } else {
514     if (enc->video_bitrate == 0) {
515       enc->info.quality = enc->video_quality;
516     }
517   }
518   enc->bitrate_changed = FALSE;
519   enc->quality_changed = FALSE;
520   GST_OBJECT_UNLOCK (enc);
521
522   if (enc->encoder)
523     th_encode_free (enc->encoder);
524   enc->encoder = th_encode_alloc (&enc->info);
525   /* We ensure this function cannot fail. */
526   g_assert (enc->encoder != NULL);
527   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level,
528       sizeof (enc->speed_level));
529   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_VP3_COMPATIBLE,
530       &enc->vp3_compatible, sizeof (enc->vp3_compatible));
531
532   rate_flags = 0;
533   if (enc->drop_frames)
534     rate_flags |= TH_RATECTL_DROP_FRAMES;
535   if (enc->drop_frames)
536     rate_flags |= TH_RATECTL_CAP_OVERFLOW;
537   if (enc->drop_frames)
538     rate_flags |= TH_RATECTL_CAP_UNDERFLOW;
539   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_FLAGS,
540       &rate_flags, sizeof (rate_flags));
541
542   if (enc->rate_buffer) {
543     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_BUFFER,
544         &enc->rate_buffer, sizeof (enc->rate_buffer));
545   } else {
546     /* FIXME */
547   }
548
549   keyframe_force = enc->keyframe_auto ?
550       enc->keyframe_force : enc->keyframe_freq;
551   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
552       &keyframe_force, sizeof (keyframe_force));
553
554   /* Get placeholder data */
555   if (enc->multipass_cache_fd
556       && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS)
557     theora_enc_write_multipass_cache (enc, TRUE, FALSE);
558 }
559
560 static void
561 theora_enc_clear (GstTheoraEnc * enc)
562 {
563   enc->packetno = 0;
564   enc->bytes_out = 0;
565   enc->granulepos_offset = 0;
566   enc->timestamp_offset = 0;
567
568   enc->next_ts = GST_CLOCK_TIME_NONE;
569   enc->next_discont = FALSE;
570   enc->expected_ts = GST_CLOCK_TIME_NONE;
571 }
572
573 static char *
574 theora_enc_get_supported_formats (void)
575 {
576   th_enc_ctx *encoder;
577   th_info info;
578   static const struct
579   {
580     th_pixel_fmt pixelformat;
581     const char fourcc[5];
582   } formats[] = {
583     {
584     TH_PF_420, "I420"}, {
585     TH_PF_422, "Y42B"}, {
586     TH_PF_444, "Y444"}
587   };
588   GString *string = NULL;
589   guint i;
590
591   th_info_init (&info);
592   info.frame_width = 16;
593   info.frame_height = 16;
594   info.fps_numerator = 25;
595   info.fps_denominator = 1;
596   for (i = 0; i < G_N_ELEMENTS (formats); i++) {
597     info.pixel_fmt = formats[i].pixelformat;
598
599     encoder = th_encode_alloc (&info);
600     if (encoder == NULL)
601       continue;
602
603     GST_LOG ("format %s is supported", formats[i].fourcc);
604     th_encode_free (encoder);
605
606     if (string == NULL) {
607       string = g_string_new (formats[i].fourcc);
608     } else {
609       g_string_append (string, ", ");
610       g_string_append (string, formats[i].fourcc);
611     }
612   }
613   th_info_clear (&info);
614
615   return string == NULL ? NULL : g_string_free (string, FALSE);
616 }
617
618 static GstCaps *
619 theora_enc_sink_getcaps (GstPad * pad)
620 {
621   GstTheoraEnc *encoder;
622   GstPad *peer;
623   GstCaps *caps;
624
625   /* If we already have caps return them */
626   if (GST_PAD_CAPS (pad))
627     return gst_caps_ref (GST_PAD_CAPS (pad));
628
629   encoder = GST_THEORA_ENC (gst_pad_get_parent (pad));
630   if (!encoder)
631     return gst_caps_new_empty ();
632
633   peer = gst_pad_get_peer (encoder->srcpad);
634   if (peer) {
635     const GstCaps *templ_caps;
636     GstCaps *peer_caps, *tmp_caps;
637     GstStructure *s;
638     guint i, n;
639
640     peer_caps = gst_pad_get_caps (peer);
641
642     /* Translate peercaps to YUV */
643     peer_caps = gst_caps_make_writable (peer_caps);
644     n = gst_caps_get_size (peer_caps);
645     for (i = 0; i < n; i++) {
646       s = gst_caps_get_structure (peer_caps, i);
647
648       gst_structure_set_name (s, "video/x-raw-yuv");
649       gst_structure_remove_field (s, "streamheader");
650     }
651
652     templ_caps = gst_pad_get_pad_template_caps (pad);
653
654     tmp_caps = gst_caps_intersect (peer_caps, templ_caps);
655     caps = gst_caps_intersect (tmp_caps, theora_enc_src_caps);
656     gst_caps_unref (tmp_caps);
657     gst_caps_unref (peer_caps);
658     gst_object_unref (peer);
659     peer = NULL;
660   } else {
661     caps = gst_caps_ref (theora_enc_src_caps);
662   }
663
664   gst_object_unref (encoder);
665
666   return caps;
667 }
668
669 static gboolean
670 theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
671 {
672   GstStructure *structure = gst_caps_get_structure (caps, 0);
673   GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
674   guint32 fourcc;
675   const GValue *par;
676   gint fps_n, fps_d;
677
678   gst_structure_get_fourcc (structure, "format", &fourcc);
679   gst_structure_get_int (structure, "width", &enc->width);
680   gst_structure_get_int (structure, "height", &enc->height);
681   gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
682   par = gst_structure_get_value (structure, "pixel-aspect-ratio");
683
684   th_info_clear (&enc->info);
685   th_info_init (&enc->info);
686   /* Theora has a divisible-by-sixteen restriction for the encoded video size but
687    * we can define a picture area using pic_width/pic_height */
688   enc->info.frame_width = GST_ROUND_UP_16 (enc->width);
689   enc->info.frame_height = GST_ROUND_UP_16 (enc->height);
690   enc->info.pic_width = enc->width;
691   enc->info.pic_height = enc->height;
692   switch (fourcc) {
693     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
694       enc->info.pixel_fmt = TH_PF_420;
695       break;
696     case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
697       enc->info.pixel_fmt = TH_PF_422;
698       break;
699     case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
700       enc->info.pixel_fmt = TH_PF_444;
701       break;
702     default:
703       g_assert_not_reached ();
704   }
705
706   enc->info.fps_numerator = enc->fps_n = fps_n;
707   enc->info.fps_denominator = enc->fps_d = fps_d;
708   if (par) {
709     enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
710     enc->par_n = gst_value_get_fraction_numerator (par);
711     enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
712     enc->par_d = gst_value_get_fraction_denominator (par);
713   } else {
714     /* setting them to 0 indicates that the decoder can chose a good aspect
715      * ratio, defaulting to 1/1 */
716     enc->info.aspect_numerator = 0;
717     enc->par_n = 1;
718     enc->info.aspect_denominator = 0;
719     enc->par_d = 1;
720   }
721
722   enc->info.colorspace = TH_CS_UNSPECIFIED;
723
724   /* as done in theora */
725   enc->info.keyframe_granule_shift = _ilog (enc->keyframe_force - 1);
726   GST_DEBUG_OBJECT (enc,
727       "keyframe_frequency_force is %d, granule shift is %d",
728       enc->keyframe_force, enc->info.keyframe_granule_shift);
729
730   theora_enc_reset (enc);
731   enc->initialised = TRUE;
732
733   gst_object_unref (enc);
734
735   return TRUE;
736 }
737
738 static guint64
739 granulepos_add (guint64 granulepos, guint64 addend, gint shift)
740 {
741   guint64 iframe, pframe;
742
743   iframe = granulepos >> shift;
744   pframe = granulepos - (iframe << shift);
745   iframe += addend;
746
747   return (iframe << shift) + pframe;
748 }
749
750 /* prepare a buffer for transmission by passing data through libtheora */
751 static GstFlowReturn
752 theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
753     GstClockTime timestamp, GstClockTime running_time,
754     GstClockTime duration, GstBuffer ** buffer)
755 {
756   GstBuffer *buf;
757   GstFlowReturn ret = GST_FLOW_OK;
758
759   buf = gst_buffer_new_and_alloc (packet->bytes);
760   if (!buf) {
761     GST_WARNING_OBJECT (enc, "Could not allocate buffer");
762     ret = GST_FLOW_ERROR;
763     goto done;
764   }
765
766   memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
767   gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
768   /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
769    * time representation */
770   GST_BUFFER_OFFSET_END (buf) =
771       granulepos_add (packet->granulepos, enc->granulepos_offset,
772       enc->info.keyframe_granule_shift);
773   GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc,
774       GST_BUFFER_OFFSET_END (buf));
775
776   GST_BUFFER_TIMESTAMP (buf) = timestamp;
777   GST_BUFFER_DURATION (buf) = duration;
778
779   if (enc->next_discont) {
780     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
781     enc->next_discont = FALSE;
782   }
783
784   /* th_packet_iskeyframe returns positive for keyframes */
785   if (th_packet_iskeyframe (packet) > 0) {
786     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
787   } else {
788     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
789   }
790   enc->packetno++;
791
792 done:
793   *buffer = buf;
794   return ret;
795 }
796
797 /* push out the buffer and do internal bookkeeping */
798 static GstFlowReturn
799 theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
800 {
801   GstFlowReturn ret;
802
803   enc->bytes_out += GST_BUFFER_SIZE (buffer);
804
805   ret = gst_pad_push (enc->srcpad, buffer);
806
807   return ret;
808 }
809
810 static GstFlowReturn
811 theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
812     GstClockTime timestamp, GstClockTime running_time, GstClockTime duration)
813 {
814   GstBuffer *buf;
815   GstFlowReturn ret;
816
817   ret =
818       theora_buffer_from_packet (enc, packet, timestamp, running_time, duration,
819       &buf);
820   if (ret == GST_FLOW_OK)
821     ret = theora_push_buffer (enc, buf);
822
823   return ret;
824 }
825
826 static GstCaps *
827 theora_set_header_on_caps (GstCaps * caps, GSList * buffers)
828 {
829   GstStructure *structure;
830   GValue array = { 0 };
831   GValue value = { 0 };
832   GstBuffer *buffer;
833   GSList *walk;
834
835   caps = gst_caps_make_writable (caps);
836   structure = gst_caps_get_structure (caps, 0);
837
838   /* put copies of the buffers in a fixed list */
839   g_value_init (&array, GST_TYPE_ARRAY);
840
841   for (walk = buffers; walk; walk = walk->next) {
842     buffer = walk->data;
843
844     /* mark buffer */
845     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
846
847     /* Copy buffer, because we can't use the original -
848      * it creates a circular refcount with the caps<->buffers */
849     buffer = gst_buffer_copy (buffer);
850
851     g_value_init (&value, GST_TYPE_BUFFER);
852     gst_value_set_buffer (&value, buffer);
853     gst_value_array_append_value (&array, &value);
854     g_value_unset (&value);
855
856     /* Unref our copy */
857     gst_buffer_unref (buffer);
858   }
859
860   gst_structure_set_value (structure, "streamheader", &array);
861   g_value_unset (&array);
862
863   return caps;
864 }
865
866 static void
867 theora_enc_force_keyframe (GstTheoraEnc * enc)
868 {
869   GstClockTime next_ts;
870
871   /* make sure timestamps increment after resetting the decoder */
872   next_ts = enc->next_ts + enc->timestamp_offset;
873
874   theora_enc_reset (enc);
875   enc->granulepos_offset =
876       gst_util_uint64_scale (next_ts, enc->fps_n, GST_SECOND * enc->fps_d);
877   enc->timestamp_offset = next_ts;
878   enc->next_ts = 0;
879 }
880
881 static gboolean
882 theora_enc_sink_event (GstPad * pad, GstEvent * event)
883 {
884   GstTheoraEnc *enc;
885   ogg_packet op;
886   gboolean res;
887
888   enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
889
890   switch (GST_EVENT_TYPE (event)) {
891     case GST_EVENT_NEWSEGMENT:
892     {
893       gboolean update;
894       gdouble rate, applied_rate;
895       GstFormat format;
896       gint64 start, stop, time;
897
898       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
899           &format, &start, &stop, &time);
900
901       gst_segment_set_newsegment_full (&enc->segment, update, rate,
902           applied_rate, format, start, stop, time);
903
904       res = gst_pad_push_event (enc->srcpad, event);
905       break;
906     }
907     case GST_EVENT_EOS:
908       if (enc->initialised) {
909         /* push last packet with eos flag, should not be called */
910         while (th_encode_packetout (enc->encoder, 1, &op)) {
911           GstClockTime next_time =
912               th_granule_time (enc->encoder, op.granulepos) * GST_SECOND;
913
914           theora_push_packet (enc, &op, GST_CLOCK_TIME_NONE, enc->next_ts,
915               next_time - enc->next_ts);
916           enc->next_ts = next_time;
917         }
918       }
919       if (enc->initialised && enc->multipass_cache_fd
920           && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS)
921         theora_enc_write_multipass_cache (enc, TRUE, TRUE);
922
923       theora_enc_clear_multipass_cache (enc);
924
925       res = gst_pad_push_event (enc->srcpad, event);
926       break;
927     case GST_EVENT_FLUSH_STOP:
928       gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED);
929       res = gst_pad_push_event (enc->srcpad, event);
930       break;
931     case GST_EVENT_CUSTOM_DOWNSTREAM:
932     {
933       const GstStructure *s;
934
935       s = gst_event_get_structure (event);
936
937       if (gst_structure_has_name (s, "GstForceKeyUnit"))
938         theora_enc_force_keyframe (enc);
939       res = gst_pad_push_event (enc->srcpad, event);
940       break;
941     }
942     default:
943       res = gst_pad_push_event (enc->srcpad, event);
944       break;
945   }
946   return res;
947 }
948
949 static gboolean
950 theora_enc_src_event (GstPad * pad, GstEvent * event)
951 {
952   GstTheoraEnc *enc;
953   gboolean res = TRUE;
954
955   enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
956
957   switch (GST_EVENT_TYPE (event)) {
958     case GST_EVENT_CUSTOM_UPSTREAM:
959     {
960       const GstStructure *s;
961
962       s = gst_event_get_structure (event);
963
964       if (gst_structure_has_name (s, "GstForceKeyUnit")) {
965         GST_OBJECT_LOCK (enc);
966         enc->force_keyframe = TRUE;
967         GST_OBJECT_UNLOCK (enc);
968         /* consume the event */
969         res = TRUE;
970         gst_event_unref (event);
971       } else {
972         res = gst_pad_push_event (enc->sinkpad, event);
973       }
974       break;
975     }
976     default:
977       res = gst_pad_push_event (enc->sinkpad, event);
978       break;
979   }
980
981   return res;
982 }
983
984 static gboolean
985 theora_enc_is_discontinuous (GstTheoraEnc * enc, GstClockTime timestamp,
986     GstClockTime duration)
987 {
988   GstClockTimeDiff max_diff;
989   gboolean ret = FALSE;
990
991   /* Allow 3/4 a frame off */
992   max_diff = (enc->info.fps_denominator * GST_SECOND * 3) /
993       (enc->info.fps_numerator * 4);
994
995   if (timestamp != GST_CLOCK_TIME_NONE
996       && enc->expected_ts != GST_CLOCK_TIME_NONE) {
997     if ((GstClockTimeDiff) (timestamp - enc->expected_ts) > max_diff) {
998       GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT
999           " exceeds expected value %" GST_TIME_FORMAT
1000           " by too much, marking discontinuity",
1001           GST_TIME_ARGS (timestamp), GST_TIME_ARGS (enc->expected_ts));
1002       ret = TRUE;
1003     }
1004   }
1005
1006   if (GST_CLOCK_TIME_IS_VALID (duration))
1007     enc->expected_ts = timestamp + duration;
1008   else
1009     enc->expected_ts = GST_CLOCK_TIME_NONE;
1010
1011   return ret;
1012 }
1013
1014 static void
1015 theora_enc_init_buffer (th_ycbcr_buffer buf, th_info * info, guint8 * data)
1016 {
1017   GstVideoFormat format;
1018   guint i;
1019
1020   switch (info->pixel_fmt) {
1021     case TH_PF_444:
1022       format = GST_VIDEO_FORMAT_Y444;
1023       break;
1024     case TH_PF_420:
1025       format = GST_VIDEO_FORMAT_I420;
1026       break;
1027     case TH_PF_422:
1028       format = GST_VIDEO_FORMAT_Y42B;
1029       break;
1030     default:
1031       g_assert_not_reached ();
1032   }
1033
1034   /* According to Theora developer Timothy Terriberry, the Theora 
1035    * encoder will not use memory outside of pic_width/height, even when
1036    * the frame size is bigger. The values outside this region will be encoded
1037    * to default values.
1038    * Due to this, setting the frame's width/height as the buffer width/height
1039    * is perfectly ok, even though it does not strictly look ok.
1040    */
1041   for (i = 0; i < 3; i++) {
1042     buf[i].width =
1043         gst_video_format_get_component_width (format, i, info->frame_width);
1044     buf[i].height =
1045         gst_video_format_get_component_height (format, i, info->frame_height);
1046
1047     buf[i].data =
1048         data + gst_video_format_get_component_offset (format, i,
1049         info->pic_width, info->pic_height);
1050     buf[i].stride =
1051         gst_video_format_get_row_stride (format, i, info->pic_width);
1052   }
1053 }
1054
1055 static gboolean
1056 theora_enc_read_multipass_cache (GstTheoraEnc * enc)
1057 {
1058   GstBuffer *cache_buf;
1059   const guint8 *cache_data;
1060   gsize bytes_read = 0;
1061   gint bytes_consumed = 0;
1062   GIOStatus stat = G_IO_STATUS_NORMAL;
1063   gboolean done = FALSE;
1064
1065   while (!done) {
1066     if (gst_adapter_available (enc->multipass_cache_adapter) == 0) {
1067       cache_buf = gst_buffer_new_and_alloc (512);
1068       stat = g_io_channel_read_chars (enc->multipass_cache_fd,
1069           (gchar *) GST_BUFFER_DATA (cache_buf), GST_BUFFER_SIZE (cache_buf),
1070           &bytes_read, NULL);
1071
1072       if (bytes_read <= 0) {
1073         gst_buffer_unref (cache_buf);
1074         break;
1075       } else {
1076         GST_BUFFER_SIZE (cache_buf) = bytes_read;
1077
1078         gst_adapter_push (enc->multipass_cache_adapter, cache_buf);
1079       }
1080     }
1081     if (gst_adapter_available (enc->multipass_cache_adapter) == 0)
1082       break;
1083
1084     bytes_read =
1085         MIN (gst_adapter_available (enc->multipass_cache_adapter), 512);
1086
1087     cache_data = gst_adapter_peek (enc->multipass_cache_adapter, bytes_read);
1088
1089     bytes_consumed =
1090         th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_IN, (guint8 *) cache_data,
1091         bytes_read);
1092     done = bytes_consumed <= 0;
1093     if (bytes_consumed > 0)
1094       gst_adapter_flush (enc->multipass_cache_adapter, bytes_consumed);
1095   }
1096
1097   if (stat == G_IO_STATUS_ERROR || (stat == G_IO_STATUS_EOF && bytes_read == 0)
1098       || bytes_consumed < 0) {
1099     GST_ELEMENT_ERROR (enc, RESOURCE, READ, (NULL),
1100         ("Failed to read multipass cache file"));
1101     return FALSE;
1102   }
1103   return TRUE;
1104 }
1105
1106 static gboolean
1107 theora_enc_write_multipass_cache (GstTheoraEnc * enc, gboolean begin,
1108     gboolean eos)
1109 {
1110   GError *err = NULL;
1111   GIOStatus stat = G_IO_STATUS_NORMAL;
1112   gint bytes_read = 0;
1113   gsize bytes_written = 0;
1114   gchar *buf;
1115
1116   if (begin)
1117     stat = g_io_channel_seek_position (enc->multipass_cache_fd, 0, G_SEEK_SET,
1118         &err);
1119   if (stat != G_IO_STATUS_ERROR) {
1120     do {
1121       bytes_read =
1122           th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_OUT, &buf, sizeof (buf));
1123       if (bytes_read > 0)
1124         g_io_channel_write_chars (enc->multipass_cache_fd, buf, bytes_read,
1125             &bytes_written, NULL);
1126     } while (bytes_read > 0 && bytes_written > 0);
1127
1128   }
1129
1130   if (stat == G_IO_STATUS_ERROR || bytes_read < 0) {
1131     if (begin) {
1132       if (eos)
1133         GST_ELEMENT_WARNING (enc, RESOURCE, WRITE, (NULL),
1134             ("Failed to seek to beginning of multipass cache file: %s",
1135                 err->message));
1136       else
1137         GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
1138             ("Failed to seek to beginning of multipass cache file: %s",
1139                 err->message));
1140     } else {
1141       GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
1142           ("Failed to write multipass cache file"));
1143     }
1144     if (err)
1145       g_error_free (err);
1146
1147     return FALSE;
1148   }
1149   return TRUE;
1150 }
1151
1152 static GstFlowReturn
1153 theora_enc_encode_and_push (GstTheoraEnc * enc, ogg_packet op,
1154     GstClockTime timestamp, GstClockTime running_time,
1155     GstClockTime duration, GstBuffer * buffer)
1156 {
1157   GstFlowReturn ret;
1158   th_ycbcr_buffer ycbcr;
1159   gint res;
1160
1161   theora_enc_init_buffer (ycbcr, &enc->info, GST_BUFFER_DATA (buffer));
1162
1163   if (theora_enc_is_discontinuous (enc, running_time, duration)) {
1164     theora_enc_reset (enc);
1165     enc->granulepos_offset =
1166         gst_util_uint64_scale (running_time, enc->fps_n,
1167         GST_SECOND * enc->fps_d);
1168     enc->timestamp_offset = running_time;
1169     enc->next_ts = 0;
1170     enc->next_discont = TRUE;
1171   }
1172
1173   if (enc->multipass_cache_fd
1174       && enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS) {
1175     if (!theora_enc_read_multipass_cache (enc)) {
1176       ret = GST_FLOW_ERROR;
1177       goto multipass_read_failed;
1178     }
1179   }
1180
1181   res = th_encode_ycbcr_in (enc->encoder, ycbcr);
1182   /* none of the failure cases can happen here */
1183   g_assert (res == 0);
1184
1185   if (enc->multipass_cache_fd
1186       && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS) {
1187     if (!theora_enc_write_multipass_cache (enc, FALSE, FALSE)) {
1188       ret = GST_FLOW_ERROR;
1189       goto multipass_write_failed;
1190     }
1191   }
1192
1193   ret = GST_FLOW_OK;
1194   while (th_encode_packetout (enc->encoder, 0, &op)) {
1195     GstClockTime next_time;
1196
1197     next_time = th_granule_time (enc->encoder, op.granulepos) * GST_SECOND;
1198
1199     ret =
1200         theora_push_packet (enc, &op, timestamp, enc->next_ts,
1201         next_time - enc->next_ts);
1202
1203     enc->next_ts = next_time;
1204     if (ret != GST_FLOW_OK)
1205       goto data_push;
1206   }
1207   gst_buffer_unref (buffer);
1208
1209   return ret;
1210
1211   /* ERRORS */
1212 multipass_read_failed:
1213   {
1214     gst_buffer_unref (buffer);
1215     return ret;
1216   }
1217 multipass_write_failed:
1218   {
1219     gst_buffer_unref (buffer);
1220     return ret;
1221   }
1222 data_push:
1223   {
1224     gst_buffer_unref (buffer);
1225     return ret;
1226   }
1227 }
1228
1229 static GstFlowReturn
1230 theora_enc_chain (GstPad * pad, GstBuffer * buffer)
1231 {
1232   GstTheoraEnc *enc;
1233   ogg_packet op;
1234   GstClockTime timestamp, duration, running_time;
1235   GstFlowReturn ret;
1236   gboolean force_keyframe;
1237
1238   enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
1239
1240   /* we keep track of two timelines.
1241    * - The timestamps from the incoming buffers, which we copy to the outgoing
1242    *   encoded buffers as-is. We need to do this as we simply forward the
1243    *   newsegment events.
1244    * - The running_time of the buffers, which we use to construct the granulepos
1245    *   in the packets.
1246    */
1247   timestamp = GST_BUFFER_TIMESTAMP (buffer);
1248   duration = GST_BUFFER_DURATION (buffer);
1249
1250   running_time =
1251       gst_segment_to_running_time (&enc->segment, GST_FORMAT_TIME, timestamp);
1252   if ((gint64) running_time < 0) {
1253     GST_DEBUG_OBJECT (enc, "Dropping buffer, timestamp: %" GST_TIME_FORMAT,
1254         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
1255     gst_buffer_unref (buffer);
1256     return GST_FLOW_OK;
1257   }
1258
1259   GST_OBJECT_LOCK (enc);
1260   if (enc->bitrate_changed) {
1261     long int bitrate = enc->video_bitrate;
1262
1263     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_BITRATE, &bitrate,
1264         sizeof (long int));
1265     enc->bitrate_changed = FALSE;
1266   }
1267
1268   if (enc->quality_changed) {
1269     long int quality = enc->video_quality;
1270
1271     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_QUALITY, &quality,
1272         sizeof (long int));
1273     enc->quality_changed = FALSE;
1274   }
1275
1276   /* see if we need to schedule a keyframe */
1277   force_keyframe = enc->force_keyframe;
1278   enc->force_keyframe = FALSE;
1279   GST_OBJECT_UNLOCK (enc);
1280
1281   if (force_keyframe) {
1282     GstClockTime stream_time;
1283     GstStructure *s;
1284
1285     stream_time = gst_segment_to_stream_time (&enc->segment,
1286         GST_FORMAT_TIME, timestamp);
1287
1288     s = gst_structure_new ("GstForceKeyUnit",
1289         "timestamp", G_TYPE_UINT64, timestamp,
1290         "stream-time", G_TYPE_UINT64, stream_time,
1291         "running-time", G_TYPE_UINT64, running_time, NULL);
1292
1293     theora_enc_force_keyframe (enc);
1294
1295     gst_pad_push_event (enc->srcpad,
1296         gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s));
1297   }
1298
1299   /* make sure we copy the discont flag to the next outgoing buffer when it's
1300    * set on the incoming buffer */
1301   if (GST_BUFFER_IS_DISCONT (buffer)) {
1302     enc->next_discont = TRUE;
1303   }
1304
1305   if (enc->packetno == 0) {
1306     /* no packets written yet, setup headers */
1307     GstCaps *caps;
1308     GstBuffer *buf;
1309     GSList *buffers = NULL;
1310     int result;
1311
1312     enc->granulepos_offset = 0;
1313     enc->timestamp_offset = 0;
1314
1315     GST_DEBUG_OBJECT (enc, "output headers");
1316     /* Theora streams begin with three headers; the initial header (with
1317        most of the codec setup parameters) which is mandated by the Ogg
1318        bitstream spec.  The second header holds any comment fields.  The
1319        third header holds the bitstream codebook.  We merely need to
1320        make the headers, then pass them to libtheora one at a time;
1321        libtheora handles the additional Ogg bitstream constraints */
1322
1323     /* create the remaining theora headers */
1324     th_comment_clear (&enc->comment);
1325     th_comment_init (&enc->comment);
1326
1327     while ((result =
1328             th_encode_flushheader (enc->encoder, &enc->comment, &op)) > 0) {
1329       ret =
1330           theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
1331           GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf);
1332       if (ret != GST_FLOW_OK) {
1333         goto header_buffer_alloc;
1334       }
1335       buffers = g_slist_prepend (buffers, buf);
1336     }
1337     if (result < 0) {
1338       g_slist_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
1339       g_slist_free (buffers);
1340       goto encoder_disabled;
1341     }
1342
1343     buffers = g_slist_reverse (buffers);
1344
1345     /* mark buffers and put on caps */
1346     caps = gst_caps_new_simple ("video/x-theora",
1347         "width", G_TYPE_INT, enc->width,
1348         "height", G_TYPE_INT, enc->height,
1349         "framerate", GST_TYPE_FRACTION, enc->fps_n, enc->fps_d,
1350         "pixel-aspect-ratio", GST_TYPE_FRACTION, enc->par_n, enc->par_d, NULL);
1351     caps = theora_set_header_on_caps (caps, buffers);
1352     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
1353     gst_pad_set_caps (enc->srcpad, caps);
1354
1355     g_slist_foreach (buffers, (GFunc) gst_buffer_set_caps, caps);
1356
1357     gst_caps_unref (caps);
1358
1359     /* push out the header buffers */
1360     while (buffers) {
1361       buf = buffers->data;
1362       buffers = g_slist_delete_link (buffers, buffers);
1363       if ((ret = theora_push_buffer (enc, buf)) != GST_FLOW_OK) {
1364         g_slist_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
1365         g_slist_free (buffers);
1366         goto header_push;
1367       }
1368     }
1369
1370     enc->granulepos_offset =
1371         gst_util_uint64_scale (running_time, enc->fps_n,
1372         GST_SECOND * enc->fps_d);
1373     enc->timestamp_offset = running_time;
1374     enc->next_ts = 0;
1375   }
1376
1377   ret = theora_enc_encode_and_push (enc, op, timestamp, running_time, duration,
1378       buffer);
1379
1380   return ret;
1381
1382   /* ERRORS */
1383 header_buffer_alloc:
1384   {
1385     gst_buffer_unref (buffer);
1386     return ret;
1387   }
1388 header_push:
1389   {
1390     gst_buffer_unref (buffer);
1391     return ret;
1392   }
1393 encoder_disabled:
1394   {
1395     GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1396         ("libtheora has been compiled with the encoder disabled"));
1397     gst_buffer_unref (buffer);
1398     return GST_FLOW_ERROR;
1399   }
1400 }
1401
1402 static GstStateChangeReturn
1403 theora_enc_change_state (GstElement * element, GstStateChange transition)
1404 {
1405   GstTheoraEnc *enc;
1406   GstStateChangeReturn ret;
1407   th_enc_ctx *th_ctx;
1408
1409   enc = GST_THEORA_ENC (element);
1410
1411   switch (transition) {
1412     case GST_STATE_CHANGE_NULL_TO_READY:
1413       th_ctx = dummy_encode_ctx ();
1414       if (!th_ctx) {
1415         GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1416             ("libtheora has been compiled with the encoder disabled"));
1417         return GST_STATE_CHANGE_FAILURE;
1418       }
1419       th_encode_free (th_ctx);
1420       break;
1421     case GST_STATE_CHANGE_READY_TO_PAUSED:
1422       GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state");
1423       th_info_init (&enc->info);
1424       th_comment_init (&enc->comment);
1425       enc->packetno = 0;
1426       enc->force_keyframe = FALSE;
1427
1428       if (enc->multipass_mode >= MULTIPASS_MODE_FIRST_PASS) {
1429         GError *err = NULL;
1430
1431         if (!enc->multipass_cache_file) {
1432           ret = GST_STATE_CHANGE_FAILURE;
1433           GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL), (NULL));
1434           return ret;
1435         }
1436         enc->multipass_cache_fd =
1437             g_io_channel_new_file (enc->multipass_cache_file,
1438             (enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS ? "w" : "r"),
1439             &err);
1440
1441         if (enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS)
1442           enc->multipass_cache_adapter = gst_adapter_new ();
1443
1444         if (!enc->multipass_cache_fd) {
1445           ret = GST_STATE_CHANGE_FAILURE;
1446           GST_ELEMENT_ERROR (enc, RESOURCE, OPEN_READ, (NULL),
1447               ("Failed to open multipass cache file: %s", err->message));
1448           g_error_free (err);
1449           return ret;
1450         }
1451
1452         g_io_channel_set_encoding (enc->multipass_cache_fd, NULL, NULL);
1453       }
1454       break;
1455     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1456       break;
1457     default:
1458       break;
1459   }
1460
1461   ret = parent_class->change_state (element, transition);
1462
1463   switch (transition) {
1464     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1465       break;
1466     case GST_STATE_CHANGE_PAUSED_TO_READY:
1467       GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state");
1468       if (enc->encoder) {
1469         th_encode_free (enc->encoder);
1470         enc->encoder = NULL;
1471       }
1472       th_comment_clear (&enc->comment);
1473       th_info_clear (&enc->info);
1474
1475       theora_enc_clear (enc);
1476       enc->initialised = FALSE;
1477       break;
1478     case GST_STATE_CHANGE_READY_TO_NULL:
1479       break;
1480     default:
1481       break;
1482   }
1483
1484   return ret;
1485 }
1486
1487 static void
1488 theora_enc_set_property (GObject * object, guint prop_id,
1489     const GValue * value, GParamSpec * pspec)
1490 {
1491   GstTheoraEnc *enc = GST_THEORA_ENC (object);
1492
1493   switch (prop_id) {
1494     case PROP_CENTER:
1495     case PROP_BORDER:
1496     case PROP_QUICK:
1497     case PROP_KEYFRAME_THRESHOLD:
1498     case PROP_KEYFRAME_MINDISTANCE:
1499     case PROP_NOISE_SENSITIVITY:
1500     case PROP_SHARPNESS:
1501       /* kept for API compat, but ignored */
1502       GST_WARNING_OBJECT (object, "Obsolete property '%s' ignored",
1503           pspec->name);
1504       break;
1505     case PROP_BITRATE:
1506       GST_OBJECT_LOCK (enc);
1507       enc->video_bitrate = g_value_get_int (value) * 1000;
1508       enc->bitrate_changed = TRUE;
1509       GST_OBJECT_UNLOCK (enc);
1510       break;
1511     case PROP_QUALITY:
1512       GST_OBJECT_LOCK (enc);
1513       if (GST_STATE (enc) >= GST_STATE_PAUSED && enc->video_bitrate > 0) {
1514         GST_WARNING_OBJECT (object, "Can't change from bitrate to quality mode"
1515             " while playing");
1516       } else {
1517         enc->video_quality = g_value_get_int (value);
1518         enc->video_bitrate = 0;
1519         enc->quality_changed = TRUE;
1520       }
1521       GST_OBJECT_UNLOCK (enc);
1522       break;
1523     case PROP_KEYFRAME_AUTO:
1524       enc->keyframe_auto = g_value_get_boolean (value);
1525       break;
1526     case PROP_KEYFRAME_FREQ:
1527       enc->keyframe_freq = g_value_get_int (value);
1528       break;
1529     case PROP_KEYFRAME_FREQ_FORCE:
1530       enc->keyframe_force = g_value_get_int (value);
1531       break;
1532     case PROP_SPEEDLEVEL:
1533       enc->speed_level = g_value_get_int (value);
1534       if (enc->encoder) {
1535         th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level,
1536             sizeof (enc->speed_level));
1537       }
1538       break;
1539     case PROP_VP3_COMPATIBLE:
1540       enc->vp3_compatible = g_value_get_boolean (value);
1541       break;
1542     case PROP_DROP_FRAMES:
1543       enc->drop_frames = g_value_get_boolean (value);
1544       break;
1545     case PROP_CAP_OVERFLOW:
1546       enc->cap_overflow = g_value_get_boolean (value);
1547       break;
1548     case PROP_CAP_UNDERFLOW:
1549       enc->cap_underflow = g_value_get_boolean (value);
1550       break;
1551     case PROP_RATE_BUFFER:
1552       enc->rate_buffer = g_value_get_int (value);
1553       break;
1554     case PROP_MULTIPASS_CACHE_FILE:
1555       enc->multipass_cache_file = g_value_dup_string (value);
1556       break;
1557     case PROP_MULTIPASS_MODE:
1558       enc->multipass_mode = g_value_get_enum (value);
1559       break;
1560     default:
1561       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1562       break;
1563   }
1564 }
1565
1566 static void
1567 theora_enc_get_property (GObject * object, guint prop_id,
1568     GValue * value, GParamSpec * pspec)
1569 {
1570   GstTheoraEnc *enc = GST_THEORA_ENC (object);
1571
1572   switch (prop_id) {
1573     case PROP_CENTER:
1574       g_value_set_boolean (value, TRUE);
1575       break;
1576     case PROP_BORDER:
1577       g_value_set_enum (value, BORDER_BLACK);
1578       break;
1579     case PROP_BITRATE:
1580       GST_OBJECT_LOCK (enc);
1581       g_value_set_int (value, enc->video_bitrate / 1000);
1582       GST_OBJECT_UNLOCK (enc);
1583       break;
1584     case PROP_QUALITY:
1585       GST_OBJECT_LOCK (enc);
1586       g_value_set_int (value, enc->video_quality);
1587       GST_OBJECT_UNLOCK (enc);
1588       break;
1589     case PROP_QUICK:
1590       g_value_set_boolean (value, TRUE);
1591       break;
1592     case PROP_KEYFRAME_AUTO:
1593       g_value_set_boolean (value, enc->keyframe_auto);
1594       break;
1595     case PROP_KEYFRAME_FREQ:
1596       g_value_set_int (value, enc->keyframe_freq);
1597       break;
1598     case PROP_KEYFRAME_FREQ_FORCE:
1599       g_value_set_int (value, enc->keyframe_force);
1600       break;
1601     case PROP_KEYFRAME_THRESHOLD:
1602       g_value_set_int (value, 80);
1603       break;
1604     case PROP_KEYFRAME_MINDISTANCE:
1605       g_value_set_int (value, 8);
1606       break;
1607     case PROP_NOISE_SENSITIVITY:
1608       g_value_set_int (value, 1);
1609       break;
1610     case PROP_SHARPNESS:
1611       g_value_set_int (value, 0);
1612       break;
1613     case PROP_SPEEDLEVEL:
1614       g_value_set_int (value, enc->speed_level);
1615       break;
1616     case PROP_VP3_COMPATIBLE:
1617       g_value_set_boolean (value, enc->vp3_compatible);
1618       break;
1619     case PROP_DROP_FRAMES:
1620       g_value_set_boolean (value, enc->drop_frames);
1621       break;
1622     case PROP_CAP_OVERFLOW:
1623       g_value_set_boolean (value, enc->cap_overflow);
1624       break;
1625     case PROP_CAP_UNDERFLOW:
1626       g_value_set_boolean (value, enc->cap_underflow);
1627       break;
1628     case PROP_RATE_BUFFER:
1629       g_value_set_int (value, enc->rate_buffer);
1630       break;
1631     case PROP_MULTIPASS_CACHE_FILE:
1632       g_value_set_string (value, enc->multipass_cache_file);
1633       break;
1634     case PROP_MULTIPASS_MODE:
1635       g_value_set_enum (value, enc->multipass_mode);
1636       break;
1637     default:
1638       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1639       break;
1640   }
1641 }