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.
31 * <title>Example pipeline</title>
33 * gst-launch -v videotestsrc num-buffers=1000 ! theoraenc ! oggmux ! filesink location=videotestsrc.ogg
43 #include <theora/theora.h>
45 #include <gst/tag/tag.h>
47 GST_DEBUG_CATEGORY (theoraenc_debug);
48 #define GST_CAT_DEFAULT theoraenc_debug
50 #define GST_TYPE_THEORA_ENC \
51 (gst_theora_enc_get_type())
52 #define GST_THEORA_ENC(obj) \
53 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_ENC,GstTheoraEnc))
54 #define GST_THEORA_ENC_CLASS(klass) \
55 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_ENC,GstTheoraEnc))
56 #define GST_IS_THEORA_ENC(obj) \
57 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_ENC))
58 #define GST_IS_THEORA_ENC_CLASS(obj) \
59 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_ENC))
61 typedef struct _GstTheoraEnc GstTheoraEnc;
62 typedef struct _GstTheoraEncClass GstTheoraEncClass;
70 GstTheoraEncBorderMode;
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 GEnumValue border_mode[] = {
78 {BORDER_NONE, "BORDER_NONE", "No Border"},
79 {BORDER_BLACK, "BORDER_BLACK", "Black Border"},
80 {BORDER_MIRROR, "BORDER_MIRROR", "Mirror image in borders"},
84 if (!border_mode_type) {
86 g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
88 return border_mode_type;
102 theora_comment comment;
105 GstTheoraEncBorderMode border;
107 gint video_bitrate; /* bitrate target for Theora video */
108 gint video_quality; /* Theora quality selector 0 = low, 63 = high */
110 gboolean keyframe_auto;
113 gint keyframe_threshold;
114 gint keyframe_mindistance;
115 gint noise_sensitivity;
118 gint info_width, info_height;
120 gint offset_x, offset_y;
125 guint64 initial_delay;
128 struct _GstTheoraEncClass
130 GstElementClass parent_class;
133 #define ROUND_UP_2(x) (((x) + 1) & ~1)
134 #define ROUND_UP_4(x) (((x) + 3) & ~3)
135 #define ROUND_UP_8(x) (((x) + 7) & ~7)
137 #define THEORA_DEF_CENTER TRUE
138 #define THEORA_DEF_BORDER BORDER_BLACK
139 #define THEORA_DEF_BITRATE 0
140 #define THEORA_DEF_QUALITY 16
141 #define THEORA_DEF_QUICK TRUE
142 #define THEORA_DEF_KEYFRAME_AUTO TRUE
143 #define THEORA_DEF_KEYFRAME_FREQ 64
144 #define THEORA_DEF_KEYFRAME_FREQ_FORCE 64
145 #define THEORA_DEF_KEYFRAME_THRESHOLD 80
146 #define THEORA_DEF_KEYFRAME_MINDISTANCE 8
147 #define THEORA_DEF_NOISE_SENSITIVITY 1
148 #define THEORA_DEF_SHARPNESS 0
160 ARG_KEYFRAME_FREQ_FORCE,
161 ARG_KEYFRAME_THRESHOLD,
162 ARG_KEYFRAME_MINDISTANCE,
163 ARG_NOISE_SENSITIVITY,
168 static GstElementDetails theora_enc_details = {
170 "Codec/Encoder/Video",
171 "encode raw YUV video to a theora stream",
172 "Wim Taymans <wim@fluendo.com>",
175 static GstStaticPadTemplate theora_enc_sink_factory =
176 GST_STATIC_PAD_TEMPLATE ("sink",
179 GST_STATIC_CAPS ("video/x-raw-yuv, "
180 "format = (fourcc) I420, "
181 "framerate = (double) [0, MAX], "
182 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
185 static GstStaticPadTemplate theora_enc_src_factory =
186 GST_STATIC_PAD_TEMPLATE ("src",
189 GST_STATIC_CAPS ("video/x-theora")
192 GST_BOILERPLATE (GstTheoraEnc, gst_theora_enc, GstElement, GST_TYPE_ELEMENT);
194 static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
195 static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
196 static GstStateChangeReturn theora_enc_change_state (GstElement * element,
197 GstStateChange transition);
198 static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
199 static void theora_enc_get_property (GObject * object, guint prop_id,
200 GValue * value, GParamSpec * pspec);
201 static void theora_enc_set_property (GObject * object, guint prop_id,
202 const GValue * value, GParamSpec * pspec);
205 gst_theora_enc_base_init (gpointer g_class)
207 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
209 gst_element_class_add_pad_template (element_class,
210 gst_static_pad_template_get (&theora_enc_src_factory));
211 gst_element_class_add_pad_template (element_class,
212 gst_static_pad_template_get (&theora_enc_sink_factory));
213 gst_element_class_set_details (element_class, &theora_enc_details);
217 gst_theora_enc_class_init (GstTheoraEncClass * klass)
219 GObjectClass *gobject_class = (GObjectClass *) klass;
220 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
222 gobject_class->set_property = theora_enc_set_property;
223 gobject_class->get_property = theora_enc_get_property;
225 g_object_class_install_property (gobject_class, ARG_CENTER,
226 g_param_spec_boolean ("center", "Center",
227 "Center image when sizes not multiple of 16", THEORA_DEF_CENTER,
228 (GParamFlags) G_PARAM_READWRITE));
229 g_object_class_install_property (gobject_class, ARG_BORDER,
230 g_param_spec_enum ("border", "Border",
231 "Border color to add when sizes not multiple of 16",
232 GST_TYPE_BORDER_MODE, THEORA_DEF_BORDER,
233 (GParamFlags) G_PARAM_READWRITE));
234 /* general encoding stream options */
235 g_object_class_install_property (gobject_class, ARG_BITRATE,
236 g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
237 0, 2000, THEORA_DEF_BITRATE, (GParamFlags) G_PARAM_READWRITE));
238 g_object_class_install_property (gobject_class, ARG_QUALITY,
239 g_param_spec_int ("quality", "Quality", "Video quality",
240 0, 63, THEORA_DEF_QUALITY, (GParamFlags) G_PARAM_READWRITE));
241 g_object_class_install_property (gobject_class, ARG_QUICK,
242 g_param_spec_boolean ("quick", "Quick", "Quick encoding",
243 THEORA_DEF_QUICK, (GParamFlags) G_PARAM_READWRITE));
244 g_object_class_install_property (gobject_class, ARG_KEYFRAME_AUTO,
245 g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
246 "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
247 (GParamFlags) G_PARAM_READWRITE));
248 g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ,
249 g_param_spec_int ("keyframe-freq", "Keyframe frequency",
250 "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
251 (GParamFlags) G_PARAM_READWRITE));
252 g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ_FORCE,
253 g_param_spec_int ("keyframe-force", "Keyframe force",
254 "Force keyframe every N frames", 1, 32768,
255 THEORA_DEF_KEYFRAME_FREQ_FORCE, (GParamFlags) G_PARAM_READWRITE));
256 g_object_class_install_property (gobject_class, ARG_KEYFRAME_THRESHOLD,
257 g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
258 "Keyframe threshold", 0, 32768, THEORA_DEF_KEYFRAME_THRESHOLD,
259 (GParamFlags) G_PARAM_READWRITE));
260 g_object_class_install_property (gobject_class, ARG_KEYFRAME_MINDISTANCE,
261 g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
262 "Keyframe mindistance", 1, 32768, THEORA_DEF_KEYFRAME_MINDISTANCE,
263 (GParamFlags) G_PARAM_READWRITE));
264 g_object_class_install_property (gobject_class, ARG_NOISE_SENSITIVITY,
265 g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
266 "Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
267 (GParamFlags) G_PARAM_READWRITE));
268 g_object_class_install_property (gobject_class, ARG_SHARPNESS,
269 g_param_spec_int ("sharpness", "Sharpness",
270 "Sharpness", 0, 2, THEORA_DEF_SHARPNESS,
271 (GParamFlags) G_PARAM_READWRITE));
273 gstelement_class->change_state = theora_enc_change_state;
274 GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
278 gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
281 gst_pad_new_from_template (gst_static_pad_template_get
282 (&theora_enc_sink_factory), "sink");
283 gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
284 gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
285 gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
286 gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
289 gst_pad_new_from_template (gst_static_pad_template_get
290 (&theora_enc_src_factory), "src");
291 gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
293 enc->center = THEORA_DEF_CENTER;
294 enc->border = THEORA_DEF_BORDER;
296 enc->video_bitrate = THEORA_DEF_BITRATE;
297 enc->video_quality = THEORA_DEF_QUALITY;
298 enc->quick = THEORA_DEF_QUICK;
299 enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
300 enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
301 enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
302 enc->keyframe_threshold = THEORA_DEF_KEYFRAME_THRESHOLD;
303 enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
304 enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
305 enc->sharpness = THEORA_DEF_SHARPNESS;
309 theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
311 GstStructure *structure = gst_caps_get_structure (caps, 0);
312 GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
315 GValue framerate = { 0 };
317 gst_structure_get_int (structure, "width", &enc->width);
318 gst_structure_get_int (structure, "height", &enc->height);
319 gst_structure_get_double (structure, "framerate", &enc->fps);
320 par = gst_structure_get_value (structure, "pixel-aspect-ratio");
322 theora_info_init (&enc->info);
323 /* Theora has a divisible-by-sixteen restriction for the encoded video size but
324 * we can define a visible area using the frame_width/frame_height */
325 enc->info_width = enc->info.width = (enc->width + 15) & ~15;
326 enc->info_height = enc->info.height = (enc->height + 15) & ~15;
327 enc->info.frame_width = enc->width;
328 enc->info.frame_height = enc->height;
330 /* center image if needed */
332 /* make sure offset is even, for easier decoding */
333 enc->offset_x = ROUND_UP_2 ((enc->info_width - enc->width) / 2);
334 enc->offset_y = ROUND_UP_2 ((enc->info_height - enc->height) / 2);
339 enc->info.offset_x = enc->offset_x;
340 enc->info.offset_y = enc->offset_y;
342 /* convert double to fraction for the framerate */
343 g_value_init (&fps, G_TYPE_DOUBLE);
344 g_value_init (&framerate, GST_TYPE_FRACTION);
345 g_value_set_double (&fps, enc->fps);
346 g_value_transform (&fps, &framerate);
348 enc->info.fps_numerator = gst_value_get_fraction_numerator (&framerate);
349 enc->info.fps_denominator = gst_value_get_fraction_denominator (&framerate);
352 enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
353 enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
355 /* setting them to 0 indicates that the decoder can chose a good aspect
356 * ratio, defaulting to 1/1 */
357 enc->info.aspect_numerator = 0;
358 enc->info.aspect_denominator = 0;
361 enc->info.colorspace = OC_CS_UNSPECIFIED;
362 enc->info.target_bitrate = enc->video_bitrate;
363 enc->info.quality = enc->video_quality;
365 enc->info.dropframes_p = 0;
366 enc->info.quick_p = (enc->quick ? 1 : 0);
367 enc->info.keyframe_auto_p = (enc->keyframe_auto ? 1 : 0);
368 enc->info.keyframe_frequency = enc->keyframe_freq;
369 enc->info.keyframe_frequency_force = enc->keyframe_force;
370 enc->info.keyframe_data_target_bitrate = enc->video_bitrate * 1.5;
371 enc->info.keyframe_auto_threshold = enc->keyframe_threshold;
372 enc->info.keyframe_mindistance = enc->keyframe_mindistance;
373 enc->info.noise_sensitivity = enc->noise_sensitivity;
374 enc->info.sharpness = enc->sharpness;
376 theora_encode_init (&enc->state, &enc->info);
381 /* prepare a buffer for transmission by passing data through libtheora */
383 theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
384 GstClockTime timestamp, GstClockTime duration)
389 ret = gst_pad_alloc_buffer (enc->srcpad,
390 GST_BUFFER_OFFSET_NONE, packet->bytes, GST_PAD_CAPS (enc->srcpad), &buf);
391 if (ret != GST_FLOW_OK)
394 memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
395 GST_BUFFER_OFFSET (buf) = enc->bytes_out;
396 GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
397 GST_BUFFER_TIMESTAMP (buf) = timestamp;
398 GST_BUFFER_DURATION (buf) = duration;
400 /* the second most significant bit of the first data byte is cleared
402 if ((packet->packet[0] & 0x40) == 0) {
403 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
405 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
417 /* push out the buffer and do internal bookkeeping */
419 theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
423 enc->bytes_out += GST_BUFFER_SIZE (buffer);
425 ret = gst_pad_push (enc->srcpad, buffer);
431 theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
432 GstClockTime timestamp, GstClockTime duration)
437 buf = theora_buffer_from_packet (enc, packet, timestamp, duration);
438 ret = theora_push_buffer (enc, buf);
444 theora_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
445 GstBuffer * buf2, GstBuffer * buf3)
447 GstStructure *structure;
449 GValue value = { 0 };
451 caps = gst_caps_make_writable (caps);
452 structure = gst_caps_get_structure (caps, 0);
455 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
456 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
457 GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
459 /* put buffers in a fixed list */
460 g_value_init (&list, GST_TYPE_ARRAY);
461 g_value_init (&value, GST_TYPE_BUFFER);
462 gst_value_set_buffer (&value, buf1);
463 gst_value_list_append_value (&list, &value);
464 g_value_unset (&value);
465 g_value_init (&value, GST_TYPE_BUFFER);
466 gst_value_set_buffer (&value, buf2);
467 gst_value_list_append_value (&list, &value);
468 g_value_unset (&value);
469 g_value_init (&value, GST_TYPE_BUFFER);
470 gst_value_set_buffer (&value, buf3);
471 gst_value_list_append_value (&list, &value);
472 gst_structure_set_value (structure, "streamheader", &list);
473 g_value_unset (&value);
474 g_value_unset (&list);
480 theora_enc_sink_event (GstPad * pad, GstEvent * event)
485 enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
487 switch (GST_EVENT_TYPE (event)) {
489 /* push last packet with eos flag */
490 while (theora_encode_packetout (&enc->state, 1, &op)) {
491 GstClockTime out_time =
492 theora_granule_time (&enc->state, op.granulepos) * GST_SECOND;
493 theora_push_packet (enc, &op, out_time, GST_SECOND / enc->fps);
496 return gst_pad_event_default (pad, event);
501 theora_enc_chain (GstPad * pad, GstBuffer * buffer)
505 GstClockTime in_time;
508 enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
510 in_time = GST_BUFFER_TIMESTAMP (buffer);
512 /* no packets written yet, setup headers */
513 if (enc->packetno == 0) {
515 GstBuffer *buf1, *buf2, *buf3;
517 /* Theora streams begin with three headers; the initial header (with
518 most of the codec setup parameters) which is mandated by the Ogg
519 bitstream spec. The second header holds any comment fields. The
520 third header holds the bitstream codebook. We merely need to
521 make the headers, then pass them to libtheora one at a time;
522 libtheora handles the additional Ogg bitstream constraints */
524 /* first packet will get its own page automatically */
525 theora_encode_header (&enc->state, &op);
526 buf1 = theora_buffer_from_packet (enc, &op, 0, 0);
528 /* create the remaining theora headers */
529 theora_comment_init (&enc->comment);
530 theora_encode_comment (&enc->comment, &op);
531 buf2 = theora_buffer_from_packet (enc, &op, 0, 0);
532 theora_encode_tables (&enc->state, &op);
533 buf3 = theora_buffer_from_packet (enc, &op, 0, 0);
535 /* mark buffers and put on caps */
536 caps = gst_pad_get_caps (enc->srcpad);
537 caps = theora_set_header_on_caps (caps, buf1, buf2, buf3);
538 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
539 gst_pad_set_caps (enc->srcpad, caps);
541 gst_buffer_set_caps (buf1, caps);
542 gst_buffer_set_caps (buf2, caps);
543 gst_buffer_set_caps (buf3, caps);
545 /* push out the header buffers */
546 if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK)
548 if ((ret = theora_push_buffer (enc, buf2)) != GST_FLOW_OK)
550 if ((ret = theora_push_buffer (enc, buf3)) != GST_FLOW_OK)
560 yuv.y_width = enc->info_width;
561 yuv.y_height = enc->info_height;
562 yuv.y_stride = enc->info_width;
564 yuv.uv_width = enc->info_width / 2;
565 yuv.uv_height = enc->info_height / 2;
566 yuv.uv_stride = yuv.uv_width;
568 y_size = enc->info_width * enc->info_height;
570 if (enc->width == enc->info_width && enc->height == enc->info_height) {
571 /* easy case, no cropping/conversion needed */
572 pixels = GST_BUFFER_DATA (buffer);
575 yuv.u = yuv.y + y_size;
576 yuv.v = yuv.u + y_size / 4;
580 guchar *dest_y, *src_y;
581 guchar *dest_u, *src_u;
582 guchar *dest_v, *src_v;
583 gint src_y_stride, src_uv_stride;
584 gint dst_y_stride, dst_uv_stride;
586 gint cwidth, cheight;
587 gint offset_x, right_x, right_border;
589 /* source width/height */
591 height = enc->height;
592 /* soucre chroma width/height */
594 cheight = height / 2;
596 /* source strides as defined in videotestsrc */
597 src_y_stride = ROUND_UP_4 (width);
598 src_uv_stride = ROUND_UP_8 (width) / 2;
600 /* destination strides from the real picture width */
601 dst_y_stride = enc->info_width;
602 dst_uv_stride = enc->info_width / 2;
604 ret = gst_pad_alloc_buffer (enc->srcpad,
605 GST_BUFFER_OFFSET_NONE, y_size * 3 / 2, GST_PAD_CAPS (enc->srcpad),
607 if (ret != GST_FLOW_OK)
610 dest_y = yuv.y = GST_BUFFER_DATA (newbuf);
611 dest_u = yuv.u = yuv.y + y_size;
612 dest_v = yuv.v = yuv.u + y_size / 4;
614 src_y = GST_BUFFER_DATA (buffer);
615 src_u = src_y + src_y_stride * ROUND_UP_2 (height);
616 src_v = src_u + src_uv_stride * ROUND_UP_2 (height) / 2;
618 if (enc->border != BORDER_NONE) {
619 /* fill top border */
620 for (i = 0; i < enc->offset_y; i++) {
621 memset (dest_y, 0, dst_y_stride);
622 dest_y += dst_y_stride;
625 dest_y += dst_y_stride * enc->offset_y;
628 offset_x = enc->offset_x;
629 right_x = width + enc->offset_x;
630 right_border = dst_y_stride - right_x;
633 for (i = 0; i < height; i++) {
634 memcpy (dest_y + offset_x, src_y, width);
635 if (enc->border != BORDER_NONE) {
636 memset (dest_y, 0, offset_x);
637 memset (dest_y + right_x, 0, right_border);
640 dest_y += dst_y_stride;
641 src_y += src_y_stride;
644 if (enc->border != BORDER_NONE) {
645 /* fill bottom border */
646 for (i = height + enc->offset_y; i < enc->info.height; i++) {
647 memset (dest_y, 0, dst_y_stride);
648 dest_y += dst_y_stride;
651 /* fill top border chroma */
652 for (i = 0; i < enc->offset_y / 2; i++) {
653 memset (dest_u, 128, dst_uv_stride);
654 memset (dest_v, 128, dst_uv_stride);
655 dest_u += dst_uv_stride;
656 dest_v += dst_uv_stride;
659 dest_u += dst_uv_stride * enc->offset_y / 2;
660 dest_v += dst_uv_stride * enc->offset_y / 2;
663 offset_x = enc->offset_x / 2;
664 right_x = cwidth + offset_x;
665 right_border = dst_uv_stride - right_x;
668 for (i = 0; i < cheight; i++) {
669 memcpy (dest_v + offset_x, src_v, cwidth);
670 memcpy (dest_u + offset_x, src_u, cwidth);
672 if (enc->border != BORDER_NONE) {
673 memset (dest_u, 128, offset_x);
674 memset (dest_u + right_x, 128, right_border);
675 memset (dest_v, 128, offset_x);
676 memset (dest_v + right_x, 128, right_border);
679 dest_u += dst_uv_stride;
680 dest_v += dst_uv_stride;
681 src_u += src_uv_stride;
682 src_v += src_uv_stride;
685 if (enc->border != BORDER_NONE) {
686 /* fill bottom border */
687 for (i = cheight + enc->offset_y / 2; i < enc->info_height / 2; i++) {
688 memset (dest_u, 128, dst_uv_stride);
689 memset (dest_v, 128, dst_uv_stride);
690 dest_u += dst_uv_stride;
691 dest_v += dst_uv_stride;
695 gst_buffer_unref (buffer);
699 res = theora_encode_YUVin (&enc->state, &yuv);
702 while (theora_encode_packetout (&enc->state, 0, &op)) {
703 GstClockTime out_time;
705 out_time = theora_granule_time (&enc->state, op.granulepos) * GST_SECOND;
706 if ((ret = theora_push_packet (enc, &op, out_time, GST_SECOND / enc->fps))
710 gst_buffer_unref (buffer);
718 gst_buffer_unref (buffer);
723 gst_buffer_unref (buffer);
728 gst_buffer_unref (buffer);
733 static GstStateChangeReturn
734 theora_enc_change_state (GstElement * element, GstStateChange transition)
737 GstStateChangeReturn ret;
739 enc = GST_THEORA_ENC (element);
741 switch (transition) {
742 case GST_STATE_CHANGE_NULL_TO_READY:
744 case GST_STATE_CHANGE_READY_TO_PAUSED:
745 theora_info_init (&enc->info);
746 theora_comment_init (&enc->comment);
748 enc->initial_delay = 0;
750 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
756 ret = parent_class->change_state (element, transition);
758 switch (transition) {
759 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
761 case GST_STATE_CHANGE_PAUSED_TO_READY:
762 GST_STREAM_LOCK (enc->sinkpad);
763 theora_clear (&enc->state);
764 theora_comment_clear (&enc->comment);
765 theora_info_clear (&enc->info);
766 GST_STREAM_UNLOCK (enc->sinkpad);
768 case GST_STATE_CHANGE_READY_TO_NULL:
778 theora_enc_set_property (GObject * object, guint prop_id,
779 const GValue * value, GParamSpec * pspec)
781 GstTheoraEnc *enc = GST_THEORA_ENC (object);
785 enc->center = g_value_get_boolean (value);
788 enc->border = g_value_get_enum (value);
791 enc->video_bitrate = g_value_get_int (value) * 1000;
792 enc->video_quality = 0;
795 enc->video_quality = g_value_get_int (value);
796 enc->video_bitrate = 0;
799 enc->quick = g_value_get_boolean (value);
801 case ARG_KEYFRAME_AUTO:
802 enc->keyframe_auto = g_value_get_boolean (value);
804 case ARG_KEYFRAME_FREQ:
805 enc->keyframe_freq = g_value_get_int (value);
807 case ARG_KEYFRAME_FREQ_FORCE:
808 enc->keyframe_force = g_value_get_int (value);
810 case ARG_KEYFRAME_THRESHOLD:
811 enc->keyframe_threshold = g_value_get_int (value);
813 case ARG_KEYFRAME_MINDISTANCE:
814 enc->keyframe_mindistance = g_value_get_int (value);
816 case ARG_NOISE_SENSITIVITY:
817 enc->noise_sensitivity = g_value_get_int (value);
820 enc->sharpness = g_value_get_int (value);
823 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
829 theora_enc_get_property (GObject * object, guint prop_id,
830 GValue * value, GParamSpec * pspec)
832 GstTheoraEnc *enc = GST_THEORA_ENC (object);
836 g_value_set_boolean (value, enc->center);
839 g_value_set_enum (value, enc->border);
842 g_value_set_int (value, enc->video_bitrate / 1000);
845 g_value_set_int (value, enc->video_quality);
848 g_value_set_boolean (value, enc->quick);
850 case ARG_KEYFRAME_AUTO:
851 g_value_set_boolean (value, enc->keyframe_auto);
853 case ARG_KEYFRAME_FREQ:
854 g_value_set_int (value, enc->keyframe_freq);
856 case ARG_KEYFRAME_FREQ_FORCE:
857 g_value_set_int (value, enc->keyframe_force);
859 case ARG_KEYFRAME_THRESHOLD:
860 g_value_set_int (value, enc->keyframe_threshold);
862 case ARG_KEYFRAME_MINDISTANCE:
863 g_value_set_int (value, enc->keyframe_mindistance);
865 case ARG_NOISE_SENSITIVITY:
866 g_value_set_int (value, enc->noise_sensitivity);
869 g_value_set_int (value, enc->sharpness);
872 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);