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
26 * This element encodes raw video into a Theora stream.
27 * <ulink url="http://www.theora.org/">Theora</ulink> is a royalty-free
28 * video codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
29 * Foundation</ulink>, based on the VP3 codec.
32 * The theora codec internally only supports encoding of images that are a
33 * multiple of 16 pixels in both X and Y direction. It is however perfectly
34 * possible to encode images with other dimensions because an arbitrary
35 * rectangular cropping region can be set up. This element will automatically
36 * set up a correct cropping region if the dimensions are not multiples of 16
37 * pixels. The "border" and "center" properties control how this cropping
38 * region will be set up.
41 * To control the quality of the encoding, the "bitrate" and "quality"
42 * properties can be used. These two properties are mutualy exclusive. Setting
43 * the bitrate property will produce a constant bitrate (CBR) stream while
44 * setting the quality property will produce a variable bitrate (VBR) stream.
46 * <title>Example pipeline</title>
48 * gst-launch -v videotestsrc num-buffers=1000 ! theoraenc ! oggmux ! filesink location=videotestsrc.ogg
50 * This example pipeline will encode a test video source to theora muxed in an
51 * ogg container. Refer to the theoradec documentation to decode the create
55 * Last reviewed on 2006-03-01 (0.10.4)
62 #include "gsttheoraenc.h"
65 #include <stdlib.h> /* free */
67 #include <gst/tag/tag.h>
69 #define GST_CAT_DEFAULT theoraenc_debug
70 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
72 #define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
74 gst_border_mode_get_type (void)
76 static GType border_mode_type = 0;
77 static const GEnumValue border_mode[] = {
78 {BORDER_NONE, "No Border", "none"},
79 {BORDER_BLACK, "Black Border", "black"},
80 {BORDER_MIRROR, "Mirror image in borders", "mirror"},
84 if (!border_mode_type) {
86 g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
88 return border_mode_type;
91 /* taken from theora/lib/toplevel.c */
93 _ilog (unsigned int v)
104 #define THEORA_DEF_CENTER TRUE
105 #define THEORA_DEF_BORDER BORDER_BLACK
106 #define THEORA_DEF_BITRATE 0
107 #define THEORA_DEF_QUALITY 16
108 #define THEORA_DEF_QUICK TRUE
109 #define THEORA_DEF_KEYFRAME_AUTO TRUE
110 #define THEORA_DEF_KEYFRAME_FREQ 64
111 #define THEORA_DEF_KEYFRAME_FREQ_FORCE 64
112 #define THEORA_DEF_KEYFRAME_THRESHOLD 80
113 #define THEORA_DEF_KEYFRAME_MINDISTANCE 8
114 #define THEORA_DEF_NOISE_SENSITIVITY 1
115 #define THEORA_DEF_SHARPNESS 0
126 ARG_KEYFRAME_FREQ_FORCE,
127 ARG_KEYFRAME_THRESHOLD,
128 ARG_KEYFRAME_MINDISTANCE,
129 ARG_NOISE_SENSITIVITY,
134 /* this function does a straight granulepos -> timestamp conversion */
136 granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos)
138 guint64 iframe, pframe;
139 int shift = theoraenc->granule_shift;
142 return GST_CLOCK_TIME_NONE;
144 iframe = granulepos >> shift;
145 pframe = granulepos - (iframe << shift);
147 /* num and den are 32 bit, so we can safely multiply with GST_SECOND */
148 return gst_util_uint64_scale ((guint64) (iframe + pframe),
149 GST_SECOND * theoraenc->info.fps_denominator,
150 theoraenc->info.fps_numerator);
153 static const GstElementDetails theora_enc_details =
154 GST_ELEMENT_DETAILS ("Theora video encoder",
155 "Codec/Encoder/Video",
156 "encode raw YUV video to a theora stream",
157 "Wim Taymans <wim@fluendo.com>");
159 static GstStaticPadTemplate theora_enc_sink_factory =
160 GST_STATIC_PAD_TEMPLATE ("sink",
163 GST_STATIC_CAPS ("video/x-raw-yuv, "
164 "format = (fourcc) I420, "
165 "framerate = (fraction) [0/1, MAX], "
166 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
169 static GstStaticPadTemplate theora_enc_src_factory =
170 GST_STATIC_PAD_TEMPLATE ("src",
173 GST_STATIC_CAPS ("video/x-theora")
176 GST_BOILERPLATE (GstTheoraEnc, gst_theora_enc, GstElement, GST_TYPE_ELEMENT);
178 static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
179 static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
180 static GstStateChangeReturn theora_enc_change_state (GstElement * element,
181 GstStateChange transition);
182 static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
183 static void theora_enc_get_property (GObject * object, guint prop_id,
184 GValue * value, GParamSpec * pspec);
185 static void theora_enc_set_property (GObject * object, guint prop_id,
186 const GValue * value, GParamSpec * pspec);
187 static void theora_enc_finalize (GObject * object);
190 gst_theora_enc_base_init (gpointer g_class)
192 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
194 gst_element_class_add_pad_template (element_class,
195 gst_static_pad_template_get (&theora_enc_src_factory));
196 gst_element_class_add_pad_template (element_class,
197 gst_static_pad_template_get (&theora_enc_sink_factory));
198 gst_element_class_set_details (element_class, &theora_enc_details);
202 gst_theora_enc_class_init (GstTheoraEncClass * klass)
204 GObjectClass *gobject_class = (GObjectClass *) klass;
205 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
207 gobject_class->set_property = theora_enc_set_property;
208 gobject_class->get_property = theora_enc_get_property;
209 gobject_class->finalize = theora_enc_finalize;
211 g_object_class_install_property (gobject_class, ARG_CENTER,
212 g_param_spec_boolean ("center", "Center",
213 "Center image when sizes not multiple of 16", THEORA_DEF_CENTER,
214 (GParamFlags) G_PARAM_READWRITE));
215 g_object_class_install_property (gobject_class, ARG_BORDER,
216 g_param_spec_enum ("border", "Border",
217 "Border color to add when sizes not multiple of 16",
218 GST_TYPE_BORDER_MODE, THEORA_DEF_BORDER,
219 (GParamFlags) G_PARAM_READWRITE));
220 /* general encoding stream options */
221 g_object_class_install_property (gobject_class, ARG_BITRATE,
222 g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
223 0, 2000, THEORA_DEF_BITRATE, (GParamFlags) G_PARAM_READWRITE));
224 g_object_class_install_property (gobject_class, ARG_QUALITY,
225 g_param_spec_int ("quality", "Quality", "Video quality",
226 0, 63, THEORA_DEF_QUALITY, (GParamFlags) G_PARAM_READWRITE));
227 g_object_class_install_property (gobject_class, ARG_QUICK,
228 g_param_spec_boolean ("quick", "Quick", "Quick encoding",
229 THEORA_DEF_QUICK, (GParamFlags) G_PARAM_READWRITE));
230 g_object_class_install_property (gobject_class, ARG_KEYFRAME_AUTO,
231 g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
232 "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
233 (GParamFlags) G_PARAM_READWRITE));
234 g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ,
235 g_param_spec_int ("keyframe-freq", "Keyframe frequency",
236 "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
237 (GParamFlags) G_PARAM_READWRITE));
238 g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ_FORCE,
239 g_param_spec_int ("keyframe-force", "Keyframe force",
240 "Force keyframe every N frames", 1, 32768,
241 THEORA_DEF_KEYFRAME_FREQ_FORCE, (GParamFlags) G_PARAM_READWRITE));
242 g_object_class_install_property (gobject_class, ARG_KEYFRAME_THRESHOLD,
243 g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
244 "Keyframe threshold", 0, 32768, THEORA_DEF_KEYFRAME_THRESHOLD,
245 (GParamFlags) G_PARAM_READWRITE));
246 g_object_class_install_property (gobject_class, ARG_KEYFRAME_MINDISTANCE,
247 g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
248 "Keyframe mindistance", 1, 32768, THEORA_DEF_KEYFRAME_MINDISTANCE,
249 (GParamFlags) G_PARAM_READWRITE));
250 g_object_class_install_property (gobject_class, ARG_NOISE_SENSITIVITY,
251 g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
252 "Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
253 (GParamFlags) G_PARAM_READWRITE));
254 g_object_class_install_property (gobject_class, ARG_SHARPNESS,
255 g_param_spec_int ("sharpness", "Sharpness",
256 "Sharpness", 0, 2, THEORA_DEF_SHARPNESS,
257 (GParamFlags) G_PARAM_READWRITE));
259 gstelement_class->change_state = theora_enc_change_state;
260 GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
264 gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
267 gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink");
268 gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
269 gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
270 gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
271 gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
274 gst_pad_new_from_static_template (&theora_enc_src_factory, "src");
275 gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
277 enc->center = THEORA_DEF_CENTER;
278 enc->border = THEORA_DEF_BORDER;
280 enc->video_bitrate = THEORA_DEF_BITRATE;
281 enc->video_quality = THEORA_DEF_QUALITY;
282 enc->quick = THEORA_DEF_QUICK;
283 enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
284 enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
285 enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
286 enc->keyframe_threshold = THEORA_DEF_KEYFRAME_THRESHOLD;
287 enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
288 enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
289 enc->sharpness = THEORA_DEF_SHARPNESS;
291 enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
292 GST_DEBUG_OBJECT (enc,
293 "keyframe_frequency_force is %d, granule shift is %d",
294 enc->info.keyframe_frequency_force, enc->granule_shift);
295 enc->expected_ts = GST_CLOCK_TIME_NONE;
299 theora_enc_finalize (GObject * object)
301 GstTheoraEnc *enc = GST_THEORA_ENC (object);
303 GST_DEBUG_OBJECT (enc, "Finalizing");
304 theora_clear (&enc->state);
305 theora_comment_clear (&enc->comment);
306 theora_info_clear (&enc->info);
308 G_OBJECT_CLASS (parent_class)->finalize (object);
312 theora_enc_reset (GstTheoraEnc * enc)
314 theora_clear (&enc->state);
315 theora_encode_init (&enc->state, &enc->info);
319 theora_enc_clear (GstTheoraEnc * enc)
323 enc->granulepos_offset = 0;
324 enc->timestamp_offset = 0;
326 enc->next_ts = GST_CLOCK_TIME_NONE;
327 enc->next_discont = FALSE;
328 enc->expected_ts = GST_CLOCK_TIME_NONE;
332 theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
334 GstStructure *structure = gst_caps_get_structure (caps, 0);
335 GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
339 gst_structure_get_int (structure, "width", &enc->width);
340 gst_structure_get_int (structure, "height", &enc->height);
341 gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
342 par = gst_structure_get_value (structure, "pixel-aspect-ratio");
344 theora_info_clear (&enc->info);
345 theora_info_init (&enc->info);
346 /* Theora has a divisible-by-sixteen restriction for the encoded video size but
347 * we can define a visible area using the frame_width/frame_height */
348 enc->info_width = enc->info.width = (enc->width + 15) & ~15;
349 enc->info_height = enc->info.height = (enc->height + 15) & ~15;
350 enc->info.frame_width = enc->width;
351 enc->info.frame_height = enc->height;
353 /* center image if needed */
355 /* make sure offset is even, for easier decoding */
356 enc->offset_x = GST_ROUND_UP_2 ((enc->info_width - enc->width) / 2);
357 enc->offset_y = GST_ROUND_UP_2 ((enc->info_height - enc->height) / 2);
362 enc->info.offset_x = enc->offset_x;
363 enc->info.offset_y = enc->offset_y;
365 enc->info.fps_numerator = enc->fps_n = fps_n;
366 enc->info.fps_denominator = enc->fps_d = fps_d;
368 enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
369 enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
371 /* setting them to 0 indicates that the decoder can chose a good aspect
372 * ratio, defaulting to 1/1 */
373 enc->info.aspect_numerator = 0;
374 enc->info.aspect_denominator = 0;
377 enc->info.colorspace = OC_CS_UNSPECIFIED;
378 enc->info.target_bitrate = enc->video_bitrate;
379 enc->info.quality = enc->video_quality;
381 enc->info.dropframes_p = 0;
382 enc->info.quick_p = (enc->quick ? 1 : 0);
383 enc->info.keyframe_auto_p = (enc->keyframe_auto ? 1 : 0);
384 enc->info.keyframe_frequency = enc->keyframe_freq;
385 enc->info.keyframe_frequency_force = enc->keyframe_force;
386 enc->info.keyframe_data_target_bitrate = enc->video_bitrate * 1.5;
387 enc->info.keyframe_auto_threshold = enc->keyframe_threshold;
388 enc->info.keyframe_mindistance = enc->keyframe_mindistance;
389 enc->info.noise_sensitivity = enc->noise_sensitivity;
390 enc->info.sharpness = enc->sharpness;
392 /* as done in theora */
393 enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
394 GST_DEBUG_OBJECT (enc,
395 "keyframe_frequency_force is %d, granule shift is %d",
396 enc->info.keyframe_frequency_force, enc->granule_shift);
398 theora_enc_reset (enc);
400 gst_object_unref (enc);
406 granulepos_add (guint64 granulepos, guint64 addend, gint shift)
408 guint64 iframe, pframe;
410 iframe = granulepos >> shift;
411 pframe = granulepos - (iframe << shift);
414 return (iframe << shift) + pframe;
417 /* prepare a buffer for transmission by passing data through libtheora */
419 theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
420 GstClockTime timestamp, GstClockTime duration, GstBuffer ** buffer)
425 ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
426 GST_BUFFER_OFFSET_NONE, packet->bytes, GST_PAD_CAPS (enc->srcpad), &buf);
427 if (ret != GST_FLOW_OK)
430 memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
431 /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
432 * time representation */
433 GST_BUFFER_OFFSET_END (buf) =
434 granulepos_add (packet->granulepos, enc->granulepos_offset,
436 GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc,
437 GST_BUFFER_OFFSET_END (buf));
439 GST_BUFFER_TIMESTAMP (buf) = timestamp + enc->timestamp_offset;
440 GST_BUFFER_DURATION (buf) = duration;
442 if (enc->next_discont) {
443 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
444 enc->next_discont = FALSE;
447 /* the second most significant bit of the first data byte is cleared
449 if ((packet->packet[0] & 0x40) == 0) {
450 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
452 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
466 /* push out the buffer and do internal bookkeeping */
468 theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
472 enc->bytes_out += GST_BUFFER_SIZE (buffer);
474 ret = gst_pad_push (enc->srcpad, buffer);
480 theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
481 GstClockTime timestamp, GstClockTime duration)
486 ret = theora_buffer_from_packet (enc, packet, timestamp, duration, &buf);
487 if (ret == GST_FLOW_OK)
488 ret = theora_push_buffer (enc, buf);
494 theora_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
495 GstBuffer * buf2, GstBuffer * buf3)
497 GstStructure *structure;
498 GValue array = { 0 };
499 GValue value = { 0 };
501 caps = gst_caps_make_writable (caps);
502 structure = gst_caps_get_structure (caps, 0);
505 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
506 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
507 GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
509 /* Copy buffers, because we can't use the originals -
510 * it creates a circular refcount with the caps<->buffers */
511 buf1 = gst_buffer_copy (buf1);
512 buf2 = gst_buffer_copy (buf2);
513 buf3 = gst_buffer_copy (buf3);
515 /* put copies of the buffers in a fixed list */
516 g_value_init (&array, GST_TYPE_ARRAY);
518 g_value_init (&value, GST_TYPE_BUFFER);
519 gst_value_set_buffer (&value, buf1);
520 gst_value_array_append_value (&array, &value);
521 g_value_unset (&value);
523 g_value_init (&value, GST_TYPE_BUFFER);
524 gst_value_set_buffer (&value, buf2);
525 gst_value_array_append_value (&array, &value);
526 g_value_unset (&value);
528 g_value_init (&value, GST_TYPE_BUFFER);
529 gst_value_set_buffer (&value, buf3);
530 gst_value_array_append_value (&array, &value);
531 g_value_unset (&value);
533 gst_structure_set_value (structure, "streamheader", &array);
534 g_value_unset (&array);
536 /* Unref our copies */
537 gst_buffer_unref (buf1);
538 gst_buffer_unref (buf2);
539 gst_buffer_unref (buf3);
545 theora_enc_sink_event (GstPad * pad, GstEvent * event)
551 enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
553 switch (GST_EVENT_TYPE (event)) {
555 /* push last packet with eos flag */
556 while (theora_encode_packetout (&enc->state, 1, &op)) {
557 /* See comment in the chain function */
558 GstClockTime next_time = theora_granule_time (&enc->state,
559 granulepos_add (op.granulepos, 1, enc->granule_shift)) * GST_SECOND;
561 theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
562 enc->next_ts = next_time;
564 res = gst_pad_push_event (enc->srcpad, event);
567 res = gst_pad_push_event (enc->srcpad, event);
573 theora_enc_is_discontinuous (GstTheoraEnc * enc, GstBuffer * buffer)
575 GstClockTime ts = GST_BUFFER_TIMESTAMP (buffer);
576 GstClockTimeDiff max_diff;
577 gboolean ret = FALSE;
579 /* Allow 3/4 a frame off */
580 max_diff = (enc->info.fps_denominator * GST_SECOND * 3) /
581 (enc->info.fps_numerator * 4);
583 if (ts != GST_CLOCK_TIME_NONE && enc->expected_ts != GST_CLOCK_TIME_NONE) {
584 if ((GstClockTimeDiff) (ts - enc->expected_ts) > max_diff) {
585 GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT
586 " exceeds expected value %" GST_TIME_FORMAT
587 " by too much, marking discontinuity",
588 GST_TIME_ARGS (ts), GST_TIME_ARGS (enc->expected_ts));
593 if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)))
594 enc->expected_ts = ts + GST_BUFFER_DURATION (buffer);
596 enc->expected_ts = GST_CLOCK_TIME_NONE;
602 theora_enc_chain (GstPad * pad, GstBuffer * buffer)
606 GstClockTime in_time;
609 enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
611 in_time = GST_BUFFER_TIMESTAMP (buffer);
613 /* no packets written yet, setup headers */
614 if (enc->packetno == 0) {
616 GstBuffer *buf1, *buf2, *buf3;
618 enc->granulepos_offset = 0;
619 enc->timestamp_offset = 0;
621 /* Theora streams begin with three headers; the initial header (with
622 most of the codec setup parameters) which is mandated by the Ogg
623 bitstream spec. The second header holds any comment fields. The
624 third header holds the bitstream codebook. We merely need to
625 make the headers, then pass them to libtheora one at a time;
626 libtheora handles the additional Ogg bitstream constraints */
628 /* first packet will get its own page automatically */
629 if (theora_encode_header (&enc->state, &op) != 0)
630 goto encoder_disabled;
632 ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
633 GST_CLOCK_TIME_NONE, &buf1);
634 if (ret != GST_FLOW_OK) {
635 goto header_buffer_alloc;
638 /* create the remaining theora headers */
639 theora_comment_clear (&enc->comment);
640 theora_comment_init (&enc->comment);
642 if (theora_encode_comment (&enc->comment, &op) != 0)
643 goto encoder_disabled;
645 ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
646 GST_CLOCK_TIME_NONE, &buf2);
647 /* Theora expects us to put this packet buffer into an ogg page,
648 * in which case it becomes the ogg library's responsibility to
649 * free it. Since we're copying and outputting a gst_buffer,
650 * we need to free it ourselves. */
654 if (ret != GST_FLOW_OK) {
655 gst_buffer_unref (buf1);
656 goto header_buffer_alloc;
659 if (theora_encode_tables (&enc->state, &op) != 0)
660 goto encoder_disabled;
662 ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
663 GST_CLOCK_TIME_NONE, &buf3);
664 if (ret != GST_FLOW_OK) {
665 gst_buffer_unref (buf1);
666 gst_buffer_unref (buf2);
667 goto header_buffer_alloc;
670 /* mark buffers and put on caps */
671 caps = gst_pad_get_caps (enc->srcpad);
672 caps = theora_set_header_on_caps (caps, buf1, buf2, buf3);
673 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
674 gst_pad_set_caps (enc->srcpad, caps);
676 gst_buffer_set_caps (buf1, caps);
677 gst_buffer_set_caps (buf2, caps);
678 gst_buffer_set_caps (buf3, caps);
680 gst_caps_unref (caps);
682 /* push out the header buffers */
683 if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK) {
684 gst_buffer_unref (buf2);
685 gst_buffer_unref (buf3);
688 if ((ret = theora_push_buffer (enc, buf2)) != GST_FLOW_OK) {
689 gst_buffer_unref (buf3);
692 if ((ret = theora_push_buffer (enc, buf3)) != GST_FLOW_OK) {
696 enc->granulepos_offset =
697 gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buffer), enc->fps_n,
698 GST_SECOND * enc->fps_d);
699 enc->timestamp_offset = GST_BUFFER_TIMESTAMP (buffer);
709 yuv.y_width = enc->info_width;
710 yuv.y_height = enc->info_height;
711 yuv.y_stride = enc->info_width;
713 yuv.uv_width = enc->info_width / 2;
714 yuv.uv_height = enc->info_height / 2;
715 yuv.uv_stride = yuv.uv_width;
717 y_size = enc->info_width * enc->info_height;
719 if (enc->width == enc->info_width && enc->height == enc->info_height) {
720 /* easy case, no cropping/conversion needed */
721 pixels = GST_BUFFER_DATA (buffer);
724 yuv.u = yuv.y + y_size;
725 yuv.v = yuv.u + y_size / 4;
729 guchar *dest_y, *src_y;
730 guchar *dest_u, *src_u;
731 guchar *dest_v, *src_v;
732 gint src_y_stride, src_uv_stride;
733 gint dst_y_stride, dst_uv_stride;
735 gint cwidth, cheight;
736 gint offset_x, right_x, right_border;
738 /* source width/height */
740 height = enc->height;
741 /* soucre chroma width/height */
743 cheight = height / 2;
745 /* source strides as defined in videotestsrc */
746 src_y_stride = GST_ROUND_UP_4 (width);
747 src_uv_stride = GST_ROUND_UP_8 (width) / 2;
749 /* destination strides from the real picture width */
750 dst_y_stride = enc->info_width;
751 dst_uv_stride = enc->info_width / 2;
753 ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
754 GST_BUFFER_OFFSET_NONE, y_size * 3 / 2, GST_PAD_CAPS (enc->srcpad),
756 if (ret != GST_FLOW_OK)
759 dest_y = yuv.y = GST_BUFFER_DATA (newbuf);
760 dest_u = yuv.u = yuv.y + y_size;
761 dest_v = yuv.v = yuv.u + y_size / 4;
763 src_y = GST_BUFFER_DATA (buffer);
764 src_u = src_y + src_y_stride * GST_ROUND_UP_2 (height);
765 src_v = src_u + src_uv_stride * GST_ROUND_UP_2 (height) / 2;
767 if (enc->border != BORDER_NONE) {
768 /* fill top border */
769 for (i = 0; i < enc->offset_y; i++) {
770 memset (dest_y, 0, dst_y_stride);
771 dest_y += dst_y_stride;
774 dest_y += dst_y_stride * enc->offset_y;
777 offset_x = enc->offset_x;
778 right_x = width + enc->offset_x;
779 right_border = dst_y_stride - right_x;
782 for (i = 0; i < height; i++) {
783 memcpy (dest_y + offset_x, src_y, width);
784 if (enc->border != BORDER_NONE) {
785 memset (dest_y, 0, offset_x);
786 memset (dest_y + right_x, 0, right_border);
789 dest_y += dst_y_stride;
790 src_y += src_y_stride;
793 if (enc->border != BORDER_NONE) {
794 /* fill bottom border */
795 for (i = height + enc->offset_y; i < enc->info.height; i++) {
796 memset (dest_y, 0, dst_y_stride);
797 dest_y += dst_y_stride;
800 /* fill top border chroma */
801 for (i = 0; i < enc->offset_y / 2; i++) {
802 memset (dest_u, 128, dst_uv_stride);
803 memset (dest_v, 128, dst_uv_stride);
804 dest_u += dst_uv_stride;
805 dest_v += dst_uv_stride;
808 dest_u += dst_uv_stride * enc->offset_y / 2;
809 dest_v += dst_uv_stride * enc->offset_y / 2;
812 offset_x = enc->offset_x / 2;
813 right_x = cwidth + offset_x;
814 right_border = dst_uv_stride - right_x;
817 for (i = 0; i < cheight; i++) {
818 memcpy (dest_v + offset_x, src_v, cwidth);
819 memcpy (dest_u + offset_x, src_u, cwidth);
821 if (enc->border != BORDER_NONE) {
822 memset (dest_u, 128, offset_x);
823 memset (dest_u + right_x, 128, right_border);
824 memset (dest_v, 128, offset_x);
825 memset (dest_v + right_x, 128, right_border);
828 dest_u += dst_uv_stride;
829 dest_v += dst_uv_stride;
830 src_u += src_uv_stride;
831 src_v += src_uv_stride;
834 if (enc->border != BORDER_NONE) {
835 /* fill bottom border */
836 for (i = cheight + enc->offset_y / 2; i < enc->info_height / 2; i++) {
837 memset (dest_u, 128, dst_uv_stride);
838 memset (dest_v, 128, dst_uv_stride);
839 dest_u += dst_uv_stride;
840 dest_v += dst_uv_stride;
844 gst_buffer_unref (buffer);
848 if (theora_enc_is_discontinuous (enc, buffer)) {
849 theora_enc_reset (enc);
850 enc->granulepos_offset =
851 gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buffer), enc->fps_n,
852 GST_SECOND * enc->fps_d);
853 enc->timestamp_offset = GST_BUFFER_TIMESTAMP (buffer);
855 enc->next_discont = TRUE;
858 res = theora_encode_YUVin (&enc->state, &yuv);
861 while (theora_encode_packetout (&enc->state, 0, &op)) {
862 /* This is where we hack around theora's broken idea of what granulepos
863 is -- normally we wouldn't need to add the 1, because granulepos
864 should be the presentation time of the last sample in the packet, but
865 theora starts with 0 instead of 1... */
866 GstClockTime next_time;
868 next_time = theora_granule_time (&enc->state,
869 granulepos_add (op.granulepos, 1, enc->granule_shift)) * GST_SECOND;
871 theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
872 enc->next_ts = next_time;
873 if (ret != GST_FLOW_OK)
876 gst_buffer_unref (buffer);
884 gst_buffer_unref (buffer);
889 gst_buffer_unref (buffer);
894 gst_buffer_unref (buffer);
899 gst_buffer_unref (buffer);
904 GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
905 ("libtheora has been compiled with the encoder disabled"));
906 gst_buffer_unref (buffer);
907 return GST_FLOW_ERROR;
911 static GstStateChangeReturn
912 theora_enc_change_state (GstElement * element, GstStateChange transition)
915 GstStateChangeReturn ret;
917 enc = GST_THEORA_ENC (element);
919 switch (transition) {
920 case GST_STATE_CHANGE_NULL_TO_READY:
922 case GST_STATE_CHANGE_READY_TO_PAUSED:
923 GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state");
924 theora_info_init (&enc->info);
925 theora_comment_init (&enc->comment);
928 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
934 ret = parent_class->change_state (element, transition);
936 switch (transition) {
937 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
939 case GST_STATE_CHANGE_PAUSED_TO_READY:
940 GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state");
941 theora_clear (&enc->state);
942 theora_comment_clear (&enc->comment);
943 theora_info_clear (&enc->info);
945 theora_enc_clear (enc);
947 case GST_STATE_CHANGE_READY_TO_NULL:
957 theora_enc_set_property (GObject * object, guint prop_id,
958 const GValue * value, GParamSpec * pspec)
960 GstTheoraEnc *enc = GST_THEORA_ENC (object);
964 enc->center = g_value_get_boolean (value);
967 enc->border = g_value_get_enum (value);
970 enc->video_bitrate = g_value_get_int (value) * 1000;
971 enc->video_quality = 0;
974 enc->video_quality = g_value_get_int (value);
975 enc->video_bitrate = 0;
978 enc->quick = g_value_get_boolean (value);
980 case ARG_KEYFRAME_AUTO:
981 enc->keyframe_auto = g_value_get_boolean (value);
983 case ARG_KEYFRAME_FREQ:
984 enc->keyframe_freq = g_value_get_int (value);
986 case ARG_KEYFRAME_FREQ_FORCE:
987 enc->keyframe_force = g_value_get_int (value);
989 case ARG_KEYFRAME_THRESHOLD:
990 enc->keyframe_threshold = g_value_get_int (value);
992 case ARG_KEYFRAME_MINDISTANCE:
993 enc->keyframe_mindistance = g_value_get_int (value);
995 case ARG_NOISE_SENSITIVITY:
996 enc->noise_sensitivity = g_value_get_int (value);
999 enc->sharpness = g_value_get_int (value);
1002 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1008 theora_enc_get_property (GObject * object, guint prop_id,
1009 GValue * value, GParamSpec * pspec)
1011 GstTheoraEnc *enc = GST_THEORA_ENC (object);
1015 g_value_set_boolean (value, enc->center);
1018 g_value_set_enum (value, enc->border);
1021 g_value_set_int (value, enc->video_bitrate / 1000);
1024 g_value_set_int (value, enc->video_quality);
1027 g_value_set_boolean (value, enc->quick);
1029 case ARG_KEYFRAME_AUTO:
1030 g_value_set_boolean (value, enc->keyframe_auto);
1032 case ARG_KEYFRAME_FREQ:
1033 g_value_set_int (value, enc->keyframe_freq);
1035 case ARG_KEYFRAME_FREQ_FORCE:
1036 g_value_set_int (value, enc->keyframe_force);
1038 case ARG_KEYFRAME_THRESHOLD:
1039 g_value_set_int (value, enc->keyframe_threshold);
1041 case ARG_KEYFRAME_MINDISTANCE:
1042 g_value_set_int (value, enc->keyframe_mindistance);
1044 case ARG_NOISE_SENSITIVITY:
1045 g_value_set_int (value, enc->noise_sensitivity);
1048 g_value_set_int (value, enc->sharpness);
1051 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);