plugins: uddate gst_type_mark_as_plugin_api() calls
[platform/upstream/gstreamer.git] / ext / theora / gsttheoraenc.c
1 /* GStreamer
2  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
3  * Copyright (c) 2012 Collabora Ltd.
4  *      Author : Edward Hervey <edward@collabora.com>
5  *      Author : Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /**
24  * SECTION:element-theoraenc
25  * @title: theoraenc
26  * @see_also: theoradec, oggmux
27  *
28  * This element encodes raw video into a Theora stream.
29  * [Theora](http://www.theora.org/) is a royalty-free
30  * video codec maintained by the [Xiph.org Foundation](http://www.xiph.org/),
31  * based on the VP3 codec.
32  *
33  * The theora codec internally only supports encoding of images that are a
34  * multiple of 16 pixels in both X and Y direction. It is however perfectly
35  * possible to encode images with other dimensions because an arbitrary
36  * rectangular cropping region can be set up. This element will automatically
37  * set up a correct cropping region if the dimensions are not multiples of 16
38  * pixels.
39  *
40  * To control the quality of the encoding, the #GstTheoraEnc:bitrate and
41  * #GstTheoraEnc:quality properties can be used. These two properties are
42  * mutualy exclusive. Setting the bitrate property will produce a constant
43  * bitrate (CBR) stream while setting the quality property will produce a
44  * variable bitrate (VBR) stream.
45  *
46  * A videorate element is often required in front of theoraenc, especially
47  * when transcoding and when putting Theora into the Ogg container.
48  *
49  * ## Example pipeline
50  * |[
51  * gst-launch-1.0 -v videotestsrc num-buffers=500 ! video/x-raw,width=1280,height=720 ! queue ! progressreport ! theoraenc ! oggmux ! filesink location=videotestsrc.ogg
52  * ]|
53  *  This example pipeline will encode a test video source to theora muxed in an
54  * ogg container. Refer to the theoradec documentation to decode the create
55  * stream.
56  *
57  */
58
59 #ifdef HAVE_CONFIG_H
60 #include "config.h"
61 #endif
62
63 #include <string.h>
64 #include <stdlib.h>             /* free */
65
66 #include <gst/tag/tag.h>
67 #include <gst/video/video.h>
68 #include <gst/video/gstvideometa.h>
69
70 #include "gsttheoraenc.h"
71
72 #define GST_CAT_DEFAULT theoraenc_debug
73 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
74
75 #define GST_TYPE_MULTIPASS_MODE (gst_multipass_mode_get_type())
76 static GType
77 gst_multipass_mode_get_type (void)
78 {
79   static GType multipass_mode_type = 0;
80   static const GEnumValue multipass_mode[] = {
81     {MULTIPASS_MODE_SINGLE_PASS, "Single pass", "single-pass"},
82     {MULTIPASS_MODE_FIRST_PASS, "First pass", "first-pass"},
83     {MULTIPASS_MODE_SECOND_PASS, "Second pass", "second-pass"},
84     {0, NULL, NULL},
85   };
86
87   if (!multipass_mode_type) {
88     multipass_mode_type =
89         g_enum_register_static ("GstTheoraEncMultipassMode", multipass_mode);
90   }
91   return multipass_mode_type;
92 }
93
94 /* taken from theora/lib/toplevel.c */
95 static int
96 _ilog (unsigned int v)
97 {
98   int ret = 0;
99
100   while (v) {
101     ret++;
102     v >>= 1;
103   }
104   return (ret);
105 }
106
107 #define THEORA_DEF_BITRATE              0
108 #define THEORA_DEF_QUALITY              48
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_SPEEDLEVEL           1
113 #define THEORA_DEF_VP3_COMPATIBLE       FALSE
114 #define THEORA_DEF_DROP_FRAMES          TRUE
115 #define THEORA_DEF_CAP_OVERFLOW         TRUE
116 #define THEORA_DEF_CAP_UNDERFLOW        FALSE
117 #define THEORA_DEF_RATE_BUFFER          0
118 #define THEORA_DEF_MULTIPASS_CACHE_FILE NULL
119 #define THEORA_DEF_MULTIPASS_MODE       MULTIPASS_MODE_SINGLE_PASS
120 enum
121 {
122   PROP_0,
123   PROP_BITRATE,
124   PROP_QUALITY,
125   PROP_KEYFRAME_AUTO,
126   PROP_KEYFRAME_FREQ,
127   PROP_KEYFRAME_FREQ_FORCE,
128   PROP_SPEEDLEVEL,
129   PROP_VP3_COMPATIBLE,
130   PROP_DROP_FRAMES,
131   PROP_CAP_OVERFLOW,
132   PROP_CAP_UNDERFLOW,
133   PROP_RATE_BUFFER,
134   PROP_MULTIPASS_CACHE_FILE,
135   PROP_MULTIPASS_MODE
136       /* FILL ME */
137 };
138
139 /* this function does a straight granulepos -> timestamp conversion */
140 static GstClockTime
141 granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos)
142 {
143   guint64 iframe, pframe;
144   int shift = theoraenc->info.keyframe_granule_shift;
145
146   if (granulepos < 0)
147     return GST_CLOCK_TIME_NONE;
148
149   iframe = granulepos >> shift;
150   pframe = granulepos - (iframe << shift);
151
152   /* num and den are 32 bit, so we can safely multiply with GST_SECOND */
153   return gst_util_uint64_scale ((guint64) (iframe + pframe),
154       GST_SECOND * theoraenc->info.fps_denominator,
155       theoraenc->info.fps_numerator);
156 }
157
158 static GstStaticPadTemplate theora_enc_sink_factory =
159 GST_STATIC_PAD_TEMPLATE ("sink",
160     GST_PAD_SINK,
161     GST_PAD_ALWAYS,
162     GST_STATIC_CAPS ("video/x-raw, "
163         "format = (string) { I420, Y42B, Y444 }, "
164         "framerate = (fraction) [1/MAX, MAX], "
165         "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
166     );
167
168 static GstStaticPadTemplate theora_enc_src_factory =
169 GST_STATIC_PAD_TEMPLATE ("src",
170     GST_PAD_SRC,
171     GST_PAD_ALWAYS,
172     GST_STATIC_CAPS ("video/x-theora, "
173         "framerate = (fraction) [1/MAX, MAX], "
174         "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
175     );
176
177 #define gst_theora_enc_parent_class parent_class
178 G_DEFINE_TYPE (GstTheoraEnc, gst_theora_enc, GST_TYPE_VIDEO_ENCODER);
179
180 static gboolean theora_enc_start (GstVideoEncoder * enc);
181 static gboolean theora_enc_stop (GstVideoEncoder * enc);
182 static gboolean theora_enc_flush (GstVideoEncoder * enc);
183 static gboolean theora_enc_set_format (GstVideoEncoder * enc,
184     GstVideoCodecState * state);
185 static GstFlowReturn theora_enc_handle_frame (GstVideoEncoder * enc,
186     GstVideoCodecFrame * frame);
187 static GstFlowReturn theora_enc_pre_push (GstVideoEncoder * benc,
188     GstVideoCodecFrame * frame);
189 static GstFlowReturn theora_enc_finish (GstVideoEncoder * enc);
190 static gboolean theora_enc_propose_allocation (GstVideoEncoder * encoder,
191     GstQuery * query);
192
193 static GstCaps *theora_enc_getcaps (GstVideoEncoder * encoder,
194     GstCaps * filter);
195 static void theora_enc_get_property (GObject * object, guint prop_id,
196     GValue * value, GParamSpec * pspec);
197 static void theora_enc_set_property (GObject * object, guint prop_id,
198     const GValue * value, GParamSpec * pspec);
199 static void theora_enc_finalize (GObject * object);
200
201 static gboolean theora_enc_write_multipass_cache (GstTheoraEnc * enc,
202     gboolean begin, gboolean eos);
203
204 static void
205 gst_theora_enc_class_init (GstTheoraEncClass * klass)
206 {
207   GObjectClass *gobject_class = (GObjectClass *) klass;
208   GstElementClass *element_class = (GstElementClass *) klass;
209   GstVideoEncoderClass *gstvideo_encoder_class =
210       GST_VIDEO_ENCODER_CLASS (klass);
211
212   gobject_class->set_property = theora_enc_set_property;
213   gobject_class->get_property = theora_enc_get_property;
214   gobject_class->finalize = theora_enc_finalize;
215
216   gst_element_class_add_static_pad_template (element_class,
217       &theora_enc_src_factory);
218   gst_element_class_add_static_pad_template (element_class,
219       &theora_enc_sink_factory);
220   gst_element_class_set_static_metadata (element_class, "Theora video encoder",
221       "Codec/Encoder/Video", "encode raw YUV video to a theora stream",
222       "Wim Taymans <wim@fluendo.com>");
223
224   gstvideo_encoder_class->start = GST_DEBUG_FUNCPTR (theora_enc_start);
225   gstvideo_encoder_class->stop = GST_DEBUG_FUNCPTR (theora_enc_stop);
226   gstvideo_encoder_class->flush = GST_DEBUG_FUNCPTR (theora_enc_flush);
227   gstvideo_encoder_class->set_format =
228       GST_DEBUG_FUNCPTR (theora_enc_set_format);
229   gstvideo_encoder_class->handle_frame =
230       GST_DEBUG_FUNCPTR (theora_enc_handle_frame);
231   gstvideo_encoder_class->pre_push = GST_DEBUG_FUNCPTR (theora_enc_pre_push);
232   gstvideo_encoder_class->finish = GST_DEBUG_FUNCPTR (theora_enc_finish);
233   gstvideo_encoder_class->getcaps = GST_DEBUG_FUNCPTR (theora_enc_getcaps);
234   gstvideo_encoder_class->propose_allocation =
235       GST_DEBUG_FUNCPTR (theora_enc_propose_allocation);
236
237   /* general encoding stream options */
238   g_object_class_install_property (gobject_class, PROP_BITRATE,
239       g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
240           0, (1 << 24) - 1, THEORA_DEF_BITRATE,
241           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
242           GST_PARAM_MUTABLE_PLAYING));
243   g_object_class_install_property (gobject_class, PROP_QUALITY,
244       g_param_spec_int ("quality", "Quality", "Video quality", 0, 63,
245           THEORA_DEF_QUALITY,
246           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
247           GST_PARAM_MUTABLE_PLAYING));
248   g_object_class_install_property (gobject_class, PROP_KEYFRAME_AUTO,
249       g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
250           "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
251           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
252   g_object_class_install_property (gobject_class, PROP_KEYFRAME_FREQ,
253       g_param_spec_int ("keyframe-freq", "Keyframe frequency",
254           "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
255           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
256   g_object_class_install_property (gobject_class, PROP_KEYFRAME_FREQ_FORCE,
257       g_param_spec_int ("keyframe-force", "Keyframe force",
258           "Force keyframe every N frames", 1, 32768,
259           THEORA_DEF_KEYFRAME_FREQ_FORCE,
260           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
261   g_object_class_install_property (gobject_class, PROP_SPEEDLEVEL,
262       g_param_spec_int ("speed-level", "Speed level",
263           "Controls the amount of motion vector searching done while encoding",
264           0, 3, THEORA_DEF_SPEEDLEVEL,
265           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
266   g_object_class_install_property (gobject_class, PROP_VP3_COMPATIBLE,
267       g_param_spec_boolean ("vp3-compatible", "VP3 compatible",
268           "Disables non-VP3 compatible features",
269           THEORA_DEF_VP3_COMPATIBLE,
270           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
271   g_object_class_install_property (gobject_class, PROP_DROP_FRAMES,
272       g_param_spec_boolean ("drop-frames", "Drop frames",
273           "Allow or disallow frame dropping",
274           THEORA_DEF_DROP_FRAMES,
275           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
276   g_object_class_install_property (gobject_class, PROP_CAP_OVERFLOW,
277       g_param_spec_boolean ("cap-overflow", "Cap overflow",
278           "Enable capping of bit reservoir overflows",
279           THEORA_DEF_CAP_OVERFLOW,
280           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
281   g_object_class_install_property (gobject_class, PROP_CAP_UNDERFLOW,
282       g_param_spec_boolean ("cap-underflow", "Cap underflow",
283           "Enable capping of bit reservoir underflows",
284           THEORA_DEF_CAP_UNDERFLOW,
285           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
286   g_object_class_install_property (gobject_class, PROP_RATE_BUFFER,
287       g_param_spec_int ("rate-buffer", "Rate Control Buffer",
288           "Sets the size of the rate control buffer, in units of frames.  "
289           "The default value of 0 instructs the encoder to automatically "
290           "select an appropriate value",
291           0, 1000, THEORA_DEF_RATE_BUFFER,
292           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
293   g_object_class_install_property (gobject_class, PROP_MULTIPASS_CACHE_FILE,
294       g_param_spec_string ("multipass-cache-file", "Multipass Cache File",
295           "Multipass cache file", THEORA_DEF_MULTIPASS_CACHE_FILE,
296           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
297   g_object_class_install_property (gobject_class, PROP_MULTIPASS_MODE,
298       g_param_spec_enum ("multipass-mode", "Multipass mode",
299           "Single pass or first/second pass", GST_TYPE_MULTIPASS_MODE,
300           THEORA_DEF_MULTIPASS_MODE,
301           (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
302
303   GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
304
305   gst_type_mark_as_plugin_api (GST_TYPE_MULTIPASS_MODE, 0);
306 }
307
308 static void
309 gst_theora_enc_init (GstTheoraEnc * enc)
310 {
311   GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (enc));
312
313   enc->video_bitrate = THEORA_DEF_BITRATE;
314   enc->video_quality = THEORA_DEF_QUALITY;
315   enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
316   enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
317   enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
318
319   enc->speed_level = THEORA_DEF_SPEEDLEVEL;
320   enc->vp3_compatible = THEORA_DEF_VP3_COMPATIBLE;
321   enc->drop_frames = THEORA_DEF_DROP_FRAMES;
322   enc->cap_overflow = THEORA_DEF_CAP_OVERFLOW;
323   enc->cap_underflow = THEORA_DEF_CAP_UNDERFLOW;
324   enc->rate_buffer = THEORA_DEF_RATE_BUFFER;
325
326   enc->multipass_mode = THEORA_DEF_MULTIPASS_MODE;
327   enc->multipass_cache_file = THEORA_DEF_MULTIPASS_CACHE_FILE;
328 }
329
330 static void
331 theora_enc_clear_multipass_cache (GstTheoraEnc * enc)
332 {
333   if (enc->multipass_cache_fd) {
334     g_io_channel_shutdown (enc->multipass_cache_fd, TRUE, NULL);
335     g_io_channel_unref (enc->multipass_cache_fd);
336     enc->multipass_cache_fd = NULL;
337   }
338
339   if (enc->multipass_cache_adapter) {
340     gst_object_unref (enc->multipass_cache_adapter);
341     enc->multipass_cache_adapter = NULL;
342   }
343 }
344
345 static void
346 theora_enc_finalize (GObject * object)
347 {
348   GstTheoraEnc *enc = GST_THEORA_ENC (object);
349
350   GST_DEBUG_OBJECT (enc, "Finalizing");
351   if (enc->encoder)
352     th_encode_free (enc->encoder);
353   th_comment_clear (&enc->comment);
354   th_info_clear (&enc->info);
355   g_free (enc->multipass_cache_file);
356
357   theora_enc_clear_multipass_cache (enc);
358
359   if (enc->input_state)
360     gst_video_codec_state_unref (enc->input_state);
361
362   G_OBJECT_CLASS (parent_class)->finalize (object);
363 }
364
365 static gboolean
366 theora_enc_flush (GstVideoEncoder * encoder)
367 {
368   GstTheoraEnc *enc = GST_THEORA_ENC (encoder);
369   ogg_uint32_t keyframe_force;
370   int rate_flags;
371
372
373   if (enc->input_state == NULL) {
374     GST_INFO_OBJECT (enc, "Not configured yet, returning FALSE");
375
376     return FALSE;
377   }
378
379   GST_OBJECT_LOCK (enc);
380   enc->info.target_bitrate = enc->video_bitrate;
381   enc->info.quality = enc->video_quality;
382   enc->bitrate_changed = FALSE;
383   enc->quality_changed = FALSE;
384   GST_OBJECT_UNLOCK (enc);
385
386   if (enc->encoder)
387     th_encode_free (enc->encoder);
388
389   enc->encoder = th_encode_alloc (&enc->info);
390   /* We ensure this function cannot fail. */
391   g_assert (enc->encoder != NULL);
392   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level,
393       sizeof (enc->speed_level));
394   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_VP3_COMPATIBLE,
395       &enc->vp3_compatible, sizeof (enc->vp3_compatible));
396
397   rate_flags = 0;
398   if (enc->drop_frames)
399     rate_flags |= TH_RATECTL_DROP_FRAMES;
400   if (enc->drop_frames)
401     rate_flags |= TH_RATECTL_CAP_OVERFLOW;
402   if (enc->drop_frames)
403     rate_flags |= TH_RATECTL_CAP_UNDERFLOW;
404   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_FLAGS,
405       &rate_flags, sizeof (rate_flags));
406
407   if (enc->rate_buffer) {
408     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_BUFFER,
409         &enc->rate_buffer, sizeof (enc->rate_buffer));
410   } else {
411     /* FIXME */
412   }
413
414   keyframe_force = enc->keyframe_auto ?
415       enc->keyframe_force : enc->keyframe_freq;
416   th_encode_ctl (enc->encoder, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
417       &keyframe_force, sizeof (keyframe_force));
418
419   /* Get placeholder data */
420   if (enc->multipass_cache_fd
421       && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS)
422     theora_enc_write_multipass_cache (enc, TRUE, FALSE);
423
424   return TRUE;
425 }
426
427 static gboolean
428 theora_enc_start (GstVideoEncoder * benc)
429 {
430   GstTheoraEnc *enc;
431
432   GST_DEBUG_OBJECT (benc, "start: init theora");
433   enc = GST_THEORA_ENC (benc);
434
435   if (enc->multipass_mode >= MULTIPASS_MODE_FIRST_PASS) {
436     GError *err = NULL;
437
438     if (!enc->multipass_cache_file) {
439       GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL), (NULL));
440       return FALSE;
441     }
442     enc->multipass_cache_fd =
443         g_io_channel_new_file (enc->multipass_cache_file,
444         (enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS ? "w" : "r"), &err);
445
446     if (enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS)
447       enc->multipass_cache_adapter = gst_adapter_new ();
448
449     if (!enc->multipass_cache_fd) {
450       GST_ELEMENT_ERROR (enc, RESOURCE, OPEN_READ, (NULL),
451           ("Failed to open multipass cache file: %s", err->message));
452       g_error_free (err);
453       return FALSE;
454     }
455
456     g_io_channel_set_encoding (enc->multipass_cache_fd, NULL, NULL);
457   }
458
459   enc->packetno = 0;
460   enc->initialised = FALSE;
461
462   return TRUE;
463 }
464
465 static gboolean
466 theora_enc_stop (GstVideoEncoder * benc)
467 {
468   GstTheoraEnc *enc;
469
470   GST_DEBUG_OBJECT (benc, "stop: clearing theora state");
471   enc = GST_THEORA_ENC (benc);
472
473   if (enc->encoder)
474     th_encode_free (enc->encoder);
475   enc->encoder = NULL;
476   th_comment_clear (&enc->comment);
477   th_info_clear (&enc->info);
478
479   if (enc->input_state)
480     gst_video_codec_state_unref (enc->input_state);
481   enc->input_state = NULL;
482
483   /* Everything else is handled in reset() */
484   theora_enc_clear_multipass_cache (enc);
485
486   return TRUE;
487 }
488
489 static char *
490 theora_enc_get_supported_formats (void)
491 {
492   th_enc_ctx *encoder;
493   th_info info;
494   struct
495   {
496     th_pixel_fmt pixelformat;
497     const char *fourcc;
498   } formats[] = {
499     {
500     TH_PF_420, "I420"}, {
501     TH_PF_422, "Y42B"}, {
502     TH_PF_444, "Y444"}
503   };
504   GString *string = NULL;
505   guint i;
506
507   th_info_init (&info);
508   info.frame_width = 16;
509   info.frame_height = 16;
510   info.fps_numerator = 25;
511   info.fps_denominator = 1;
512   for (i = 0; i < G_N_ELEMENTS (formats); i++) {
513     info.pixel_fmt = formats[i].pixelformat;
514
515     encoder = th_encode_alloc (&info);
516     if (encoder == NULL)
517       continue;
518
519     GST_LOG ("format %s is supported", formats[i].fourcc);
520     th_encode_free (encoder);
521
522     if (string == NULL) {
523       string = g_string_new (formats[i].fourcc);
524     } else {
525       g_string_append (string, ", ");
526       g_string_append (string, formats[i].fourcc);
527     }
528   }
529   th_info_clear (&info);
530
531   return string == NULL ? NULL : g_string_free (string, FALSE);
532 }
533
534 static GstCaps *
535 theora_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
536 {
537   GstCaps *caps, *ret;
538   char *supported_formats, *caps_string;
539
540   supported_formats = theora_enc_get_supported_formats ();
541   if (!supported_formats) {
542     GST_WARNING ("no supported formats found. Encoder disabled?");
543     return gst_caps_new_empty ();
544   }
545
546   caps_string = g_strdup_printf ("video/x-raw, "
547       "format = (string) { %s }, "
548       "framerate = (fraction) [1/MAX, MAX], "
549       "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]",
550       supported_formats);
551   caps = gst_caps_from_string (caps_string);
552   g_free (caps_string);
553   g_free (supported_formats);
554   GST_DEBUG ("Supported caps: %" GST_PTR_FORMAT, caps);
555
556   ret = gst_video_encoder_proxy_getcaps (encoder, caps, filter);
557   gst_caps_unref (caps);
558
559   return ret;
560 }
561
562 static gboolean
563 theora_enc_set_format (GstVideoEncoder * benc, GstVideoCodecState * state)
564 {
565   GstTheoraEnc *enc = GST_THEORA_ENC (benc);
566   GstVideoInfo *info = &state->info;
567
568   enc->width = GST_VIDEO_INFO_WIDTH (info);
569   enc->height = GST_VIDEO_INFO_HEIGHT (info);
570
571   th_info_clear (&enc->info);
572   th_info_init (&enc->info);
573   /* Theora has a divisible-by-sixteen restriction for the encoded video size but
574    * we can define a picture area using pic_width/pic_height */
575   enc->info.frame_width = GST_ROUND_UP_16 (enc->width);
576   enc->info.frame_height = GST_ROUND_UP_16 (enc->height);
577   enc->info.pic_width = enc->width;
578   enc->info.pic_height = enc->height;
579   switch (GST_VIDEO_INFO_FORMAT (info)) {
580     case GST_VIDEO_FORMAT_I420:
581       enc->info.pixel_fmt = TH_PF_420;
582       break;
583     case GST_VIDEO_FORMAT_Y42B:
584       enc->info.pixel_fmt = TH_PF_422;
585       break;
586     case GST_VIDEO_FORMAT_Y444:
587       enc->info.pixel_fmt = TH_PF_444;
588       break;
589     default:
590       g_assert_not_reached ();
591   }
592
593   enc->info.fps_numerator = enc->fps_n = GST_VIDEO_INFO_FPS_N (info);
594   enc->info.fps_denominator = enc->fps_d = GST_VIDEO_INFO_FPS_D (info);
595   enc->info.aspect_numerator = GST_VIDEO_INFO_PAR_N (info);
596   enc->info.aspect_denominator = GST_VIDEO_INFO_PAR_D (info);
597
598   enc->info.colorspace = TH_CS_UNSPECIFIED;
599
600   /* Save input state */
601   if (enc->input_state)
602     gst_video_codec_state_unref (enc->input_state);
603   enc->input_state = gst_video_codec_state_ref (state);
604
605   /* as done in theora */
606   enc->info.keyframe_granule_shift = _ilog (enc->keyframe_force - 1);
607   GST_DEBUG_OBJECT (enc,
608       "keyframe_frequency_force is %d, granule shift is %d",
609       enc->keyframe_force, enc->info.keyframe_granule_shift);
610
611   theora_enc_flush (benc);
612   enc->initialised = TRUE;
613
614   return TRUE;
615 }
616
617 static GstFlowReturn
618 theora_enc_pre_push (GstVideoEncoder * benc, GstVideoCodecFrame * frame)
619 {
620   GstTheoraEnc *enc = GST_THEORA_ENC (benc);
621   guint64 pfn;
622
623   /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
624    * time representation */
625   /* granulepos from sync frame */
626   pfn = frame->presentation_frame_number - frame->distance_from_sync;
627   /* correct to correspond to linear running time */
628   pfn -= enc->pfn_offset;
629   pfn += enc->granulepos_offset + 1;
630   /* granulepos */
631   GST_BUFFER_OFFSET_END (frame->output_buffer) =
632       (pfn << enc->info.keyframe_granule_shift) + frame->distance_from_sync;
633   GST_BUFFER_OFFSET (frame->output_buffer) = granulepos_to_timestamp (enc,
634       GST_BUFFER_OFFSET_END (frame->output_buffer));
635
636   return GST_FLOW_OK;
637 }
638
639 static GstFlowReturn
640 theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet)
641 {
642   GstVideoEncoder *benc;
643   GstFlowReturn ret;
644   GstVideoCodecFrame *frame;
645
646   benc = GST_VIDEO_ENCODER (enc);
647
648   frame = gst_video_encoder_get_oldest_frame (benc);
649   if (gst_video_encoder_allocate_output_frame (benc, frame,
650           packet->bytes) != GST_FLOW_OK) {
651     GST_WARNING_OBJECT (enc, "Could not allocate buffer");
652     gst_video_codec_frame_unref (frame);
653     ret = GST_FLOW_ERROR;
654     goto done;
655   }
656
657   if (packet->bytes > 0)
658     gst_buffer_fill (frame->output_buffer, 0, packet->packet, packet->bytes);
659
660   /* the second most significant bit of the first data byte is cleared
661    * for keyframes */
662   if (packet->bytes > 0 && (packet->packet[0] & 0x40) == 0) {
663     GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
664   } else {
665     GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
666   }
667   enc->packetno++;
668
669   ret = gst_video_encoder_finish_frame (benc, frame);
670
671 done:
672   return ret;
673 }
674
675 static GstCaps *
676 theora_set_header_on_caps (GstCaps * caps, GList * buffers)
677 {
678   GstStructure *structure;
679   GValue array = { 0 };
680   GValue value = { 0 };
681   GstBuffer *buffer;
682   GList *walk;
683
684   caps = gst_caps_make_writable (caps);
685   structure = gst_caps_get_structure (caps, 0);
686
687   /* put copies of the buffers in a fixed list */
688   g_value_init (&array, GST_TYPE_ARRAY);
689
690   for (walk = buffers; walk; walk = walk->next) {
691     buffer = walk->data;
692     g_value_init (&value, GST_TYPE_BUFFER);
693     gst_value_set_buffer (&value, buffer);
694     gst_value_array_append_value (&array, &value);
695     g_value_unset (&value);
696   }
697
698   gst_structure_take_value (structure, "streamheader", &array);
699
700   return caps;
701 }
702
703 static void
704 theora_enc_init_buffer (th_ycbcr_buffer buf, GstVideoFrame * frame)
705 {
706   GstVideoInfo vinfo;
707   guint i;
708
709   /* According to Theora developer Timothy Terriberry, the Theora
710    * encoder will not use memory outside of pic_width/height, even when
711    * the frame size is bigger. The values outside this region will be encoded
712    * to default values.
713    * Due to this, setting the frame's width/height as the buffer width/height
714    * is perfectly ok, even though it does not strictly look ok.
715    */
716
717   gst_video_info_init (&vinfo);
718   gst_video_info_set_format (&vinfo, GST_VIDEO_FRAME_FORMAT (frame),
719       GST_ROUND_UP_16 (GST_VIDEO_FRAME_WIDTH (frame)),
720       GST_ROUND_UP_16 (GST_VIDEO_FRAME_HEIGHT (frame)));
721
722   for (i = 0; i < 3; i++) {
723     buf[i].width = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, i);
724     buf[i].height = GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, i);
725     buf[i].data = GST_VIDEO_FRAME_COMP_DATA (frame, i);
726     buf[i].stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
727   }
728 }
729
730 static gboolean
731 theora_enc_read_multipass_cache (GstTheoraEnc * enc)
732 {
733   GstBuffer *cache_buf;
734   const guint8 *cache_data;
735   gsize bytes_read = 0;
736   gssize bytes_consumed = 0;
737   GIOStatus stat = G_IO_STATUS_NORMAL;
738   gboolean done = FALSE;
739
740   while (!done) {
741     if (gst_adapter_available (enc->multipass_cache_adapter) == 0) {
742       GstMapInfo minfo;
743
744       cache_buf = gst_buffer_new_allocate (NULL, 512, NULL);
745
746       gst_buffer_map (cache_buf, &minfo, GST_MAP_WRITE);
747
748       stat = g_io_channel_read_chars (enc->multipass_cache_fd,
749           (gchar *) minfo.data, minfo.size, &bytes_read, NULL);
750
751       if (bytes_read <= 0) {
752         gst_buffer_unmap (cache_buf, &minfo);
753         gst_buffer_unref (cache_buf);
754         break;
755       } else {
756         gst_buffer_unmap (cache_buf, &minfo);
757         gst_buffer_resize (cache_buf, 0, bytes_read);
758
759         gst_adapter_push (enc->multipass_cache_adapter, cache_buf);
760       }
761     }
762     if (gst_adapter_available (enc->multipass_cache_adapter) == 0)
763       break;
764
765     bytes_read =
766         MIN (gst_adapter_available (enc->multipass_cache_adapter), 512);
767
768     cache_data = gst_adapter_map (enc->multipass_cache_adapter, bytes_read);
769
770     bytes_consumed =
771         th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_IN, (guint8 *) cache_data,
772         bytes_read);
773     gst_adapter_unmap (enc->multipass_cache_adapter);
774
775     done = bytes_consumed <= 0;
776     if (bytes_consumed > 0)
777       gst_adapter_flush (enc->multipass_cache_adapter, bytes_consumed);
778   }
779
780   if (stat == G_IO_STATUS_ERROR || (stat == G_IO_STATUS_EOF && bytes_read == 0)
781       || bytes_consumed < 0) {
782     GST_ELEMENT_ERROR (enc, RESOURCE, READ, (NULL),
783         ("Failed to read multipass cache file"));
784     return FALSE;
785   }
786   return TRUE;
787 }
788
789 static gboolean
790 theora_enc_write_multipass_cache (GstTheoraEnc * enc, gboolean begin,
791     gboolean eos)
792 {
793   GError *err = NULL;
794   GIOStatus stat = G_IO_STATUS_NORMAL;
795   gint bytes_read = 0;
796   gsize bytes_written = 0;
797   gchar *buf;
798
799   if (begin) {
800     stat = g_io_channel_seek_position (enc->multipass_cache_fd, 0, G_SEEK_SET,
801         &err);
802
803     if (stat == G_IO_STATUS_ERROR) {
804       if (eos)
805         GST_ELEMENT_WARNING (enc, RESOURCE, WRITE, (NULL),
806             ("Failed to seek to beginning of multipass cache file: %s",
807                 err->message));
808       else
809         GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
810             ("Failed to seek to beginning of multipass cache file: %s",
811                 err->message));
812       g_error_free (err);
813       return FALSE;
814     }
815   }
816
817
818   do {
819     bytes_read =
820         th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_OUT, &buf, sizeof (buf));
821     if (bytes_read > 0)
822       g_io_channel_write_chars (enc->multipass_cache_fd, buf, bytes_read,
823           &bytes_written, &err);
824   } while (bytes_read > 0 && bytes_written > 0 && !err);
825
826   if (bytes_read < 0 || err) {
827     if (bytes_read < 0) {
828       GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
829           ("Failed to read multipass cache data: %d", bytes_read));
830     } else {
831       GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL),
832           ("Failed to write multipass cache file: %s", err->message));
833     }
834     if (err)
835       g_error_free (err);
836
837     return FALSE;
838   }
839
840   return TRUE;
841 }
842
843 static void
844 theora_enc_reset_ts (GstTheoraEnc * enc, GstClockTime running_time, gint pfn)
845 {
846   enc->granulepos_offset =
847       gst_util_uint64_scale (running_time, enc->fps_n, GST_SECOND * enc->fps_d);
848   enc->timestamp_offset = running_time;
849   enc->pfn_offset = pfn;
850 }
851
852 static GstBuffer *
853 theora_enc_buffer_from_header_packet (GstTheoraEnc * enc, ogg_packet * packet)
854 {
855   GstBuffer *outbuf;
856
857   outbuf =
858       gst_video_encoder_allocate_output_buffer (GST_VIDEO_ENCODER (enc),
859       packet->bytes);
860   gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
861   GST_BUFFER_OFFSET (outbuf) = 0;
862   GST_BUFFER_OFFSET_END (outbuf) = 0;
863   GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
864   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
865   GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_HEADER);
866
867   GST_DEBUG ("created header packet buffer, %u bytes",
868       (guint) gst_buffer_get_size (outbuf));
869   return outbuf;
870 }
871
872 static GstFlowReturn
873 theora_enc_handle_frame (GstVideoEncoder * benc, GstVideoCodecFrame * frame)
874 {
875   GstTheoraEnc *enc;
876   ogg_packet op;
877   GstClockTime timestamp, running_time;
878   GstFlowReturn ret;
879   gboolean force_keyframe;
880
881   enc = GST_THEORA_ENC (benc);
882
883   /* we keep track of two timelines.
884    * - The timestamps from the incoming buffers, which we copy to the outgoing
885    *   encoded buffers as-is. We need to do this as we simply forward the
886    *   newsegment events.
887    * - The running_time of the buffers, which we use to construct the granulepos
888    *   in the packets.
889    */
890   timestamp = frame->pts;
891
892   /* incoming buffers are clipped, so this should be positive */
893   running_time =
894       gst_segment_to_running_time (&GST_VIDEO_ENCODER_INPUT_SEGMENT (enc),
895       GST_FORMAT_TIME, timestamp);
896
897   GST_OBJECT_LOCK (enc);
898   if (enc->bitrate_changed) {
899     long int bitrate = enc->video_bitrate;
900
901     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_BITRATE, &bitrate,
902         sizeof (long int));
903     enc->bitrate_changed = FALSE;
904   }
905
906   if (enc->quality_changed) {
907     long int quality = enc->video_quality;
908
909     th_encode_ctl (enc->encoder, TH_ENCCTL_SET_QUALITY, &quality,
910         sizeof (long int));
911     enc->quality_changed = FALSE;
912   }
913
914   /* see if we need to schedule a keyframe */
915   force_keyframe = GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame);
916   GST_OBJECT_UNLOCK (enc);
917
918   if (enc->packetno == 0) {
919     /* no packets written yet, setup headers */
920     GstCaps *caps;
921     GstBuffer *buf;
922     GList *buffers = NULL;
923     int result;
924     GstVideoCodecState *state;
925
926     enc->granulepos_offset = 0;
927     enc->timestamp_offset = 0;
928
929     GST_DEBUG_OBJECT (enc, "output headers");
930     /* Theora streams begin with three headers; the initial header (with
931        most of the codec setup parameters) which is mandated by the Ogg
932        bitstream spec.  The second header holds any comment fields.  The
933        third header holds the bitstream codebook.  We merely need to
934        make the headers, then pass them to libtheora one at a time;
935        libtheora handles the additional Ogg bitstream constraints */
936
937     /* create the remaining theora headers */
938     th_comment_clear (&enc->comment);
939     th_comment_init (&enc->comment);
940
941     while ((result =
942             th_encode_flushheader (enc->encoder, &enc->comment, &op)) > 0) {
943       buf = theora_enc_buffer_from_header_packet (enc, &op);
944       buffers = g_list_prepend (buffers, buf);
945     }
946     if (result < 0) {
947       g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
948       g_list_free (buffers);
949       goto encoder_disabled;
950     }
951
952     buffers = g_list_reverse (buffers);
953
954     /* mark buffers and put on caps */
955     caps = gst_caps_new_empty_simple ("video/x-theora");
956     caps = theora_set_header_on_caps (caps, buffers);
957     state = gst_video_encoder_set_output_state (benc, caps, enc->input_state);
958
959     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, state->caps);
960
961     gst_video_codec_state_unref (state);
962
963     gst_video_encoder_negotiate (GST_VIDEO_ENCODER (enc));
964
965     gst_video_encoder_set_headers (benc, buffers);
966
967     theora_enc_reset_ts (enc, running_time, frame->presentation_frame_number);
968   }
969
970   {
971     th_ycbcr_buffer ycbcr;
972     gint res, keyframe_interval;
973     GstVideoFrame vframe;
974
975     if (force_keyframe) {
976       /* if we want a keyframe, temporarily reset the max keyframe interval
977        * to 1, which will cause libtheora to emit one. There is no API to
978        * request a keyframe at the moment. */
979       keyframe_interval = 1;
980       th_encode_ctl (enc->encoder, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
981           &keyframe_interval, sizeof (keyframe_interval));
982     }
983
984     if (enc->multipass_cache_fd
985         && enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS) {
986       if (!theora_enc_read_multipass_cache (enc)) {
987         ret = GST_FLOW_ERROR;
988         goto multipass_read_failed;
989       }
990     }
991
992     gst_video_frame_map (&vframe, &enc->input_state->info, frame->input_buffer,
993         GST_MAP_READ);
994     theora_enc_init_buffer (ycbcr, &vframe);
995
996     res = th_encode_ycbcr_in (enc->encoder, ycbcr);
997     gst_video_frame_unmap (&vframe);
998
999     /* none of the failure cases can happen here */
1000     g_assert (res == 0);
1001
1002     if (enc->multipass_cache_fd
1003         && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS) {
1004       if (!theora_enc_write_multipass_cache (enc, FALSE, FALSE)) {
1005         ret = GST_FLOW_ERROR;
1006         goto multipass_write_failed;
1007       }
1008     }
1009
1010     ret = GST_FLOW_OK;
1011     while (th_encode_packetout (enc->encoder, 0, &op)) {
1012       /* Reset the max keyframe interval to its original state, and reset
1013        * the flag so we don't create more keyframes if we loop */
1014       if (force_keyframe) {
1015         keyframe_interval =
1016             enc->keyframe_auto ? enc->keyframe_force : enc->keyframe_freq;
1017         th_encode_ctl (enc->encoder, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
1018             &keyframe_interval, sizeof (keyframe_interval));
1019         force_keyframe = FALSE;
1020       }
1021
1022       ret = theora_push_packet (enc, &op);
1023       if (ret != GST_FLOW_OK)
1024         goto beach;
1025     }
1026   }
1027
1028 beach:
1029   gst_video_codec_frame_unref (frame);
1030   return ret;
1031
1032   /* ERRORS */
1033 multipass_read_failed:
1034   {
1035     gst_video_codec_frame_unref (frame);
1036     return ret;
1037   }
1038 multipass_write_failed:
1039   {
1040     gst_video_codec_frame_unref (frame);
1041     return ret;
1042   }
1043 encoder_disabled:
1044   {
1045     gst_video_codec_frame_unref (frame);
1046     GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1047         ("libtheora has been compiled with the encoder disabled"));
1048     return GST_FLOW_ERROR;
1049   }
1050 }
1051
1052 static gboolean
1053 theora_enc_finish (GstVideoEncoder * benc)
1054 {
1055   GstTheoraEnc *enc;
1056   ogg_packet op;
1057
1058   enc = GST_THEORA_ENC (benc);
1059
1060   if (enc->initialised) {
1061     /* push last packet with eos flag, should not be called */
1062     while (th_encode_packetout (enc->encoder, 1, &op)) {
1063       theora_push_packet (enc, &op);
1064     }
1065   }
1066   if (enc->initialised && enc->multipass_cache_fd
1067       && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS)
1068     theora_enc_write_multipass_cache (enc, TRUE, TRUE);
1069
1070   theora_enc_clear_multipass_cache (enc);
1071
1072   return TRUE;
1073 }
1074
1075 static gboolean
1076 theora_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
1077 {
1078   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
1079
1080   return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
1081       query);
1082 }
1083
1084 static void
1085 theora_enc_set_property (GObject * object, guint prop_id,
1086     const GValue * value, GParamSpec * pspec)
1087 {
1088   GstTheoraEnc *enc = GST_THEORA_ENC (object);
1089
1090   switch (prop_id) {
1091     case PROP_BITRATE:
1092       GST_OBJECT_LOCK (enc);
1093       enc->video_bitrate = g_value_get_int (value) * 1000;
1094       enc->video_quality = 0;
1095       enc->bitrate_changed = TRUE;
1096       GST_OBJECT_UNLOCK (enc);
1097       break;
1098     case PROP_QUALITY:
1099       GST_OBJECT_LOCK (enc);
1100       if (GST_STATE (enc) >= GST_STATE_PAUSED && enc->video_quality == 0) {
1101         GST_WARNING_OBJECT (object, "Can't change from bitrate to quality mode"
1102             " while playing");
1103       } else {
1104         enc->video_quality = g_value_get_int (value);
1105         enc->video_bitrate = 0;
1106         enc->quality_changed = TRUE;
1107       }
1108       GST_OBJECT_UNLOCK (enc);
1109       break;
1110     case PROP_KEYFRAME_AUTO:
1111       enc->keyframe_auto = g_value_get_boolean (value);
1112       break;
1113     case PROP_KEYFRAME_FREQ:
1114       enc->keyframe_freq = g_value_get_int (value);
1115       break;
1116     case PROP_KEYFRAME_FREQ_FORCE:
1117       enc->keyframe_force = g_value_get_int (value);
1118       break;
1119     case PROP_SPEEDLEVEL:
1120       enc->speed_level = g_value_get_int (value);
1121       break;
1122     case PROP_VP3_COMPATIBLE:
1123       enc->vp3_compatible = g_value_get_boolean (value);
1124       break;
1125     case PROP_DROP_FRAMES:
1126       enc->drop_frames = g_value_get_boolean (value);
1127       break;
1128     case PROP_CAP_OVERFLOW:
1129       enc->cap_overflow = g_value_get_boolean (value);
1130       break;
1131     case PROP_CAP_UNDERFLOW:
1132       enc->cap_underflow = g_value_get_boolean (value);
1133       break;
1134     case PROP_RATE_BUFFER:
1135       enc->rate_buffer = g_value_get_int (value);
1136       break;
1137     case PROP_MULTIPASS_CACHE_FILE:
1138       enc->multipass_cache_file = g_value_dup_string (value);
1139       break;
1140     case PROP_MULTIPASS_MODE:
1141       enc->multipass_mode = g_value_get_enum (value);
1142       break;
1143     default:
1144       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1145       break;
1146   }
1147 }
1148
1149 static void
1150 theora_enc_get_property (GObject * object, guint prop_id,
1151     GValue * value, GParamSpec * pspec)
1152 {
1153   GstTheoraEnc *enc = GST_THEORA_ENC (object);
1154
1155   switch (prop_id) {
1156     case PROP_BITRATE:
1157       GST_OBJECT_LOCK (enc);
1158       g_value_set_int (value, enc->video_bitrate / 1000);
1159       GST_OBJECT_UNLOCK (enc);
1160       break;
1161     case PROP_QUALITY:
1162       GST_OBJECT_LOCK (enc);
1163       g_value_set_int (value, enc->video_quality);
1164       GST_OBJECT_UNLOCK (enc);
1165       break;
1166     case PROP_KEYFRAME_AUTO:
1167       g_value_set_boolean (value, enc->keyframe_auto);
1168       break;
1169     case PROP_KEYFRAME_FREQ:
1170       g_value_set_int (value, enc->keyframe_freq);
1171       break;
1172     case PROP_KEYFRAME_FREQ_FORCE:
1173       g_value_set_int (value, enc->keyframe_force);
1174       break;
1175     case PROP_SPEEDLEVEL:
1176       g_value_set_int (value, enc->speed_level);
1177       break;
1178     case PROP_VP3_COMPATIBLE:
1179       g_value_set_boolean (value, enc->vp3_compatible);
1180       break;
1181     case PROP_DROP_FRAMES:
1182       g_value_set_boolean (value, enc->drop_frames);
1183       break;
1184     case PROP_CAP_OVERFLOW:
1185       g_value_set_boolean (value, enc->cap_overflow);
1186       break;
1187     case PROP_CAP_UNDERFLOW:
1188       g_value_set_boolean (value, enc->cap_underflow);
1189       break;
1190     case PROP_RATE_BUFFER:
1191       g_value_set_int (value, enc->rate_buffer);
1192       break;
1193     case PROP_MULTIPASS_CACHE_FILE:
1194       g_value_set_string (value, enc->multipass_cache_file);
1195       break;
1196     case PROP_MULTIPASS_MODE:
1197       g_value_set_enum (value, enc->multipass_mode);
1198       break;
1199     default:
1200       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1201       break;
1202   }
1203 }