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
42 #include "gsttheoraenc.h"
44 #include <gst/tag/tag.h>
46 GST_DEBUG_CATEGORY (theoraenc_debug);
47 #define GST_CAT_DEFAULT theoraenc_debug
49 #define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
51 gst_border_mode_get_type (void)
53 static GType border_mode_type = 0;
54 static GEnumValue border_mode[] = {
55 {BORDER_NONE, "No Border", "none"},
56 {BORDER_BLACK, "Black Border", "black"},
57 {BORDER_MIRROR, "Mirror image in borders", "mirror"},
61 if (!border_mode_type) {
63 g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
65 return border_mode_type;
68 #define ROUND_UP_2(x) (((x) + 1) & ~1)
69 #define ROUND_UP_4(x) (((x) + 3) & ~3)
70 #define ROUND_UP_8(x) (((x) + 7) & ~7)
72 #define THEORA_DEF_CENTER TRUE
73 #define THEORA_DEF_BORDER BORDER_BLACK
74 #define THEORA_DEF_BITRATE 0
75 #define THEORA_DEF_QUALITY 16
76 #define THEORA_DEF_QUICK TRUE
77 #define THEORA_DEF_KEYFRAME_AUTO TRUE
78 #define THEORA_DEF_KEYFRAME_FREQ 64
79 #define THEORA_DEF_KEYFRAME_FREQ_FORCE 64
80 #define THEORA_DEF_KEYFRAME_THRESHOLD 80
81 #define THEORA_DEF_KEYFRAME_MINDISTANCE 8
82 #define THEORA_DEF_NOISE_SENSITIVITY 1
83 #define THEORA_DEF_SHARPNESS 0
85 /* taken from theora/lib/toplevel.c */
87 _ilog (unsigned int v)
108 ARG_KEYFRAME_FREQ_FORCE,
109 ARG_KEYFRAME_THRESHOLD,
110 ARG_KEYFRAME_MINDISTANCE,
111 ARG_NOISE_SENSITIVITY,
116 static GstElementDetails theora_enc_details = {
118 "Codec/Encoder/Video",
119 "encode raw YUV video to a theora stream",
120 "Wim Taymans <wim@fluendo.com>",
123 static GstStaticPadTemplate theora_enc_sink_factory =
124 GST_STATIC_PAD_TEMPLATE ("sink",
127 GST_STATIC_CAPS ("video/x-raw-yuv, "
128 "format = (fourcc) I420, "
129 "framerate = (fraction) [0/1, MAX], "
130 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
133 static GstStaticPadTemplate theora_enc_src_factory =
134 GST_STATIC_PAD_TEMPLATE ("src",
137 GST_STATIC_CAPS ("video/x-theora")
140 GST_BOILERPLATE (GstTheoraEnc, gst_theora_enc, GstElement, GST_TYPE_ELEMENT);
142 static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
143 static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
144 static GstStateChangeReturn theora_enc_change_state (GstElement * element,
145 GstStateChange transition);
146 static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
147 static void theora_enc_get_property (GObject * object, guint prop_id,
148 GValue * value, GParamSpec * pspec);
149 static void theora_enc_set_property (GObject * object, guint prop_id,
150 const GValue * value, GParamSpec * pspec);
151 static void theora_enc_finalize (GObject * object);
154 gst_theora_enc_base_init (gpointer g_class)
156 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
158 gst_element_class_add_pad_template (element_class,
159 gst_static_pad_template_get (&theora_enc_src_factory));
160 gst_element_class_add_pad_template (element_class,
161 gst_static_pad_template_get (&theora_enc_sink_factory));
162 gst_element_class_set_details (element_class, &theora_enc_details);
166 gst_theora_enc_class_init (GstTheoraEncClass * klass)
168 GObjectClass *gobject_class = (GObjectClass *) klass;
169 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
171 gobject_class->set_property = theora_enc_set_property;
172 gobject_class->get_property = theora_enc_get_property;
173 gobject_class->finalize = theora_enc_finalize;
175 g_object_class_install_property (gobject_class, ARG_CENTER,
176 g_param_spec_boolean ("center", "Center",
177 "Center image when sizes not multiple of 16", THEORA_DEF_CENTER,
178 (GParamFlags) G_PARAM_READWRITE));
179 g_object_class_install_property (gobject_class, ARG_BORDER,
180 g_param_spec_enum ("border", "Border",
181 "Border color to add when sizes not multiple of 16",
182 GST_TYPE_BORDER_MODE, THEORA_DEF_BORDER,
183 (GParamFlags) G_PARAM_READWRITE));
184 /* general encoding stream options */
185 g_object_class_install_property (gobject_class, ARG_BITRATE,
186 g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
187 0, 2000, THEORA_DEF_BITRATE, (GParamFlags) G_PARAM_READWRITE));
188 g_object_class_install_property (gobject_class, ARG_QUALITY,
189 g_param_spec_int ("quality", "Quality", "Video quality",
190 0, 63, THEORA_DEF_QUALITY, (GParamFlags) G_PARAM_READWRITE));
191 g_object_class_install_property (gobject_class, ARG_QUICK,
192 g_param_spec_boolean ("quick", "Quick", "Quick encoding",
193 THEORA_DEF_QUICK, (GParamFlags) G_PARAM_READWRITE));
194 g_object_class_install_property (gobject_class, ARG_KEYFRAME_AUTO,
195 g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
196 "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
197 (GParamFlags) G_PARAM_READWRITE));
198 g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ,
199 g_param_spec_int ("keyframe-freq", "Keyframe frequency",
200 "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
201 (GParamFlags) G_PARAM_READWRITE));
202 g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ_FORCE,
203 g_param_spec_int ("keyframe-force", "Keyframe force",
204 "Force keyframe every N frames", 1, 32768,
205 THEORA_DEF_KEYFRAME_FREQ_FORCE, (GParamFlags) G_PARAM_READWRITE));
206 g_object_class_install_property (gobject_class, ARG_KEYFRAME_THRESHOLD,
207 g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
208 "Keyframe threshold", 0, 32768, THEORA_DEF_KEYFRAME_THRESHOLD,
209 (GParamFlags) G_PARAM_READWRITE));
210 g_object_class_install_property (gobject_class, ARG_KEYFRAME_MINDISTANCE,
211 g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
212 "Keyframe mindistance", 1, 32768, THEORA_DEF_KEYFRAME_MINDISTANCE,
213 (GParamFlags) G_PARAM_READWRITE));
214 g_object_class_install_property (gobject_class, ARG_NOISE_SENSITIVITY,
215 g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
216 "Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
217 (GParamFlags) G_PARAM_READWRITE));
218 g_object_class_install_property (gobject_class, ARG_SHARPNESS,
219 g_param_spec_int ("sharpness", "Sharpness",
220 "Sharpness", 0, 2, THEORA_DEF_SHARPNESS,
221 (GParamFlags) G_PARAM_READWRITE));
223 gstelement_class->change_state = theora_enc_change_state;
224 GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
228 gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
231 gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink");
232 gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
233 gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
234 gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
235 gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
238 gst_pad_new_from_static_template (&theora_enc_src_factory, "src");
239 gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
241 enc->center = THEORA_DEF_CENTER;
242 enc->border = THEORA_DEF_BORDER;
244 enc->video_bitrate = THEORA_DEF_BITRATE;
245 enc->video_quality = THEORA_DEF_QUALITY;
246 enc->quick = THEORA_DEF_QUICK;
247 enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
248 enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
249 enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
250 enc->keyframe_threshold = THEORA_DEF_KEYFRAME_THRESHOLD;
251 enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
252 enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
253 enc->sharpness = THEORA_DEF_SHARPNESS;
255 enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
256 GST_DEBUG_OBJECT (enc,
257 "keyframe_frequency_force is %d, granule shift is %d",
258 enc->info.keyframe_frequency_force, enc->granule_shift);
262 theora_enc_finalize (GObject * object)
264 GstTheoraEnc *enc = GST_THEORA_ENC (object);
266 GST_DEBUG_OBJECT (enc, "Finalizing");
267 theora_clear (&enc->state);
268 theora_comment_clear (&enc->comment);
269 theora_info_clear (&enc->info);
271 G_OBJECT_CLASS (parent_class)->finalize (object);
275 theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
277 GstStructure *structure = gst_caps_get_structure (caps, 0);
278 GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
282 gst_structure_get_int (structure, "width", &enc->width);
283 gst_structure_get_int (structure, "height", &enc->height);
284 gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
285 par = gst_structure_get_value (structure, "pixel-aspect-ratio");
287 theora_info_clear (&enc->info);
288 theora_info_init (&enc->info);
289 /* Theora has a divisible-by-sixteen restriction for the encoded video size but
290 * we can define a visible area using the frame_width/frame_height */
291 enc->info_width = enc->info.width = (enc->width + 15) & ~15;
292 enc->info_height = enc->info.height = (enc->height + 15) & ~15;
293 enc->info.frame_width = enc->width;
294 enc->info.frame_height = enc->height;
296 /* center image if needed */
298 /* make sure offset is even, for easier decoding */
299 enc->offset_x = ROUND_UP_2 ((enc->info_width - enc->width) / 2);
300 enc->offset_y = ROUND_UP_2 ((enc->info_height - enc->height) / 2);
305 enc->info.offset_x = enc->offset_x;
306 enc->info.offset_y = enc->offset_y;
308 enc->info.fps_numerator = enc->fps_n = fps_n;
309 enc->info.fps_denominator = enc->fps_d = fps_d;
311 enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
312 enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
314 /* setting them to 0 indicates that the decoder can chose a good aspect
315 * ratio, defaulting to 1/1 */
316 enc->info.aspect_numerator = 0;
317 enc->info.aspect_denominator = 0;
320 enc->info.colorspace = OC_CS_UNSPECIFIED;
321 enc->info.target_bitrate = enc->video_bitrate;
322 enc->info.quality = enc->video_quality;
324 enc->info.dropframes_p = 0;
325 enc->info.quick_p = (enc->quick ? 1 : 0);
326 enc->info.keyframe_auto_p = (enc->keyframe_auto ? 1 : 0);
327 enc->info.keyframe_frequency = enc->keyframe_freq;
328 enc->info.keyframe_frequency_force = enc->keyframe_force;
329 enc->info.keyframe_data_target_bitrate = enc->video_bitrate * 1.5;
330 enc->info.keyframe_auto_threshold = enc->keyframe_threshold;
331 enc->info.keyframe_mindistance = enc->keyframe_mindistance;
332 enc->info.noise_sensitivity = enc->noise_sensitivity;
333 enc->info.sharpness = enc->sharpness;
335 /* as done in theora */
336 enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
337 GST_DEBUG_OBJECT (enc,
338 "keyframe_frequency_force is %d, granule shift is %d",
339 enc->info.keyframe_frequency_force, enc->granule_shift);
341 theora_encode_init (&enc->state, &enc->info);
343 gst_object_unref (enc);
349 granulepos_add (guint64 granulepos, guint64 addend, gint shift)
351 GstClockTime iframe, pframe;
353 iframe = granulepos >> shift;
354 pframe = granulepos - (iframe << shift);
357 return (iframe << shift) + pframe;
360 /* prepare a buffer for transmission by passing data through libtheora */
362 theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
363 GstClockTime timestamp, GstClockTime duration, GstBuffer ** buffer)
368 ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
369 GST_BUFFER_OFFSET_NONE, packet->bytes, GST_PAD_CAPS (enc->srcpad), &buf);
370 if (ret != GST_FLOW_OK)
373 memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
374 GST_BUFFER_OFFSET (buf) = enc->bytes_out;
375 GST_BUFFER_OFFSET_END (buf) =
376 granulepos_add (packet->granulepos, enc->granulepos_offset,
378 GST_BUFFER_TIMESTAMP (buf) = timestamp + enc->timestamp_offset;
379 GST_BUFFER_DURATION (buf) = duration;
381 /* the second most significant bit of the first data byte is cleared
383 if ((packet->packet[0] & 0x40) == 0) {
384 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
386 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
400 /* push out the buffer and do internal bookkeeping */
402 theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
406 enc->bytes_out += GST_BUFFER_SIZE (buffer);
408 ret = gst_pad_push (enc->srcpad, buffer);
414 theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
415 GstClockTime timestamp, GstClockTime duration)
420 ret = theora_buffer_from_packet (enc, packet, timestamp, duration, &buf);
421 if (ret == GST_FLOW_OK)
422 ret = theora_push_buffer (enc, buf);
428 theora_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
429 GstBuffer * buf2, GstBuffer * buf3)
431 GstStructure *structure;
432 GValue array = { 0 };
433 GValue value = { 0 };
435 caps = gst_caps_make_writable (caps);
436 structure = gst_caps_get_structure (caps, 0);
438 /* Copy buffers, because we can't use the originals -
439 * it creates a circular refcount with the caps<->buffers */
440 buf1 = gst_buffer_copy (buf1);
441 buf2 = gst_buffer_copy (buf2);
442 buf3 = gst_buffer_copy (buf3);
445 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
446 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
447 GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
449 /* put copies of the buffers in a fixed list */
450 g_value_init (&array, GST_TYPE_ARRAY);
452 g_value_init (&value, GST_TYPE_BUFFER);
453 gst_value_set_buffer (&value, buf1);
454 gst_value_array_append_value (&array, &value);
455 g_value_unset (&value);
457 g_value_init (&value, GST_TYPE_BUFFER);
458 gst_value_set_buffer (&value, buf2);
459 gst_value_array_append_value (&array, &value);
460 g_value_unset (&value);
462 g_value_init (&value, GST_TYPE_BUFFER);
463 gst_value_set_buffer (&value, buf3);
464 gst_value_array_append_value (&array, &value);
465 g_value_unset (&value);
467 gst_structure_set_value (structure, "streamheader", &array);
468 g_value_unset (&array);
470 /* Unref our copies */
471 gst_buffer_unref (buf1);
472 gst_buffer_unref (buf2);
473 gst_buffer_unref (buf3);
479 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 /* See comment in the chain function */
492 GstClockTime next_time = theora_granule_time (&enc->state,
493 granulepos_add (op.granulepos, 1, enc->granule_shift)) * GST_SECOND;
495 theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
496 enc->next_ts = next_time;
498 res = gst_pad_push_event (enc->srcpad, event);
501 res = gst_pad_push_event (enc->srcpad, event);
507 theora_enc_chain (GstPad * pad, GstBuffer * buffer)
511 GstClockTime in_time;
514 enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
516 in_time = GST_BUFFER_TIMESTAMP (buffer);
518 /* no packets written yet, setup headers */
519 if (enc->packetno == 0) {
521 GstBuffer *buf1, *buf2, *buf3;
523 enc->granulepos_offset = 0;
524 enc->timestamp_offset = 0;
526 /* Theora streams begin with three headers; the initial header (with
527 most of the codec setup parameters) which is mandated by the Ogg
528 bitstream spec. The second header holds any comment fields. The
529 third header holds the bitstream codebook. We merely need to
530 make the headers, then pass them to libtheora one at a time;
531 libtheora handles the additional Ogg bitstream constraints */
533 /* first packet will get its own page automatically */
534 theora_encode_header (&enc->state, &op);
535 ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
536 GST_CLOCK_TIME_NONE, &buf1);
537 if (ret != GST_FLOW_OK) {
538 goto header_buffer_alloc;
541 /* create the remaining theora headers */
542 theora_comment_clear (&enc->comment);
543 theora_comment_init (&enc->comment);
545 theora_encode_comment (&enc->comment, &op);
546 ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
547 GST_CLOCK_TIME_NONE, &buf2);
548 /* Theora expects us to put this packet buffer into an ogg page,
549 * in which case it becomes the ogg library's responsibility to
550 * free it. Since we're copying and outputting a gst_buffer,
551 * we need to free it ourselves. */
555 if (ret != GST_FLOW_OK) {
556 gst_buffer_unref (buf1);
557 goto header_buffer_alloc;
560 theora_encode_tables (&enc->state, &op);
561 ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
562 GST_CLOCK_TIME_NONE, &buf3);
563 if (ret != GST_FLOW_OK) {
564 gst_buffer_unref (buf1);
565 gst_buffer_unref (buf2);
566 goto header_buffer_alloc;
569 /* mark buffers and put on caps */
570 caps = gst_pad_get_caps (enc->srcpad);
571 caps = theora_set_header_on_caps (caps, buf1, buf2, buf3);
572 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
573 gst_pad_set_caps (enc->srcpad, caps);
575 gst_buffer_set_caps (buf1, caps);
576 gst_buffer_set_caps (buf2, caps);
577 gst_buffer_set_caps (buf3, caps);
579 gst_caps_unref (caps);
581 /* push out the header buffers */
582 if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK) {
583 gst_buffer_unref (buf2);
584 gst_buffer_unref (buf3);
587 if ((ret = theora_push_buffer (enc, buf2)) != GST_FLOW_OK) {
588 gst_buffer_unref (buf3);
591 if ((ret = theora_push_buffer (enc, buf3)) != GST_FLOW_OK) {
595 enc->granulepos_offset =
596 gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buffer), enc->fps_n,
597 GST_SECOND * enc->fps_d);
598 enc->timestamp_offset = GST_BUFFER_TIMESTAMP (buffer);
608 yuv.y_width = enc->info_width;
609 yuv.y_height = enc->info_height;
610 yuv.y_stride = enc->info_width;
612 yuv.uv_width = enc->info_width / 2;
613 yuv.uv_height = enc->info_height / 2;
614 yuv.uv_stride = yuv.uv_width;
616 y_size = enc->info_width * enc->info_height;
618 if (enc->width == enc->info_width && enc->height == enc->info_height) {
619 /* easy case, no cropping/conversion needed */
620 pixels = GST_BUFFER_DATA (buffer);
623 yuv.u = yuv.y + y_size;
624 yuv.v = yuv.u + y_size / 4;
628 guchar *dest_y, *src_y;
629 guchar *dest_u, *src_u;
630 guchar *dest_v, *src_v;
631 gint src_y_stride, src_uv_stride;
632 gint dst_y_stride, dst_uv_stride;
634 gint cwidth, cheight;
635 gint offset_x, right_x, right_border;
637 /* source width/height */
639 height = enc->height;
640 /* soucre chroma width/height */
642 cheight = height / 2;
644 /* source strides as defined in videotestsrc */
645 src_y_stride = ROUND_UP_4 (width);
646 src_uv_stride = ROUND_UP_8 (width) / 2;
648 /* destination strides from the real picture width */
649 dst_y_stride = enc->info_width;
650 dst_uv_stride = enc->info_width / 2;
652 ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
653 GST_BUFFER_OFFSET_NONE, y_size * 3 / 2, GST_PAD_CAPS (enc->srcpad),
655 if (ret != GST_FLOW_OK)
658 dest_y = yuv.y = GST_BUFFER_DATA (newbuf);
659 dest_u = yuv.u = yuv.y + y_size;
660 dest_v = yuv.v = yuv.u + y_size / 4;
662 src_y = GST_BUFFER_DATA (buffer);
663 src_u = src_y + src_y_stride * ROUND_UP_2 (height);
664 src_v = src_u + src_uv_stride * ROUND_UP_2 (height) / 2;
666 if (enc->border != BORDER_NONE) {
667 /* fill top border */
668 for (i = 0; i < enc->offset_y; i++) {
669 memset (dest_y, 0, dst_y_stride);
670 dest_y += dst_y_stride;
673 dest_y += dst_y_stride * enc->offset_y;
676 offset_x = enc->offset_x;
677 right_x = width + enc->offset_x;
678 right_border = dst_y_stride - right_x;
681 for (i = 0; i < height; i++) {
682 memcpy (dest_y + offset_x, src_y, width);
683 if (enc->border != BORDER_NONE) {
684 memset (dest_y, 0, offset_x);
685 memset (dest_y + right_x, 0, right_border);
688 dest_y += dst_y_stride;
689 src_y += src_y_stride;
692 if (enc->border != BORDER_NONE) {
693 /* fill bottom border */
694 for (i = height + enc->offset_y; i < enc->info.height; i++) {
695 memset (dest_y, 0, dst_y_stride);
696 dest_y += dst_y_stride;
699 /* fill top border chroma */
700 for (i = 0; i < enc->offset_y / 2; i++) {
701 memset (dest_u, 128, dst_uv_stride);
702 memset (dest_v, 128, dst_uv_stride);
703 dest_u += dst_uv_stride;
704 dest_v += dst_uv_stride;
707 dest_u += dst_uv_stride * enc->offset_y / 2;
708 dest_v += dst_uv_stride * enc->offset_y / 2;
711 offset_x = enc->offset_x / 2;
712 right_x = cwidth + offset_x;
713 right_border = dst_uv_stride - right_x;
716 for (i = 0; i < cheight; i++) {
717 memcpy (dest_v + offset_x, src_v, cwidth);
718 memcpy (dest_u + offset_x, src_u, cwidth);
720 if (enc->border != BORDER_NONE) {
721 memset (dest_u, 128, offset_x);
722 memset (dest_u + right_x, 128, right_border);
723 memset (dest_v, 128, offset_x);
724 memset (dest_v + right_x, 128, right_border);
727 dest_u += dst_uv_stride;
728 dest_v += dst_uv_stride;
729 src_u += src_uv_stride;
730 src_v += src_uv_stride;
733 if (enc->border != BORDER_NONE) {
734 /* fill bottom border */
735 for (i = cheight + enc->offset_y / 2; i < enc->info_height / 2; i++) {
736 memset (dest_u, 128, dst_uv_stride);
737 memset (dest_v, 128, dst_uv_stride);
738 dest_u += dst_uv_stride;
739 dest_v += dst_uv_stride;
743 gst_buffer_unref (buffer);
747 res = theora_encode_YUVin (&enc->state, &yuv);
750 while (theora_encode_packetout (&enc->state, 0, &op)) {
751 /* This is where we hack around theora's broken idea of what granulepos
752 is -- normally we wouldn't need to add the 1, because granulepos
753 should be the presentation time of the last sample in the packet, but
754 theora starts with 0 instead of 1... */
755 GstClockTime next_time;
757 next_time = theora_granule_time (&enc->state,
758 granulepos_add (op.granulepos, 1, enc->granule_shift)) * GST_SECOND;
760 theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
761 enc->next_ts = next_time;
762 if (ret != GST_FLOW_OK)
765 gst_buffer_unref (buffer);
773 gst_buffer_unref (buffer);
778 gst_buffer_unref (buffer);
783 gst_buffer_unref (buffer);
788 gst_buffer_unref (buffer);
793 static GstStateChangeReturn
794 theora_enc_change_state (GstElement * element, GstStateChange transition)
797 GstStateChangeReturn ret;
799 enc = GST_THEORA_ENC (element);
801 switch (transition) {
802 case GST_STATE_CHANGE_NULL_TO_READY:
804 case GST_STATE_CHANGE_READY_TO_PAUSED:
805 GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state");
806 theora_info_init (&enc->info);
807 theora_comment_init (&enc->comment);
810 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
816 ret = parent_class->change_state (element, transition);
818 switch (transition) {
819 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
821 case GST_STATE_CHANGE_PAUSED_TO_READY:
822 GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state");
823 theora_clear (&enc->state);
824 theora_comment_clear (&enc->comment);
825 theora_info_clear (&enc->info);
827 case GST_STATE_CHANGE_READY_TO_NULL:
837 theora_enc_set_property (GObject * object, guint prop_id,
838 const GValue * value, GParamSpec * pspec)
840 GstTheoraEnc *enc = GST_THEORA_ENC (object);
844 enc->center = g_value_get_boolean (value);
847 enc->border = g_value_get_enum (value);
850 enc->video_bitrate = g_value_get_int (value) * 1000;
851 enc->video_quality = 0;
854 enc->video_quality = g_value_get_int (value);
855 enc->video_bitrate = 0;
858 enc->quick = g_value_get_boolean (value);
860 case ARG_KEYFRAME_AUTO:
861 enc->keyframe_auto = g_value_get_boolean (value);
863 case ARG_KEYFRAME_FREQ:
864 enc->keyframe_freq = g_value_get_int (value);
866 case ARG_KEYFRAME_FREQ_FORCE:
867 enc->keyframe_force = g_value_get_int (value);
869 case ARG_KEYFRAME_THRESHOLD:
870 enc->keyframe_threshold = g_value_get_int (value);
872 case ARG_KEYFRAME_MINDISTANCE:
873 enc->keyframe_mindistance = g_value_get_int (value);
875 case ARG_NOISE_SENSITIVITY:
876 enc->noise_sensitivity = g_value_get_int (value);
879 enc->sharpness = g_value_get_int (value);
882 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
888 theora_enc_get_property (GObject * object, guint prop_id,
889 GValue * value, GParamSpec * pspec)
891 GstTheoraEnc *enc = GST_THEORA_ENC (object);
895 g_value_set_boolean (value, enc->center);
898 g_value_set_enum (value, enc->border);
901 g_value_set_int (value, enc->video_bitrate / 1000);
904 g_value_set_int (value, enc->video_quality);
907 g_value_set_boolean (value, enc->quick);
909 case ARG_KEYFRAME_AUTO:
910 g_value_set_boolean (value, enc->keyframe_auto);
912 case ARG_KEYFRAME_FREQ:
913 g_value_set_int (value, enc->keyframe_freq);
915 case ARG_KEYFRAME_FREQ_FORCE:
916 g_value_set_int (value, enc->keyframe_force);
918 case ARG_KEYFRAME_THRESHOLD:
919 g_value_set_int (value, enc->keyframe_threshold);
921 case ARG_KEYFRAME_MINDISTANCE:
922 g_value_set_int (value, enc->keyframe_mindistance);
924 case ARG_NOISE_SENSITIVITY:
925 g_value_set_int (value, enc->noise_sensitivity);
928 g_value_set_int (value, enc->sharpness);
931 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);