2 * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
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.
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.
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.
21 * SECTION:element-theoraenc
22 * @see_also: theoradec, oggmux
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.
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. The #GstTheoraEnc::border and #GstTheoraEnc::center properties
35 * control how this cropping region will be set up.
37 * To control the quality of the encoding, the #GstTheoraEnc::bitrate and
38 * #GstTheoraEnc::quality properties can be used. These two properties are
39 * mutualy exclusive. Setting the bitrate property will produce a constant
40 * bitrate (CBR) stream while setting the quality property will produce a
41 * variable bitrate (VBR) stream.
44 * <title>Example pipeline</title>
46 * gst-launch -v videotestsrc num-buffers=1000 ! theoraenc ! oggmux ! filesink location=videotestsrc.ogg
47 * ]| This example pipeline will encode a test video source to theora muxed in an
48 * ogg container. Refer to the theoradec documentation to decode the create
52 * Last reviewed on 2006-03-01 (0.10.4)
59 #include "gsttheoraenc.h"
62 #include <stdlib.h> /* free */
64 #include <gst/tag/tag.h>
66 #define GST_CAT_DEFAULT theoraenc_debug
67 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
69 /* With libtheora-1.0beta1 the granulepos scheme was changed:
70 * where earlier the granulepos refered to the index/beginning
71 * of a frame, it now refers to the end, which matches the use
72 * in vorbis/speex. There don't seem to be defines for the
73 * theora version we're compiling against, so we'll just use
74 * a run-time check for now. See theora_enc_get_ogg_packet_end_time().
76 static gboolean use_old_granulepos;
78 #define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
80 gst_border_mode_get_type (void)
82 static GType border_mode_type = 0;
83 static const GEnumValue border_mode[] = {
84 {BORDER_NONE, "No Border", "none"},
85 {BORDER_BLACK, "Black Border", "black"},
86 {BORDER_MIRROR, "Mirror image in borders", "mirror"},
90 if (!border_mode_type) {
92 g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
94 return border_mode_type;
97 /* taken from theora/lib/toplevel.c */
99 _ilog (unsigned int v)
110 #define THEORA_DEF_CENTER TRUE
111 #define THEORA_DEF_BORDER BORDER_BLACK
112 #define THEORA_DEF_BITRATE 0
113 #define THEORA_DEF_QUALITY 16
114 #define THEORA_DEF_QUICK TRUE
115 #define THEORA_DEF_KEYFRAME_AUTO TRUE
116 #define THEORA_DEF_KEYFRAME_FREQ 64
117 #define THEORA_DEF_KEYFRAME_FREQ_FORCE 64
118 #define THEORA_DEF_KEYFRAME_THRESHOLD 80
119 #define THEORA_DEF_KEYFRAME_MINDISTANCE 8
120 #define THEORA_DEF_NOISE_SENSITIVITY 1
121 #define THEORA_DEF_SHARPNESS 0
122 #define THEORA_DEF_SPEEDLEVEL 1
133 ARG_KEYFRAME_FREQ_FORCE,
134 ARG_KEYFRAME_THRESHOLD,
135 ARG_KEYFRAME_MINDISTANCE,
136 ARG_NOISE_SENSITIVITY,
142 /* this function does a straight granulepos -> timestamp conversion */
144 granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos)
146 guint64 iframe, pframe;
147 int shift = theoraenc->granule_shift;
150 return GST_CLOCK_TIME_NONE;
152 iframe = granulepos >> shift;
153 pframe = granulepos - (iframe << shift);
155 /* num and den are 32 bit, so we can safely multiply with GST_SECOND */
156 return gst_util_uint64_scale ((guint64) (iframe + pframe),
157 GST_SECOND * theoraenc->info.fps_denominator,
158 theoraenc->info.fps_numerator);
161 static const GstElementDetails theora_enc_details =
162 GST_ELEMENT_DETAILS ("Theora video encoder",
163 "Codec/Encoder/Video",
164 "encode raw YUV video to a theora stream",
165 "Wim Taymans <wim@fluendo.com>");
167 static GstStaticPadTemplate theora_enc_sink_factory =
168 GST_STATIC_PAD_TEMPLATE ("sink",
171 GST_STATIC_CAPS ("video/x-raw-yuv, "
172 "format = (fourcc) I420, "
173 "framerate = (fraction) [0/1, MAX], "
174 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
177 static GstStaticPadTemplate theora_enc_src_factory =
178 GST_STATIC_PAD_TEMPLATE ("src",
181 GST_STATIC_CAPS ("video/x-theora")
185 _do_init (GType object_type)
187 const GInterfaceInfo preset_interface_info = {
188 NULL, /* interface_init */
189 NULL, /* interface_finalize */
190 NULL /* interface_data */
193 g_type_add_interface_static (object_type, GST_TYPE_PRESET,
194 &preset_interface_info);
197 GST_BOILERPLATE_FULL (GstTheoraEnc, gst_theora_enc, GstElement,
198 GST_TYPE_ELEMENT, _do_init);
200 static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
201 static gboolean theora_enc_src_event (GstPad * pad, GstEvent * event);
202 static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
203 static GstStateChangeReturn theora_enc_change_state (GstElement * element,
204 GstStateChange transition);
205 static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
206 static void theora_enc_get_property (GObject * object, guint prop_id,
207 GValue * value, GParamSpec * pspec);
208 static void theora_enc_set_property (GObject * object, guint prop_id,
209 const GValue * value, GParamSpec * pspec);
210 static void theora_enc_finalize (GObject * object);
213 gst_theora_enc_base_init (gpointer g_class)
215 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
217 gst_element_class_add_pad_template (element_class,
218 gst_static_pad_template_get (&theora_enc_src_factory));
219 gst_element_class_add_pad_template (element_class,
220 gst_static_pad_template_get (&theora_enc_sink_factory));
221 gst_element_class_set_details (element_class, &theora_enc_details);
225 gst_theora_enc_class_init (GstTheoraEncClass * klass)
227 GObjectClass *gobject_class = (GObjectClass *) klass;
228 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
230 gobject_class->set_property = theora_enc_set_property;
231 gobject_class->get_property = theora_enc_get_property;
232 gobject_class->finalize = theora_enc_finalize;
234 g_object_class_install_property (gobject_class, ARG_CENTER,
235 g_param_spec_boolean ("center", "Center",
236 "Center image when sizes not multiple of 16", THEORA_DEF_CENTER,
237 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
238 g_object_class_install_property (gobject_class, ARG_BORDER,
239 g_param_spec_enum ("border", "Border",
240 "Border color to add when sizes not multiple of 16",
241 GST_TYPE_BORDER_MODE, THEORA_DEF_BORDER,
242 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
243 /* general encoding stream options */
244 g_object_class_install_property (gobject_class, ARG_BITRATE,
245 g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
246 0, (1 << 24) - 1, THEORA_DEF_BITRATE,
247 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
248 g_object_class_install_property (gobject_class, ARG_QUALITY,
249 g_param_spec_int ("quality", "Quality", "Video quality", 0, 63,
251 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
252 g_object_class_install_property (gobject_class, ARG_QUICK,
253 g_param_spec_boolean ("quick", "Quick", "Quick encoding",
255 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
256 g_object_class_install_property (gobject_class, ARG_KEYFRAME_AUTO,
257 g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
258 "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
259 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
260 g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ,
261 g_param_spec_int ("keyframe-freq", "Keyframe frequency",
262 "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
263 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
264 g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ_FORCE,
265 g_param_spec_int ("keyframe-force", "Keyframe force",
266 "Force keyframe every N frames", 1, 32768,
267 THEORA_DEF_KEYFRAME_FREQ_FORCE,
268 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
269 g_object_class_install_property (gobject_class, ARG_KEYFRAME_THRESHOLD,
270 g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
271 "Keyframe threshold", 0, 32768, THEORA_DEF_KEYFRAME_THRESHOLD,
272 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
273 g_object_class_install_property (gobject_class, ARG_KEYFRAME_MINDISTANCE,
274 g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
275 "Keyframe mindistance", 1, 32768, THEORA_DEF_KEYFRAME_MINDISTANCE,
276 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
277 g_object_class_install_property (gobject_class, ARG_NOISE_SENSITIVITY,
278 g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
279 "Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
280 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
281 g_object_class_install_property (gobject_class, ARG_SHARPNESS,
282 g_param_spec_int ("sharpness", "Sharpness", "Sharpness", 0, 2,
283 THEORA_DEF_SHARPNESS,
284 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
285 g_object_class_install_property (gobject_class, ARG_SPEEDLEVEL,
286 g_param_spec_int ("speed-level", "Speed level",
287 "Controls the amount of motion vector searching done while "
288 "encoding. This property requires libtheora version >= 1.0",
289 0, 2, THEORA_DEF_SPEEDLEVEL,
290 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
292 gstelement_class->change_state = theora_enc_change_state;
293 GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
295 use_old_granulepos = (theora_version_number () <= 0x00030200);
299 gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
302 gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink");
303 gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
304 gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
305 gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
306 gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
309 gst_pad_new_from_static_template (&theora_enc_src_factory, "src");
310 gst_pad_set_event_function (enc->srcpad, theora_enc_src_event);
311 gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
313 gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED);
315 enc->center = THEORA_DEF_CENTER;
316 enc->border = THEORA_DEF_BORDER;
318 enc->video_bitrate = THEORA_DEF_BITRATE;
319 enc->video_quality = THEORA_DEF_QUALITY;
320 enc->quick = THEORA_DEF_QUICK;
321 enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
322 enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
323 enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
324 enc->keyframe_threshold = THEORA_DEF_KEYFRAME_THRESHOLD;
325 enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
326 enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
327 enc->sharpness = THEORA_DEF_SHARPNESS;
329 enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
330 GST_DEBUG_OBJECT (enc,
331 "keyframe_frequency_force is %d, granule shift is %d",
332 enc->info.keyframe_frequency_force, enc->granule_shift);
333 enc->expected_ts = GST_CLOCK_TIME_NONE;
335 enc->speed_level = THEORA_DEF_SPEEDLEVEL;
339 theora_enc_finalize (GObject * object)
341 GstTheoraEnc *enc = GST_THEORA_ENC (object);
343 GST_DEBUG_OBJECT (enc, "Finalizing");
344 theora_clear (&enc->state);
345 theora_comment_clear (&enc->comment);
346 theora_info_clear (&enc->info);
348 G_OBJECT_CLASS (parent_class)->finalize (object);
352 theora_enc_reset (GstTheoraEnc * enc)
356 theora_clear (&enc->state);
357 result = theora_encode_init (&enc->state, &enc->info);
358 /* We ensure this function cannot fail. */
359 g_assert (result == 0);
360 #ifdef TH_ENCCTL_SET_SPLEVEL
361 theora_control (&enc->state, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level,
362 sizeof (enc->speed_level));
367 theora_enc_clear (GstTheoraEnc * enc)
371 enc->granulepos_offset = 0;
372 enc->timestamp_offset = 0;
374 enc->next_ts = GST_CLOCK_TIME_NONE;
375 enc->next_discont = FALSE;
376 enc->expected_ts = GST_CLOCK_TIME_NONE;
380 theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
382 GstStructure *structure = gst_caps_get_structure (caps, 0);
383 GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
387 gst_structure_get_int (structure, "width", &enc->width);
388 gst_structure_get_int (structure, "height", &enc->height);
389 gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
390 par = gst_structure_get_value (structure, "pixel-aspect-ratio");
392 theora_info_clear (&enc->info);
393 theora_info_init (&enc->info);
394 /* Theora has a divisible-by-sixteen restriction for the encoded video size but
395 * we can define a visible area using the frame_width/frame_height */
396 enc->info_width = enc->info.width = (enc->width + 15) & ~15;
397 enc->info_height = enc->info.height = (enc->height + 15) & ~15;
398 enc->info.frame_width = enc->width;
399 enc->info.frame_height = enc->height;
401 /* center image if needed */
403 /* make sure offset is even, for easier decoding */
404 enc->offset_x = GST_ROUND_UP_2 ((enc->info_width - enc->width) / 2);
405 enc->offset_y = GST_ROUND_UP_2 ((enc->info_height - enc->height) / 2);
410 enc->info.offset_x = enc->offset_x;
411 enc->info.offset_y = enc->offset_y;
413 enc->info.fps_numerator = enc->fps_n = fps_n;
414 enc->info.fps_denominator = enc->fps_d = fps_d;
416 enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
417 enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
419 /* setting them to 0 indicates that the decoder can chose a good aspect
420 * ratio, defaulting to 1/1 */
421 enc->info.aspect_numerator = 0;
422 enc->info.aspect_denominator = 0;
425 enc->info.colorspace = OC_CS_UNSPECIFIED;
426 enc->info.target_bitrate = enc->video_bitrate;
427 enc->info.quality = enc->video_quality;
429 enc->info.dropframes_p = 0;
430 enc->info.quick_p = (enc->quick ? 1 : 0);
431 enc->info.keyframe_auto_p = (enc->keyframe_auto ? 1 : 0);
432 enc->info.keyframe_frequency = enc->keyframe_freq;
433 enc->info.keyframe_frequency_force = enc->keyframe_force;
434 enc->info.keyframe_data_target_bitrate = enc->video_bitrate * 1.5;
435 enc->info.keyframe_auto_threshold = enc->keyframe_threshold;
436 enc->info.keyframe_mindistance = enc->keyframe_mindistance;
437 enc->info.noise_sensitivity = enc->noise_sensitivity;
438 enc->info.sharpness = enc->sharpness;
440 /* as done in theora */
441 enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
442 GST_DEBUG_OBJECT (enc,
443 "keyframe_frequency_force is %d, granule shift is %d",
444 enc->info.keyframe_frequency_force, enc->granule_shift);
446 theora_enc_reset (enc);
447 enc->initialised = TRUE;
449 gst_object_unref (enc);
455 granulepos_add (guint64 granulepos, guint64 addend, gint shift)
457 guint64 iframe, pframe;
459 iframe = granulepos >> shift;
460 pframe = granulepos - (iframe << shift);
463 return (iframe << shift) + pframe;
466 /* prepare a buffer for transmission by passing data through libtheora */
468 theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
469 GstClockTime timestamp, GstClockTime running_time,
470 GstClockTime duration, GstBuffer ** buffer)
473 GstFlowReturn ret = GST_FLOW_OK;
475 buf = gst_buffer_new_and_alloc (packet->bytes);
477 GST_WARNING_OBJECT (enc, "Could not allocate buffer");
478 ret = GST_FLOW_ERROR;
482 memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
483 gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
484 /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
485 * time representation */
486 GST_BUFFER_OFFSET_END (buf) =
487 granulepos_add (packet->granulepos, enc->granulepos_offset,
489 GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc,
490 GST_BUFFER_OFFSET_END (buf));
492 GST_BUFFER_TIMESTAMP (buf) = timestamp;
493 GST_BUFFER_DURATION (buf) = duration;
495 if (enc->next_discont) {
496 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
497 enc->next_discont = FALSE;
500 /* the second most significant bit of the first data byte is cleared
502 if ((packet->packet[0] & 0x40) == 0) {
503 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
505 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
514 /* push out the buffer and do internal bookkeeping */
516 theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
520 enc->bytes_out += GST_BUFFER_SIZE (buffer);
522 ret = gst_pad_push (enc->srcpad, buffer);
528 theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
529 GstClockTime timestamp, GstClockTime running_time, GstClockTime duration)
535 theora_buffer_from_packet (enc, packet, timestamp, running_time, duration,
537 if (ret == GST_FLOW_OK)
538 ret = theora_push_buffer (enc, buf);
544 theora_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
545 GstBuffer * buf2, GstBuffer * buf3)
547 GstStructure *structure;
548 GValue array = { 0 };
549 GValue value = { 0 };
551 caps = gst_caps_make_writable (caps);
552 structure = gst_caps_get_structure (caps, 0);
555 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
556 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
557 GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
559 /* Copy buffers, because we can't use the originals -
560 * it creates a circular refcount with the caps<->buffers */
561 buf1 = gst_buffer_copy (buf1);
562 buf2 = gst_buffer_copy (buf2);
563 buf3 = gst_buffer_copy (buf3);
565 /* put copies of the buffers in a fixed list */
566 g_value_init (&array, GST_TYPE_ARRAY);
568 g_value_init (&value, GST_TYPE_BUFFER);
569 gst_value_set_buffer (&value, buf1);
570 gst_value_array_append_value (&array, &value);
571 g_value_unset (&value);
573 g_value_init (&value, GST_TYPE_BUFFER);
574 gst_value_set_buffer (&value, buf2);
575 gst_value_array_append_value (&array, &value);
576 g_value_unset (&value);
578 g_value_init (&value, GST_TYPE_BUFFER);
579 gst_value_set_buffer (&value, buf3);
580 gst_value_array_append_value (&array, &value);
581 g_value_unset (&value);
583 gst_structure_set_value (structure, "streamheader", &array);
584 g_value_unset (&array);
586 /* Unref our copies */
587 gst_buffer_unref (buf1);
588 gst_buffer_unref (buf2);
589 gst_buffer_unref (buf3);
595 theora_enc_get_ogg_packet_end_time (GstTheoraEnc * enc, ogg_packet * op)
597 ogg_int64_t end_granule;
599 /* FIXME: remove this hack once we depend on libtheora >= 1.0beta1 */
600 if (G_UNLIKELY (use_old_granulepos)) {
601 /* This is where we hack around theora's broken idea of what granulepos
602 * is -- normally we wouldn't need to add the 1, because granulepos
603 * should be the presentation time of the last sample in the packet, but
604 * theora starts with 0 instead of 1... (update: this only applies to old
605 * bitstream/theora versions, this is fixed with bitstream version 3.2.1) */
606 end_granule = granulepos_add (op->granulepos, 1, enc->granule_shift);
608 end_granule = op->granulepos;
610 return theora_granule_time (&enc->state, end_granule) * GST_SECOND;
614 theora_enc_force_keyframe (GstTheoraEnc * enc)
616 GstClockTime next_ts;
618 /* make sure timestamps increment after resetting the decoder */
619 next_ts = enc->next_ts + enc->timestamp_offset;
621 theora_enc_reset (enc);
622 enc->granulepos_offset =
623 gst_util_uint64_scale (next_ts, enc->fps_n, GST_SECOND * enc->fps_d);
624 enc->timestamp_offset = next_ts;
629 theora_enc_sink_event (GstPad * pad, GstEvent * event)
635 enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
637 switch (GST_EVENT_TYPE (event)) {
638 case GST_EVENT_NEWSEGMENT:
641 gdouble rate, applied_rate;
643 gint64 start, stop, time;
645 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
646 &format, &start, &stop, &time);
648 gst_segment_set_newsegment_full (&enc->segment, update, rate,
649 applied_rate, format, start, stop, time);
651 res = gst_pad_push_event (enc->srcpad, event);
655 if (enc->initialised) {
656 /* push last packet with eos flag, should not be called */
657 while (theora_encode_packetout (&enc->state, 1, &op)) {
658 GstClockTime next_time =
659 theora_enc_get_ogg_packet_end_time (enc, &op);
661 theora_push_packet (enc, &op, GST_CLOCK_TIME_NONE, enc->next_ts,
662 next_time - enc->next_ts);
663 enc->next_ts = next_time;
666 res = gst_pad_push_event (enc->srcpad, event);
668 case GST_EVENT_FLUSH_STOP:
669 gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED);
670 res = gst_pad_push_event (enc->srcpad, event);
672 case GST_EVENT_CUSTOM_DOWNSTREAM:
674 const GstStructure *s;
676 s = gst_event_get_structure (event);
678 if (gst_structure_has_name (s, "GstForceKeyUnit"))
679 theora_enc_force_keyframe (enc);
680 res = gst_pad_push_event (enc->srcpad, event);
684 res = gst_pad_push_event (enc->srcpad, event);
691 theora_enc_src_event (GstPad * pad, GstEvent * event)
696 enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
698 switch (GST_EVENT_TYPE (event)) {
699 case GST_EVENT_CUSTOM_UPSTREAM:
701 const GstStructure *s;
703 s = gst_event_get_structure (event);
705 if (gst_structure_has_name (s, "GstForceKeyUnit")) {
706 GST_OBJECT_LOCK (enc);
707 enc->force_keyframe = TRUE;
708 GST_OBJECT_UNLOCK (enc);
709 /* consume the event */
711 gst_event_unref (event);
713 res = gst_pad_push_event (enc->sinkpad, event);
718 res = gst_pad_push_event (enc->sinkpad, event);
726 theora_enc_is_discontinuous (GstTheoraEnc * enc, GstClockTime timestamp,
727 GstClockTime duration)
729 GstClockTimeDiff max_diff;
730 gboolean ret = FALSE;
732 /* Allow 3/4 a frame off */
733 max_diff = (enc->info.fps_denominator * GST_SECOND * 3) /
734 (enc->info.fps_numerator * 4);
736 if (timestamp != GST_CLOCK_TIME_NONE
737 && enc->expected_ts != GST_CLOCK_TIME_NONE) {
738 if ((GstClockTimeDiff) (timestamp - enc->expected_ts) > max_diff) {
739 GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT
740 " exceeds expected value %" GST_TIME_FORMAT
741 " by too much, marking discontinuity",
742 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (enc->expected_ts));
747 if (GST_CLOCK_TIME_IS_VALID (duration))
748 enc->expected_ts = timestamp + duration;
750 enc->expected_ts = GST_CLOCK_TIME_NONE;
756 theora_enc_init_yuv_buffer (yuv_buffer * yuv,
757 guint8 * data, gint width, gint height)
759 yuv->y_width = width;
760 yuv->y_height = height;
761 yuv->y_stride = GST_ROUND_UP_4 (width);
763 yuv->uv_width = width / 2;
764 yuv->uv_height = height / 2;
765 yuv->uv_stride = GST_ROUND_UP_8 (width) / 2;
768 yuv->u = yuv->y + GST_ROUND_UP_2 (height) * yuv->y_stride;
769 yuv->v = yuv->u + GST_ROUND_UP_2 (height) / 2 * yuv->uv_stride;
773 theora_enc_resize_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
777 guchar *dest_y, *src_y;
778 guchar *dest_u, *src_u;
779 guchar *dest_v, *src_v;
780 gint src_y_stride, src_uv_stride;
781 gint dst_y_stride, dst_uv_stride;
783 gint cwidth, cheight;
784 gint offset_x, right_x, right_border;
787 if (enc->width == enc->info_width && enc->height == enc->info_height) {
788 GST_LOG_OBJECT (enc, "no cropping/conversion needed");
792 GST_LOG_OBJECT (enc, "cropping/conversion needed for strides");
793 /* source width/height */
795 height = enc->height;
796 /* soucre chroma width/height */
798 cheight = height / 2;
800 /* source strides as defined in videotestsrc */
801 src_y_stride = GST_ROUND_UP_4 (width);
802 src_uv_stride = GST_ROUND_UP_8 (width) / 2;
804 /* destination strides from the real picture width */
805 dst_y_stride = enc->info_width;
806 dst_uv_stride = enc->info_width / 2;
808 y_size = enc->info_width * enc->info_height;
810 newbuf = gst_buffer_new_and_alloc (y_size * 3 / 2);
812 gst_buffer_unref (buffer);
815 GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET_NONE;
816 gst_buffer_set_caps (newbuf, GST_PAD_CAPS (enc->srcpad));
818 dest_y = GST_BUFFER_DATA (newbuf);
819 dest_u = dest_y + y_size;
820 dest_v = dest_u + y_size / 4;
822 src_y = GST_BUFFER_DATA (buffer);
823 src_u = src_y + src_y_stride * GST_ROUND_UP_2 (height);
824 src_v = src_u + src_uv_stride * GST_ROUND_UP_2 (height) / 2;
826 if (enc->border != BORDER_NONE) {
827 /* fill top border */
828 for (i = 0; i < enc->offset_y; i++) {
829 memset (dest_y, 0, dst_y_stride);
830 dest_y += dst_y_stride;
833 dest_y += dst_y_stride * enc->offset_y;
836 offset_x = enc->offset_x;
837 right_x = width + enc->offset_x;
838 right_border = dst_y_stride - right_x;
841 for (i = 0; i < height; i++) {
842 memcpy (dest_y + offset_x, src_y, width);
843 if (enc->border != BORDER_NONE) {
844 memset (dest_y, 0, offset_x);
845 memset (dest_y + right_x, 0, right_border);
848 dest_y += dst_y_stride;
849 src_y += src_y_stride;
852 if (enc->border != BORDER_NONE) {
853 /* fill bottom border */
854 for (i = height + enc->offset_y; i < enc->info.height; i++) {
855 memset (dest_y, 0, dst_y_stride);
856 dest_y += dst_y_stride;
859 /* fill top border chroma */
860 for (i = 0; i < enc->offset_y / 2; i++) {
861 memset (dest_u, 128, dst_uv_stride);
862 memset (dest_v, 128, dst_uv_stride);
863 dest_u += dst_uv_stride;
864 dest_v += dst_uv_stride;
867 dest_u += dst_uv_stride * enc->offset_y / 2;
868 dest_v += dst_uv_stride * enc->offset_y / 2;
871 offset_x = enc->offset_x / 2;
872 right_x = cwidth + offset_x;
873 right_border = dst_uv_stride - right_x;
876 for (i = 0; i < cheight; i++) {
877 memcpy (dest_v + offset_x, src_v, cwidth);
878 memcpy (dest_u + offset_x, src_u, cwidth);
880 if (enc->border != BORDER_NONE) {
881 memset (dest_u, 128, offset_x);
882 memset (dest_u + right_x, 128, right_border);
883 memset (dest_v, 128, offset_x);
884 memset (dest_v + right_x, 128, right_border);
887 dest_u += dst_uv_stride;
888 dest_v += dst_uv_stride;
889 src_u += src_uv_stride;
890 src_v += src_uv_stride;
893 if (enc->border != BORDER_NONE) {
894 /* fill bottom border */
895 for (i = cheight + enc->offset_y / 2; i < enc->info_height / 2; i++) {
896 memset (dest_u, 128, dst_uv_stride);
897 memset (dest_v, 128, dst_uv_stride);
898 dest_u += dst_uv_stride;
899 dest_v += dst_uv_stride;
903 gst_buffer_unref (buffer);
908 theora_enc_chain (GstPad * pad, GstBuffer * buffer)
912 GstClockTime timestamp, duration, running_time;
914 gboolean force_keyframe;
916 enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
918 /* we keep track of two timelines.
919 * - The timestamps from the incomming buffers, which we copy to the outgoing
920 * encoded buffers as-is. We need to do this as we simply forward the
922 * - The running_time of the buffers, which we use to construct the granulepos
925 timestamp = GST_BUFFER_TIMESTAMP (buffer);
926 duration = GST_BUFFER_DURATION (buffer);
929 gst_segment_to_running_time (&enc->segment, GST_FORMAT_TIME, timestamp);
930 if ((gint64) running_time < 0) {
931 GST_DEBUG_OBJECT (enc, "Dropping buffer, timestamp: %" GST_TIME_FORMAT,
932 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
933 gst_buffer_unref (buffer);
937 /* see if we need to schedule a keyframe */
938 GST_OBJECT_LOCK (enc);
939 force_keyframe = enc->force_keyframe;
940 enc->force_keyframe = FALSE;
941 GST_OBJECT_UNLOCK (enc);
943 if (force_keyframe) {
944 GstClockTime stream_time;
947 stream_time = gst_segment_to_stream_time (&enc->segment,
948 GST_FORMAT_TIME, timestamp);
950 s = gst_structure_new ("GstForceKeyUnit",
951 "timestamp", G_TYPE_UINT64, timestamp,
952 "stream-time", G_TYPE_UINT64, stream_time,
953 "running-time", G_TYPE_UINT64, running_time, NULL);
955 theora_enc_force_keyframe (enc);
957 gst_pad_push_event (enc->srcpad,
958 gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s));
961 /* make sure we copy the discont flag to the next outgoing buffer when it's
962 * set on the incomming buffer */
963 if (GST_BUFFER_IS_DISCONT (buffer)) {
964 enc->next_discont = TRUE;
967 if (enc->packetno == 0) {
968 /* no packets written yet, setup headers */
970 GstBuffer *buf1, *buf2, *buf3;
972 enc->granulepos_offset = 0;
973 enc->timestamp_offset = 0;
975 GST_DEBUG_OBJECT (enc, "output headers");
976 /* Theora streams begin with three headers; the initial header (with
977 most of the codec setup parameters) which is mandated by the Ogg
978 bitstream spec. The second header holds any comment fields. The
979 third header holds the bitstream codebook. We merely need to
980 make the headers, then pass them to libtheora one at a time;
981 libtheora handles the additional Ogg bitstream constraints */
983 /* first packet will get its own page automatically */
984 if (theora_encode_header (&enc->state, &op) != 0)
985 goto encoder_disabled;
988 theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
989 GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf1);
990 if (ret != GST_FLOW_OK) {
991 goto header_buffer_alloc;
994 /* create the remaining theora headers */
995 theora_comment_clear (&enc->comment);
996 theora_comment_init (&enc->comment);
998 if (theora_encode_comment (&enc->comment, &op) != 0)
999 goto encoder_disabled;
1002 theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
1003 GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf2);
1004 /* Theora expects us to put this packet buffer into an ogg page,
1005 * in which case it becomes the ogg library's responsibility to
1006 * free it. Since we're copying and outputting a gst_buffer,
1007 * we need to free it ourselves. */
1011 if (ret != GST_FLOW_OK) {
1012 gst_buffer_unref (buf1);
1013 goto header_buffer_alloc;
1016 if (theora_encode_tables (&enc->state, &op) != 0)
1017 goto encoder_disabled;
1020 theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
1021 GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf3);
1022 if (ret != GST_FLOW_OK) {
1023 gst_buffer_unref (buf1);
1024 gst_buffer_unref (buf2);
1025 goto header_buffer_alloc;
1028 /* mark buffers and put on caps */
1029 caps = gst_pad_get_caps (enc->srcpad);
1030 caps = theora_set_header_on_caps (caps, buf1, buf2, buf3);
1031 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
1032 gst_pad_set_caps (enc->srcpad, caps);
1034 gst_buffer_set_caps (buf1, caps);
1035 gst_buffer_set_caps (buf2, caps);
1036 gst_buffer_set_caps (buf3, caps);
1038 gst_caps_unref (caps);
1040 /* push out the header buffers */
1041 if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK) {
1042 gst_buffer_unref (buf2);
1043 gst_buffer_unref (buf3);
1046 if ((ret = theora_push_buffer (enc, buf2)) != GST_FLOW_OK) {
1047 gst_buffer_unref (buf3);
1050 if ((ret = theora_push_buffer (enc, buf3)) != GST_FLOW_OK) {
1054 enc->granulepos_offset =
1055 gst_util_uint64_scale (running_time, enc->fps_n,
1056 GST_SECOND * enc->fps_d);
1057 enc->timestamp_offset = running_time;
1065 buffer = theora_enc_resize_buffer (enc, buffer);
1067 return GST_FLOW_ERROR;
1069 theora_enc_init_yuv_buffer (&yuv, GST_BUFFER_DATA (buffer), enc->info_width,
1072 if (theora_enc_is_discontinuous (enc, running_time, duration)) {
1073 theora_enc_reset (enc);
1074 enc->granulepos_offset =
1075 gst_util_uint64_scale (running_time, enc->fps_n,
1076 GST_SECOND * enc->fps_d);
1077 enc->timestamp_offset = running_time;
1079 enc->next_discont = TRUE;
1082 res = theora_encode_YUVin (&enc->state, &yuv);
1083 /* none of the failure cases can happen here */
1084 g_assert (res == 0);
1087 while (theora_encode_packetout (&enc->state, 0, &op)) {
1088 GstClockTime next_time;
1090 next_time = theora_enc_get_ogg_packet_end_time (enc, &op);
1093 theora_push_packet (enc, &op, timestamp, enc->next_ts,
1094 next_time - enc->next_ts);
1096 enc->next_ts = next_time;
1097 if (ret != GST_FLOW_OK)
1100 gst_buffer_unref (buffer);
1106 header_buffer_alloc:
1108 gst_buffer_unref (buffer);
1113 gst_buffer_unref (buffer);
1118 gst_buffer_unref (buffer);
1123 GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1124 ("libtheora has been compiled with the encoder disabled"));
1125 gst_buffer_unref (buffer);
1126 return GST_FLOW_ERROR;
1130 static GstStateChangeReturn
1131 theora_enc_change_state (GstElement * element, GstStateChange transition)
1134 GstStateChangeReturn ret;
1136 enc = GST_THEORA_ENC (element);
1138 switch (transition) {
1139 case GST_STATE_CHANGE_NULL_TO_READY:
1141 case GST_STATE_CHANGE_READY_TO_PAUSED:
1142 GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state");
1143 theora_info_init (&enc->info);
1144 theora_comment_init (&enc->comment);
1146 enc->force_keyframe = FALSE;
1148 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1154 ret = parent_class->change_state (element, transition);
1156 switch (transition) {
1157 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1159 case GST_STATE_CHANGE_PAUSED_TO_READY:
1160 GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state");
1161 theora_clear (&enc->state);
1162 theora_comment_clear (&enc->comment);
1163 theora_info_clear (&enc->info);
1165 theora_enc_clear (enc);
1166 enc->initialised = FALSE;
1168 case GST_STATE_CHANGE_READY_TO_NULL:
1178 theora_enc_set_property (GObject * object, guint prop_id,
1179 const GValue * value, GParamSpec * pspec)
1181 GstTheoraEnc *enc = GST_THEORA_ENC (object);
1185 enc->center = g_value_get_boolean (value);
1188 enc->border = g_value_get_enum (value);
1191 enc->video_bitrate = g_value_get_int (value) * 1000;
1192 enc->video_quality = 0;
1195 enc->video_quality = g_value_get_int (value);
1196 enc->video_bitrate = 0;
1199 enc->quick = g_value_get_boolean (value);
1201 case ARG_KEYFRAME_AUTO:
1202 enc->keyframe_auto = g_value_get_boolean (value);
1204 case ARG_KEYFRAME_FREQ:
1205 enc->keyframe_freq = g_value_get_int (value);
1207 case ARG_KEYFRAME_FREQ_FORCE:
1208 enc->keyframe_force = g_value_get_int (value);
1210 case ARG_KEYFRAME_THRESHOLD:
1211 enc->keyframe_threshold = g_value_get_int (value);
1213 case ARG_KEYFRAME_MINDISTANCE:
1214 enc->keyframe_mindistance = g_value_get_int (value);
1216 case ARG_NOISE_SENSITIVITY:
1217 enc->noise_sensitivity = g_value_get_int (value);
1220 enc->sharpness = g_value_get_int (value);
1222 case ARG_SPEEDLEVEL:
1223 #ifdef TH_ENCCTL_SET_SPLEVEL
1224 enc->speed_level = g_value_get_int (value);
1228 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1234 theora_enc_get_property (GObject * object, guint prop_id,
1235 GValue * value, GParamSpec * pspec)
1237 GstTheoraEnc *enc = GST_THEORA_ENC (object);
1241 g_value_set_boolean (value, enc->center);
1244 g_value_set_enum (value, enc->border);
1247 g_value_set_int (value, enc->video_bitrate / 1000);
1250 g_value_set_int (value, enc->video_quality);
1253 g_value_set_boolean (value, enc->quick);
1255 case ARG_KEYFRAME_AUTO:
1256 g_value_set_boolean (value, enc->keyframe_auto);
1258 case ARG_KEYFRAME_FREQ:
1259 g_value_set_int (value, enc->keyframe_freq);
1261 case ARG_KEYFRAME_FREQ_FORCE:
1262 g_value_set_int (value, enc->keyframe_force);
1264 case ARG_KEYFRAME_THRESHOLD:
1265 g_value_set_int (value, enc->keyframe_threshold);
1267 case ARG_KEYFRAME_MINDISTANCE:
1268 g_value_set_int (value, enc->keyframe_mindistance);
1270 case ARG_NOISE_SENSITIVITY:
1271 g_value_set_int (value, enc->noise_sensitivity);
1274 g_value_set_int (value, enc->sharpness);
1276 case ARG_SPEEDLEVEL:
1277 g_value_set_int (value, enc->speed_level);
1280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);