1 /* VPX
2 * Copyright (C) 2006 David Schleef <ds@schleef.org>
3 * Copyright (C) 2010 Entropy Wave Inc
4 * Copyright (C) 2010-2012 Sebastian Dröge <sebastian.droege@collabora.co.uk>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #if defined(HAVE_VP8_ENCODER) || defined(HAVE_VP9_ENCODER)
28
29 /* glib decided in 2.32 it would be a great idea to deprecated GValueArray without
30 * providing an alternative
31 *
32 * See https://bugzilla.gnome.org/show_bug.cgi?id=667228
33 * */
34 #define GLIB_DISABLE_DEPRECATION_WARNINGS
35
36 #include <gst/tag/tag.h>
37 #include <gst/video/video.h>
38 #include <string.h>
39
40 #include "gstvp8utils.h"
41 #include "gstvpxenc.h"
42
43 GST_DEBUG_CATEGORY_STATIC (gst_vpxenc_debug);
44 #define GST_CAT_DEFAULT gst_vpxenc_debug
45
46 /* From vp8/vp8_cx_iface.c and vp9/vp9_cx_iface.c */
47 #define DEFAULT_PROFILE 0
48
49 #define DEFAULT_RC_END_USAGE VPX_VBR
50 #define DEFAULT_RC_TARGET_BITRATE 0
51 #define DEFAULT_RC_MIN_QUANTIZER 4
52 #define DEFAULT_RC_MAX_QUANTIZER 63
53
54 #define DEFAULT_RC_DROPFRAME_THRESH 0
55 #define DEFAULT_RC_RESIZE_ALLOWED 0
56 #define DEFAULT_RC_RESIZE_UP_THRESH 30
57 #define DEFAULT_RC_RESIZE_DOWN_THRESH 60
58 #define DEFAULT_RC_UNDERSHOOT_PCT 100
59 #define DEFAULT_RC_OVERSHOOT_PCT 100
60 #define DEFAULT_RC_BUF_SZ 6000
61 #define DEFAULT_RC_BUF_INITIAL_SZ 4000
62 #define DEFAULT_RC_BUF_OPTIMAL_SZ 5000
63 #define DEFAULT_RC_2PASS_VBR_BIAS_PCT 50
64 #define DEFAULT_RC_2PASS_VBR_MINSECTION_PCT 0
65 #define DEFAULT_RC_2PASS_VBR_MAXSECTION_PCT 400
66
67 #define DEFAULT_KF_MODE VPX_KF_AUTO
68 #define DEFAULT_KF_MAX_DIST 128
69
70 #define DEFAULT_MULTIPASS_MODE VPX_RC_ONE_PASS
71 #define DEFAULT_MULTIPASS_CACHE_FILE "multipass.cache"
72
73 #define DEFAULT_TS_NUMBER_LAYERS 1
74 #define DEFAULT_TS_TARGET_BITRATE NULL
75 #define DEFAULT_TS_RATE_DECIMATOR NULL
76 #define DEFAULT_TS_PERIODICITY 0
77 #define DEFAULT_TS_LAYER_ID NULL
78 #define DEFAULT_TS_LAYER_FLAGS NULL
79 #define DEFAULT_TS_LAYER_SYNC_FLAGS NULL
80
81 #define DEFAULT_ERROR_RESILIENT 0
82 #define DEFAULT_LAG_IN_FRAMES 0
83
84 #define DEFAULT_THREADS 0
85
86 #define DEFAULT_H_SCALING_MODE VP8E_NORMAL
87 #define DEFAULT_V_SCALING_MODE VP8E_NORMAL
88 #define DEFAULT_CPU_USED 0
89 #define DEFAULT_ENABLE_AUTO_ALT_REF FALSE
90 #define DEFAULT_DEADLINE VPX_DL_GOOD_QUALITY
91 #define DEFAULT_NOISE_SENSITIVITY 0
92 #define DEFAULT_SHARPNESS 0
93
94 /* Use same default value as Chromium/webrtc. */
95 #define DEFAULT_STATIC_THRESHOLD 1
96
97 #define DEFAULT_TOKEN_PARTITIONS 0
98 #define DEFAULT_ARNR_MAXFRAMES 0
99 #define DEFAULT_ARNR_STRENGTH 3
100 #define DEFAULT_ARNR_TYPE 3
101 #define DEFAULT_TUNING VP8_TUNE_PSNR
102 #define DEFAULT_CQ_LEVEL 10
103 #define DEFAULT_MAX_INTRA_BITRATE_PCT 0
104 #define DEFAULT_TIMEBASE_N 0
105 #define DEFAULT_TIMEBASE_D 1
106
107 #define DEFAULT_BITS_PER_PIXEL 0.0434
108
109 enum
110 {
111 PROP_0,
112 PROP_RC_END_USAGE,
113 PROP_RC_TARGET_BITRATE,
114 PROP_RC_MIN_QUANTIZER,
115 PROP_RC_MAX_QUANTIZER,
116 PROP_RC_DROPFRAME_THRESH,
117 PROP_RC_RESIZE_ALLOWED,
118 PROP_RC_RESIZE_UP_THRESH,
119 PROP_RC_RESIZE_DOWN_THRESH,
120 PROP_RC_UNDERSHOOT_PCT,
121 PROP_RC_OVERSHOOT_PCT,
122 PROP_RC_BUF_SZ,
123 PROP_RC_BUF_INITIAL_SZ,
124 PROP_RC_BUF_OPTIMAL_SZ,
125 PROP_RC_2PASS_VBR_BIAS_PCT,
126 PROP_RC_2PASS_VBR_MINSECTION_PCT,
127 PROP_RC_2PASS_VBR_MAXSECTION_PCT,
128 PROP_KF_MODE,
129 PROP_KF_MAX_DIST,
130 PROP_TS_NUMBER_LAYERS,
131 PROP_TS_TARGET_BITRATE,
132 PROP_TS_RATE_DECIMATOR,
133 PROP_TS_PERIODICITY,
134 PROP_TS_LAYER_ID,
135 PROP_TS_LAYER_FLAGS,
136 PROP_TS_LAYER_SYNC_FLAGS,
137 PROP_MULTIPASS_MODE,
138 PROP_MULTIPASS_CACHE_FILE,
139 PROP_ERROR_RESILIENT,
140 PROP_LAG_IN_FRAMES,
141 PROP_THREADS,
142 PROP_DEADLINE,
143 PROP_H_SCALING_MODE,
144 PROP_V_SCALING_MODE,
145 PROP_CPU_USED,
146 PROP_ENABLE_AUTO_ALT_REF,
147 PROP_NOISE_SENSITIVITY,
148 PROP_SHARPNESS,
149 PROP_STATIC_THRESHOLD,
150 PROP_TOKEN_PARTITIONS,
151 PROP_ARNR_MAXFRAMES,
152 PROP_ARNR_STRENGTH,
153 PROP_ARNR_TYPE,
154 PROP_TUNING,
155 PROP_CQ_LEVEL,
156 PROP_MAX_INTRA_BITRATE_PCT,
157 PROP_TIMEBASE,
158 PROP_BITS_PER_PIXEL
159 };
160
161
162 #define GST_VPX_ENC_END_USAGE_TYPE (gst_vpx_enc_end_usage_get_type())
163 static GType
gst_vpx_enc_end_usage_get_type(void)164 gst_vpx_enc_end_usage_get_type (void)
165 {
166 static const GEnumValue values[] = {
167 {VPX_VBR, "Variable Bit Rate (VBR) mode", "vbr"},
168 {VPX_CBR, "Constant Bit Rate (CBR) mode", "cbr"},
169 {VPX_CQ, "Constant Quality Mode (CQ) mode", "cq"},
170 {0, NULL, NULL}
171 };
172 static GType id = 0;
173
174 if (g_once_init_enter ((gsize *) & id)) {
175 GType _id;
176
177 _id = g_enum_register_static ("GstVPXEncEndUsage", values);
178
179 g_once_init_leave ((gsize *) & id, _id);
180 }
181
182 return id;
183 }
184
185 #define GST_VPX_ENC_MULTIPASS_MODE_TYPE (gst_vpx_enc_multipass_mode_get_type())
186 static GType
gst_vpx_enc_multipass_mode_get_type(void)187 gst_vpx_enc_multipass_mode_get_type (void)
188 {
189 static const GEnumValue values[] = {
190 {VPX_RC_ONE_PASS, "One pass encoding (default)", "one-pass"},
191 {VPX_RC_FIRST_PASS, "First pass of multipass encoding", "first-pass"},
192 {VPX_RC_LAST_PASS, "Last pass of multipass encoding", "last-pass"},
193 {0, NULL, NULL}
194 };
195 static GType id = 0;
196
197 if (g_once_init_enter ((gsize *) & id)) {
198 GType _id;
199
200 _id = g_enum_register_static ("GstVPXEncMultipassMode", values);
201
202 g_once_init_leave ((gsize *) & id, _id);
203 }
204
205 return id;
206 }
207
208 #define GST_VPX_ENC_KF_MODE_TYPE (gst_vpx_enc_kf_mode_get_type())
209 static GType
gst_vpx_enc_kf_mode_get_type(void)210 gst_vpx_enc_kf_mode_get_type (void)
211 {
212 static const GEnumValue values[] = {
213 {VPX_KF_AUTO, "Determine optimal placement automatically", "auto"},
214 {VPX_KF_DISABLED, "Don't automatically place keyframes", "disabled"},
215 {0, NULL, NULL}
216 };
217 static GType id = 0;
218
219 if (g_once_init_enter ((gsize *) & id)) {
220 GType _id;
221
222 _id = g_enum_register_static ("GstVPXEncKfMode", values);
223
224 g_once_init_leave ((gsize *) & id, _id);
225 }
226
227 return id;
228 }
229
230 #define GST_VPX_ENC_TUNING_TYPE (gst_vpx_enc_tuning_get_type())
231 static GType
gst_vpx_enc_tuning_get_type(void)232 gst_vpx_enc_tuning_get_type (void)
233 {
234 static const GEnumValue values[] = {
235 {VP8_TUNE_PSNR, "Tune for PSNR", "psnr"},
236 {VP8_TUNE_SSIM, "Tune for SSIM", "ssim"},
237 {0, NULL, NULL}
238 };
239 static GType id = 0;
240
241 if (g_once_init_enter ((gsize *) & id)) {
242 GType _id;
243
244 _id = g_enum_register_static ("GstVPXEncTuning", values);
245
246 g_once_init_leave ((gsize *) & id, _id);
247 }
248
249 return id;
250 }
251
252 #define GST_VPX_ENC_SCALING_MODE_TYPE (gst_vpx_enc_scaling_mode_get_type())
253 static GType
gst_vpx_enc_scaling_mode_get_type(void)254 gst_vpx_enc_scaling_mode_get_type (void)
255 {
256 static const GEnumValue values[] = {
257 {VP8E_NORMAL, "Normal", "normal"},
258 {VP8E_FOURFIVE, "4:5", "4:5"},
259 {VP8E_THREEFIVE, "3:5", "3:5"},
260 {VP8E_ONETWO, "1:2", "1:2"},
261 {0, NULL, NULL}
262 };
263 static GType id = 0;
264
265 if (g_once_init_enter ((gsize *) & id)) {
266 GType _id;
267
268 _id = g_enum_register_static ("GstVPXEncScalingMode", values);
269
270 g_once_init_leave ((gsize *) & id, _id);
271 }
272
273 return id;
274 }
275
276 #define GST_VPX_ENC_TOKEN_PARTITIONS_TYPE (gst_vpx_enc_token_partitions_get_type())
277 static GType
gst_vpx_enc_token_partitions_get_type(void)278 gst_vpx_enc_token_partitions_get_type (void)
279 {
280 static const GEnumValue values[] = {
281 {VP8_ONE_TOKENPARTITION, "One token partition", "1"},
282 {VP8_TWO_TOKENPARTITION, "Two token partitions", "2"},
283 {VP8_FOUR_TOKENPARTITION, "Four token partitions", "4"},
284 {VP8_EIGHT_TOKENPARTITION, "Eight token partitions", "8"},
285 {0, NULL, NULL}
286 };
287 static GType id = 0;
288
289 if (g_once_init_enter ((gsize *) & id)) {
290 GType _id;
291
292 _id = g_enum_register_static ("GstVPXEncTokenPartitions", values);
293
294 g_once_init_leave ((gsize *) & id, _id);
295 }
296
297 return id;
298 }
299
300 #define GST_VPX_ENC_ER_FLAGS_TYPE (gst_vpx_enc_er_flags_get_type())
301 static GType
gst_vpx_enc_er_flags_get_type(void)302 gst_vpx_enc_er_flags_get_type (void)
303 {
304 static const GFlagsValue values[] = {
305 {VPX_ERROR_RESILIENT_DEFAULT, "Default error resilience", "default"},
306 {VPX_ERROR_RESILIENT_PARTITIONS,
307 "Allow partitions to be decoded independently", "partitions"},
308 {0, NULL, NULL}
309 };
310 static GType id = 0;
311
312 if (g_once_init_enter ((gsize *) & id)) {
313 GType _id;
314
315 _id = g_flags_register_static ("GstVPXEncErFlags", values);
316
317 g_once_init_leave ((gsize *) & id, _id);
318 }
319
320 return id;
321 }
322
323 #define GST_VPX_ENC_TS_LAYER_FLAGS_TYPE (gst_vpx_enc_ts_layer_flags_get_type())
324 static GType
gst_vpx_enc_ts_layer_flags_get_type(void)325 gst_vpx_enc_ts_layer_flags_get_type (void)
326 {
327 static const GFlagsValue values[] = {
328 {VP8_EFLAG_NO_REF_LAST, "Don't reference the last frame", "no-ref-last"},
329 {VP8_EFLAG_NO_REF_GF, "Don't reference the golden frame", "no-ref-golden"},
330 {VP8_EFLAG_NO_REF_ARF, "Don't reference the alternate reference frame",
331 "no-ref-alt"},
332 {VP8_EFLAG_NO_UPD_LAST, "Don't update the last frame", "no-upd-last"},
333 {VP8_EFLAG_NO_UPD_GF, "Don't update the golden frame", "no-upd-golden"},
334 {VP8_EFLAG_NO_UPD_ARF, "Don't update the alternate reference frame",
335 "no-upd-alt"},
336 {VP8_EFLAG_NO_UPD_ENTROPY, "Disable entropy update", "no-upd-entropy"},
337 {0, NULL, NULL}
338 };
339 static GType id = 0;
340
341 if (g_once_init_enter ((gsize *) & id)) {
342 GType _id;
343
344 _id = g_flags_register_static ("GstVPXEncTsLayerFlags", values);
345
346 g_once_init_leave ((gsize *) & id, _id);
347 }
348
349 return id;
350 }
351
352 static void gst_vpx_enc_finalize (GObject * object);
353 static void gst_vpx_enc_set_property (GObject * object, guint prop_id,
354 const GValue * value, GParamSpec * pspec);
355 static void gst_vpx_enc_get_property (GObject * object, guint prop_id,
356 GValue * value, GParamSpec * pspec);
357
358 static gboolean gst_vpx_enc_start (GstVideoEncoder * encoder);
359 static gboolean gst_vpx_enc_stop (GstVideoEncoder * encoder);
360 static gboolean gst_vpx_enc_set_format (GstVideoEncoder *
361 video_encoder, GstVideoCodecState * state);
362 static GstFlowReturn gst_vpx_enc_finish (GstVideoEncoder * video_encoder);
363 static gboolean gst_vpx_enc_flush (GstVideoEncoder * video_encoder);
364 static GstFlowReturn gst_vpx_enc_drain (GstVideoEncoder * video_encoder);
365 static GstFlowReturn gst_vpx_enc_handle_frame (GstVideoEncoder *
366 video_encoder, GstVideoCodecFrame * frame);
367 static gboolean gst_vpx_enc_sink_event (GstVideoEncoder *
368 video_encoder, GstEvent * event);
369 static gboolean gst_vpx_enc_propose_allocation (GstVideoEncoder * encoder,
370 GstQuery * query);
371 static gboolean gst_vpx_enc_transform_meta (GstVideoEncoder * encoder,
372 GstVideoCodecFrame * frame, GstMeta * meta);
373
374 #define parent_class gst_vpx_enc_parent_class
375 G_DEFINE_TYPE_WITH_CODE (GstVPXEnc, gst_vpx_enc, GST_TYPE_VIDEO_ENCODER,
376 G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
377 G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL););
378
379 static void
gst_vpx_enc_class_init(GstVPXEncClass * klass)380 gst_vpx_enc_class_init (GstVPXEncClass * klass)
381 {
382 GObjectClass *gobject_class;
383 GstVideoEncoderClass *video_encoder_class;
384
385 gobject_class = G_OBJECT_CLASS (klass);
386 video_encoder_class = GST_VIDEO_ENCODER_CLASS (klass);
387
388 gobject_class->set_property = gst_vpx_enc_set_property;
389 gobject_class->get_property = gst_vpx_enc_get_property;
390 gobject_class->finalize = gst_vpx_enc_finalize;
391
392 video_encoder_class->start = gst_vpx_enc_start;
393 video_encoder_class->stop = gst_vpx_enc_stop;
394 video_encoder_class->handle_frame = gst_vpx_enc_handle_frame;
395 video_encoder_class->set_format = gst_vpx_enc_set_format;
396 video_encoder_class->flush = gst_vpx_enc_flush;
397 video_encoder_class->finish = gst_vpx_enc_finish;
398 video_encoder_class->sink_event = gst_vpx_enc_sink_event;
399 video_encoder_class->propose_allocation = gst_vpx_enc_propose_allocation;
400 video_encoder_class->transform_meta = gst_vpx_enc_transform_meta;
401
402 g_object_class_install_property (gobject_class, PROP_RC_END_USAGE,
403 g_param_spec_enum ("end-usage", "Rate control mode",
404 "Rate control mode",
405 GST_VPX_ENC_END_USAGE_TYPE, DEFAULT_RC_END_USAGE,
406 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
407 GST_PARAM_DOC_SHOW_DEFAULT)));
408
409 g_object_class_install_property (gobject_class, PROP_RC_TARGET_BITRATE,
410 g_param_spec_int ("target-bitrate", "Target bitrate",
411 "Target bitrate (in bits/sec) (0: auto - bitrate depends on "
412 "resolution, see \"bits-per-pixel\" property for more info)",
413 0, G_MAXINT, DEFAULT_RC_TARGET_BITRATE,
414 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
415 GST_PARAM_DOC_SHOW_DEFAULT)));
416
417 g_object_class_install_property (gobject_class, PROP_RC_MIN_QUANTIZER,
418 g_param_spec_int ("min-quantizer", "Minimum Quantizer",
419 "Minimum Quantizer (best)",
420 0, 63, DEFAULT_RC_MIN_QUANTIZER,
421 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
422 GST_PARAM_DOC_SHOW_DEFAULT)));
423
424 g_object_class_install_property (gobject_class, PROP_RC_MAX_QUANTIZER,
425 g_param_spec_int ("max-quantizer", "Maximum Quantizer",
426 "Maximum Quantizer (worst)",
427 0, 63, DEFAULT_RC_MAX_QUANTIZER,
428 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
429 GST_PARAM_DOC_SHOW_DEFAULT)));
430
431 g_object_class_install_property (gobject_class, PROP_RC_DROPFRAME_THRESH,
432 g_param_spec_int ("dropframe-threshold", "Drop Frame Threshold",
433 "Temporal resampling threshold (buf %)",
434 0, 100, DEFAULT_RC_DROPFRAME_THRESH,
435 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
436 GST_PARAM_DOC_SHOW_DEFAULT)));
437
438 g_object_class_install_property (gobject_class, PROP_RC_RESIZE_ALLOWED,
439 g_param_spec_boolean ("resize-allowed", "Resize Allowed",
440 "Allow spatial resampling",
441 DEFAULT_RC_RESIZE_ALLOWED,
442 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
443 GST_PARAM_DOC_SHOW_DEFAULT)));
444
445 g_object_class_install_property (gobject_class, PROP_RC_RESIZE_UP_THRESH,
446 g_param_spec_int ("resize-up-threshold", "Resize Up Threshold",
447 "Upscale threshold (buf %)",
448 0, 100, DEFAULT_RC_RESIZE_UP_THRESH,
449 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
450 GST_PARAM_DOC_SHOW_DEFAULT)));
451
452 g_object_class_install_property (gobject_class, PROP_RC_RESIZE_DOWN_THRESH,
453 g_param_spec_int ("resize-down-threshold", "Resize Down Threshold",
454 "Downscale threshold (buf %)",
455 0, 100, DEFAULT_RC_RESIZE_DOWN_THRESH,
456 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
457 GST_PARAM_DOC_SHOW_DEFAULT)));
458
459 g_object_class_install_property (gobject_class, PROP_RC_UNDERSHOOT_PCT,
460 g_param_spec_int ("undershoot", "Undershoot PCT",
461 "Datarate undershoot (min) target (%)",
462 0, 1000, DEFAULT_RC_UNDERSHOOT_PCT,
463 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
464 GST_PARAM_DOC_SHOW_DEFAULT)));
465
466 g_object_class_install_property (gobject_class, PROP_RC_OVERSHOOT_PCT,
467 g_param_spec_int ("overshoot", "Overshoot PCT",
468 "Datarate overshoot (max) target (%)",
469 0, 1000, DEFAULT_RC_OVERSHOOT_PCT,
470 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
471 GST_PARAM_DOC_SHOW_DEFAULT)));
472
473 g_object_class_install_property (gobject_class, PROP_RC_BUF_SZ,
474 g_param_spec_int ("buffer-size", "Buffer size",
475 "Client buffer size (ms)",
476 0, G_MAXINT, DEFAULT_RC_BUF_SZ,
477 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
478 GST_PARAM_DOC_SHOW_DEFAULT)));
479
480 g_object_class_install_property (gobject_class, PROP_RC_BUF_INITIAL_SZ,
481 g_param_spec_int ("buffer-initial-size", "Buffer initial size",
482 "Initial client buffer size (ms)",
483 0, G_MAXINT, DEFAULT_RC_BUF_INITIAL_SZ,
484 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
485 GST_PARAM_DOC_SHOW_DEFAULT)));
486
487 g_object_class_install_property (gobject_class, PROP_RC_BUF_OPTIMAL_SZ,
488 g_param_spec_int ("buffer-optimal-size", "Buffer optimal size",
489 "Optimal client buffer size (ms)",
490 0, G_MAXINT, DEFAULT_RC_BUF_OPTIMAL_SZ,
491 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
492 GST_PARAM_DOC_SHOW_DEFAULT)));
493
494 g_object_class_install_property (gobject_class, PROP_RC_2PASS_VBR_BIAS_PCT,
495 g_param_spec_int ("twopass-vbr-bias", "2-pass VBR bias",
496 "CBR/VBR bias (0=CBR, 100=VBR)",
497 0, 100, DEFAULT_RC_2PASS_VBR_BIAS_PCT,
498 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
499 GST_PARAM_DOC_SHOW_DEFAULT)));
500
501 g_object_class_install_property (gobject_class,
502 PROP_RC_2PASS_VBR_MINSECTION_PCT,
503 g_param_spec_int ("twopass-vbr-minsection", "2-pass GOP min bitrate",
504 "GOP minimum bitrate (% target)", 0, G_MAXINT,
505 DEFAULT_RC_2PASS_VBR_MINSECTION_PCT,
506 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
507 GST_PARAM_DOC_SHOW_DEFAULT)));
508
509 g_object_class_install_property (gobject_class,
510 PROP_RC_2PASS_VBR_MAXSECTION_PCT,
511 g_param_spec_int ("twopass-vbr-maxsection", "2-pass GOP max bitrate",
512 "GOP maximum bitrate (% target)", 0, G_MAXINT,
513 DEFAULT_RC_2PASS_VBR_MINSECTION_PCT,
514 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
515 GST_PARAM_DOC_SHOW_DEFAULT)));
516
517 g_object_class_install_property (gobject_class, PROP_KF_MODE,
518 g_param_spec_enum ("keyframe-mode", "Keyframe Mode",
519 "Keyframe placement",
520 GST_VPX_ENC_KF_MODE_TYPE, DEFAULT_KF_MODE,
521 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
522 GST_PARAM_DOC_SHOW_DEFAULT)));
523
524 g_object_class_install_property (gobject_class, PROP_KF_MAX_DIST,
525 g_param_spec_int ("keyframe-max-dist", "Keyframe max distance",
526 "Maximum distance between keyframes (number of frames)",
527 0, G_MAXINT, DEFAULT_KF_MAX_DIST,
528 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
529 GST_PARAM_DOC_SHOW_DEFAULT)));
530
531 g_object_class_install_property (gobject_class, PROP_MULTIPASS_MODE,
532 g_param_spec_enum ("multipass-mode", "Multipass Mode",
533 "Multipass encode mode",
534 GST_VPX_ENC_MULTIPASS_MODE_TYPE, DEFAULT_MULTIPASS_MODE,
535 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
536 GST_PARAM_DOC_SHOW_DEFAULT)));
537
538 g_object_class_install_property (gobject_class, PROP_MULTIPASS_CACHE_FILE,
539 g_param_spec_string ("multipass-cache-file", "Multipass Cache File",
540 "Multipass cache file. "
541 "If stream caps reinited, multiple files will be created: "
542 "file, file.1, file.2, ... and so on.",
543 DEFAULT_MULTIPASS_CACHE_FILE,
544 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
545
546 g_object_class_install_property (gobject_class, PROP_TS_NUMBER_LAYERS,
547 g_param_spec_int ("temporal-scalability-number-layers",
548 "Number of coding layers", "Number of coding layers to use", 1, 5,
549 DEFAULT_TS_NUMBER_LAYERS,
550 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
551 GST_PARAM_DOC_SHOW_DEFAULT)));
552
553 g_object_class_install_property (gobject_class, PROP_TS_TARGET_BITRATE,
554 g_param_spec_value_array ("temporal-scalability-target-bitrate",
555 "Coding layer target bitrates",
556 "Target bitrates (bits/sec) for coding layers (one per layer)",
557 g_param_spec_int ("target-bitrate", "Target bitrate",
558 "Target bitrate", 0, G_MAXINT, DEFAULT_RC_TARGET_BITRATE,
559 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
560 GST_PARAM_DOC_SHOW_DEFAULT),
561 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
562 GST_PARAM_DOC_SHOW_DEFAULT));
563
564 g_object_class_install_property (gobject_class, PROP_TS_RATE_DECIMATOR,
565 g_param_spec_value_array ("temporal-scalability-rate-decimator",
566 "Coding layer rate decimator",
567 "Rate decimation factors for each layer",
568 g_param_spec_int ("rate-decimator", "Rate decimator",
569 "Rate decimator", 0, 1000000000, 0,
570 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
571 GST_PARAM_DOC_SHOW_DEFAULT),
572 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
573 GST_PARAM_DOC_SHOW_DEFAULT));
574
575 g_object_class_install_property (gobject_class, PROP_TS_PERIODICITY,
576 g_param_spec_int ("temporal-scalability-periodicity",
577 "Coding layer periodicity",
578 "Length of sequence that defines layer membership periodicity", 0, 16,
579 DEFAULT_TS_PERIODICITY,
580 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
581 GST_PARAM_DOC_SHOW_DEFAULT)));
582
583 g_object_class_install_property (gobject_class, PROP_TS_LAYER_ID,
584 g_param_spec_value_array ("temporal-scalability-layer-id",
585 "Coding layer identification",
586 "Sequence defining coding layer membership",
587 g_param_spec_int ("layer-id", "Layer ID", "Layer ID", 0, 4, 0,
588 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
589 GST_PARAM_DOC_SHOW_DEFAULT),
590 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
591 GST_PARAM_DOC_SHOW_DEFAULT));
592
593 /**
594 * GstVPXEnc:temporal-scalability-layer-flags:
595 *
596 * Sequence defining coding layer flags
597 *
598 * Since: 1.20
599 */
600 g_object_class_install_property (gobject_class, PROP_TS_LAYER_FLAGS,
601 gst_param_spec_array ("temporal-scalability-layer-flags",
602 "Coding layer flags", "Sequence defining coding layer flags",
603 g_param_spec_flags ("flags", "Flags", "Flags",
604 GST_VPX_ENC_TS_LAYER_FLAGS_TYPE, 0,
605 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
606 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
607
608 /**
609 * GstVPXEnc:temporal-scalability-layer-sync-flags:
610 *
611 * Sequence defining coding layer sync flags
612 *
613 * Since: 1.20
614 */
615 g_object_class_install_property (gobject_class, PROP_TS_LAYER_SYNC_FLAGS,
616 gst_param_spec_array ("temporal-scalability-layer-sync-flags",
617 "Coding layer sync flags",
618 "Sequence defining coding layer sync flags",
619 g_param_spec_boolean ("flags", "Flags", "Flags", FALSE,
620 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
621 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
622
623 g_object_class_install_property (gobject_class, PROP_LAG_IN_FRAMES,
624 g_param_spec_int ("lag-in-frames", "Lag in frames",
625 "Maximum number of frames to lag",
626 0, 25, DEFAULT_LAG_IN_FRAMES,
627 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
628 GST_PARAM_DOC_SHOW_DEFAULT)));
629
630 g_object_class_install_property (gobject_class, PROP_ERROR_RESILIENT,
631 g_param_spec_flags ("error-resilient", "Error resilient",
632 "Error resilience flags",
633 GST_VPX_ENC_ER_FLAGS_TYPE, DEFAULT_ERROR_RESILIENT,
634 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
635 GST_PARAM_DOC_SHOW_DEFAULT)));
636
637 g_object_class_install_property (gobject_class, PROP_THREADS,
638 g_param_spec_int ("threads", "Threads",
639 "Number of threads to use",
640 0, 64, DEFAULT_THREADS,
641 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
642 GST_PARAM_DOC_SHOW_DEFAULT)));
643
644 g_object_class_install_property (gobject_class, PROP_DEADLINE,
645 g_param_spec_int64 ("deadline", "Deadline",
646 "Deadline per frame (usec, 0=best, 1=realtime)",
647 0, G_MAXINT64, DEFAULT_DEADLINE,
648 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
649 GST_PARAM_DOC_SHOW_DEFAULT)));
650
651 g_object_class_install_property (gobject_class, PROP_H_SCALING_MODE,
652 g_param_spec_enum ("horizontal-scaling-mode", "Horizontal scaling mode",
653 "Horizontal scaling mode",
654 GST_VPX_ENC_SCALING_MODE_TYPE, DEFAULT_H_SCALING_MODE,
655 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
656 GST_PARAM_DOC_SHOW_DEFAULT)));
657
658 g_object_class_install_property (gobject_class, PROP_V_SCALING_MODE,
659 g_param_spec_enum ("vertical-scaling-mode", "Vertical scaling mode",
660 "Vertical scaling mode",
661 GST_VPX_ENC_SCALING_MODE_TYPE, DEFAULT_V_SCALING_MODE,
662 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
663 GST_PARAM_DOC_SHOW_DEFAULT)));
664
665 g_object_class_install_property (gobject_class, PROP_CPU_USED,
666 g_param_spec_int ("cpu-used", "CPU used",
667 "CPU used",
668 -16, 16, DEFAULT_CPU_USED,
669 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
670 GST_PARAM_DOC_SHOW_DEFAULT)));
671
672 g_object_class_install_property (gobject_class, PROP_ENABLE_AUTO_ALT_REF,
673 g_param_spec_boolean ("auto-alt-ref", "Auto alt reference frames",
674 "Automatically generate AltRef frames",
675 DEFAULT_ENABLE_AUTO_ALT_REF,
676 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
677 GST_PARAM_DOC_SHOW_DEFAULT)));
678
679 g_object_class_install_property (gobject_class, PROP_NOISE_SENSITIVITY,
680 g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
681 "Noise sensisivity (frames to blur)",
682 0, 6, DEFAULT_NOISE_SENSITIVITY,
683 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
684 GST_PARAM_DOC_SHOW_DEFAULT)));
685
686 g_object_class_install_property (gobject_class, PROP_SHARPNESS,
687 g_param_spec_int ("sharpness", "Sharpness",
688 "Filter sharpness",
689 0, 7, DEFAULT_SHARPNESS,
690 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
691 GST_PARAM_DOC_SHOW_DEFAULT)));
692
693 g_object_class_install_property (gobject_class, PROP_STATIC_THRESHOLD,
694 g_param_spec_int ("static-threshold", "Static Threshold",
695 "Motion detection threshold. Recommendation is to set 100 for "
696 "screen/window sharing", 0, G_MAXINT, DEFAULT_STATIC_THRESHOLD,
697 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
698 GST_PARAM_DOC_SHOW_DEFAULT)));
699
700 g_object_class_install_property (gobject_class, PROP_TOKEN_PARTITIONS,
701 g_param_spec_enum ("token-partitions", "Token partitions",
702 "Number of token partitions",
703 GST_VPX_ENC_TOKEN_PARTITIONS_TYPE, DEFAULT_TOKEN_PARTITIONS,
704 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
705 GST_PARAM_DOC_SHOW_DEFAULT)));
706
707 g_object_class_install_property (gobject_class, PROP_ARNR_MAXFRAMES,
708 g_param_spec_int ("arnr-maxframes", "AltRef max frames",
709 "AltRef maximum number of frames",
710 0, 15, DEFAULT_ARNR_MAXFRAMES,
711 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
712 GST_PARAM_DOC_SHOW_DEFAULT)));
713
714 g_object_class_install_property (gobject_class, PROP_ARNR_STRENGTH,
715 g_param_spec_int ("arnr-strength", "AltRef strength",
716 "AltRef strength",
717 0, 6, DEFAULT_ARNR_STRENGTH,
718 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
719 GST_PARAM_DOC_SHOW_DEFAULT)));
720
721 g_object_class_install_property (gobject_class, PROP_ARNR_TYPE,
722 g_param_spec_int ("arnr-type", "AltRef type",
723 "AltRef type",
724 1, 3, DEFAULT_ARNR_TYPE,
725 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
726 G_PARAM_DEPRECATED | GST_PARAM_DOC_SHOW_DEFAULT)));
727
728 g_object_class_install_property (gobject_class, PROP_TUNING,
729 g_param_spec_enum ("tuning", "Tuning",
730 "Tuning",
731 GST_VPX_ENC_TUNING_TYPE, DEFAULT_TUNING,
732 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
733 GST_PARAM_DOC_SHOW_DEFAULT)));
734
735 g_object_class_install_property (gobject_class, PROP_CQ_LEVEL,
736 g_param_spec_int ("cq-level", "Constrained quality level",
737 "Constrained quality level",
738 0, 63, DEFAULT_CQ_LEVEL,
739 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
740 GST_PARAM_DOC_SHOW_DEFAULT)));
741
742 g_object_class_install_property (gobject_class, PROP_MAX_INTRA_BITRATE_PCT,
743 g_param_spec_int ("max-intra-bitrate", "Max Intra bitrate",
744 "Maximum Intra frame bitrate",
745 0, G_MAXINT, DEFAULT_MAX_INTRA_BITRATE_PCT,
746 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
747 GST_PARAM_DOC_SHOW_DEFAULT)));
748
749 g_object_class_install_property (gobject_class, PROP_TIMEBASE,
750 gst_param_spec_fraction ("timebase", "Shortest interframe time",
751 "Fraction of one second that is the shortest interframe time - normally left as zero which will default to the framerate",
752 0, 1, G_MAXINT, 1, DEFAULT_TIMEBASE_N, DEFAULT_TIMEBASE_D,
753 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
754 GST_PARAM_DOC_SHOW_DEFAULT));
755
756 g_object_class_install_property (gobject_class, PROP_BITS_PER_PIXEL,
757 g_param_spec_float ("bits-per-pixel", "Bits per pixel",
758 "Factor to convert number of pixels to bitrate value "
759 "(only has an effect if target-bitrate=0)",
760 0.0, G_MAXFLOAT, DEFAULT_BITS_PER_PIXEL,
761 (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
762 GST_PARAM_DOC_SHOW_DEFAULT)));
763
764 GST_DEBUG_CATEGORY_INIT (gst_vpxenc_debug, "vpxenc", 0, "VPX Encoder");
765
766 gst_type_mark_as_plugin_api (GST_VPX_ENC_END_USAGE_TYPE, 0);
767 gst_type_mark_as_plugin_api (GST_VPX_ENC_MULTIPASS_MODE_TYPE, 0);
768 gst_type_mark_as_plugin_api (GST_VPX_ENC_KF_MODE_TYPE, 0);
769 gst_type_mark_as_plugin_api (GST_VPX_ENC_TUNING_TYPE, 0);
770 gst_type_mark_as_plugin_api (GST_VPX_ENC_SCALING_MODE_TYPE, 0);
771 gst_type_mark_as_plugin_api (GST_VPX_ENC_TOKEN_PARTITIONS_TYPE, 0);
772 gst_type_mark_as_plugin_api (GST_VPX_ENC_ER_FLAGS_TYPE, 0);
773 gst_type_mark_as_plugin_api (GST_TYPE_VPX_ENC, 0);
774 }
775
776 static void
gst_vpx_enc_init(GstVPXEnc * gst_vpx_enc)777 gst_vpx_enc_init (GstVPXEnc * gst_vpx_enc)
778 {
779 GST_DEBUG_OBJECT (gst_vpx_enc, "init");
780 GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (gst_vpx_enc));
781
782 gst_vpx_enc->cfg.rc_end_usage = DEFAULT_RC_END_USAGE;
783 gst_vpx_enc->cfg.rc_target_bitrate = DEFAULT_RC_TARGET_BITRATE / 1000;
784 gst_vpx_enc->rc_target_bitrate_auto = DEFAULT_RC_TARGET_BITRATE == 0;
785 gst_vpx_enc->cfg.rc_min_quantizer = DEFAULT_RC_MIN_QUANTIZER;
786 gst_vpx_enc->cfg.rc_max_quantizer = DEFAULT_RC_MAX_QUANTIZER;
787 gst_vpx_enc->cfg.rc_dropframe_thresh = DEFAULT_RC_DROPFRAME_THRESH;
788 gst_vpx_enc->cfg.rc_resize_allowed = DEFAULT_RC_RESIZE_ALLOWED;
789 gst_vpx_enc->cfg.rc_resize_up_thresh = DEFAULT_RC_RESIZE_UP_THRESH;
790 gst_vpx_enc->cfg.rc_resize_down_thresh = DEFAULT_RC_RESIZE_DOWN_THRESH;
791 gst_vpx_enc->cfg.rc_undershoot_pct = DEFAULT_RC_UNDERSHOOT_PCT;
792 gst_vpx_enc->cfg.rc_overshoot_pct = DEFAULT_RC_OVERSHOOT_PCT;
793 gst_vpx_enc->cfg.rc_buf_sz = DEFAULT_RC_BUF_SZ;
794 gst_vpx_enc->cfg.rc_buf_initial_sz = DEFAULT_RC_BUF_INITIAL_SZ;
795 gst_vpx_enc->cfg.rc_buf_optimal_sz = DEFAULT_RC_BUF_OPTIMAL_SZ;
796 gst_vpx_enc->cfg.rc_2pass_vbr_bias_pct = DEFAULT_RC_2PASS_VBR_BIAS_PCT;
797 gst_vpx_enc->cfg.rc_2pass_vbr_minsection_pct =
798 DEFAULT_RC_2PASS_VBR_MINSECTION_PCT;
799 gst_vpx_enc->cfg.rc_2pass_vbr_maxsection_pct =
800 DEFAULT_RC_2PASS_VBR_MAXSECTION_PCT;
801 gst_vpx_enc->cfg.kf_mode = DEFAULT_KF_MODE;
802 gst_vpx_enc->cfg.kf_max_dist = DEFAULT_KF_MAX_DIST;
803 gst_vpx_enc->cfg.g_pass = DEFAULT_MULTIPASS_MODE;
804 gst_vpx_enc->multipass_cache_prefix = g_strdup (DEFAULT_MULTIPASS_CACHE_FILE);
805 gst_vpx_enc->multipass_cache_file = NULL;
806 gst_vpx_enc->multipass_cache_idx = 0;
807 gst_vpx_enc->cfg.ts_number_layers = DEFAULT_TS_NUMBER_LAYERS;
808 gst_vpx_enc->n_ts_target_bitrate = 0;
809 gst_vpx_enc->n_ts_rate_decimator = 0;
810 gst_vpx_enc->cfg.ts_periodicity = DEFAULT_TS_PERIODICITY;
811 gst_vpx_enc->n_ts_layer_id = 0;
812 gst_vpx_enc->n_ts_layer_flags = 0;
813 gst_vpx_enc->ts_layer_flags = NULL;
814 gst_vpx_enc->n_ts_layer_sync_flags = 0;
815 gst_vpx_enc->ts_layer_sync_flags = NULL;
816 gst_vpx_enc->cfg.g_error_resilient = DEFAULT_ERROR_RESILIENT;
817 gst_vpx_enc->cfg.g_lag_in_frames = DEFAULT_LAG_IN_FRAMES;
818 gst_vpx_enc->cfg.g_threads = DEFAULT_THREADS;
819 gst_vpx_enc->deadline = DEFAULT_DEADLINE;
820 gst_vpx_enc->h_scaling_mode = DEFAULT_H_SCALING_MODE;
821 gst_vpx_enc->v_scaling_mode = DEFAULT_V_SCALING_MODE;
822 gst_vpx_enc->cpu_used = DEFAULT_CPU_USED;
823 gst_vpx_enc->enable_auto_alt_ref = DEFAULT_ENABLE_AUTO_ALT_REF;
824 gst_vpx_enc->noise_sensitivity = DEFAULT_NOISE_SENSITIVITY;
825 gst_vpx_enc->sharpness = DEFAULT_SHARPNESS;
826 gst_vpx_enc->static_threshold = DEFAULT_STATIC_THRESHOLD;
827 gst_vpx_enc->token_partitions = DEFAULT_TOKEN_PARTITIONS;
828 gst_vpx_enc->arnr_maxframes = DEFAULT_ARNR_MAXFRAMES;
829 gst_vpx_enc->arnr_strength = DEFAULT_ARNR_STRENGTH;
830 gst_vpx_enc->arnr_type = DEFAULT_ARNR_TYPE;
831 gst_vpx_enc->tuning = DEFAULT_TUNING;
832 gst_vpx_enc->cq_level = DEFAULT_CQ_LEVEL;
833 gst_vpx_enc->max_intra_bitrate_pct = DEFAULT_MAX_INTRA_BITRATE_PCT;
834 gst_vpx_enc->timebase_n = DEFAULT_TIMEBASE_N;
835 gst_vpx_enc->timebase_d = DEFAULT_TIMEBASE_D;
836 gst_vpx_enc->bits_per_pixel = DEFAULT_BITS_PER_PIXEL;
837 gst_vpx_enc->tl0picidx = 0;
838 gst_vpx_enc->prev_was_keyframe = FALSE;
839
840 gst_vpx_enc->cfg.g_profile = DEFAULT_PROFILE;
841
842 g_mutex_init (&gst_vpx_enc->encoder_lock);
843 }
844
845 static void
gst_vpx_enc_finalize(GObject * object)846 gst_vpx_enc_finalize (GObject * object)
847 {
848 GstVPXEnc *gst_vpx_enc;
849
850 GST_DEBUG_OBJECT (object, "finalize");
851
852 g_return_if_fail (GST_IS_VPX_ENC (object));
853 gst_vpx_enc = GST_VPX_ENC (object);
854
855 g_free (gst_vpx_enc->ts_layer_flags);
856 g_free (gst_vpx_enc->ts_layer_sync_flags);
857
858 g_free (gst_vpx_enc->multipass_cache_prefix);
859 g_free (gst_vpx_enc->multipass_cache_file);
860 gst_vpx_enc->multipass_cache_idx = 0;
861
862
863 if (gst_vpx_enc->input_state)
864 gst_video_codec_state_unref (gst_vpx_enc->input_state);
865
866 g_mutex_clear (&gst_vpx_enc->encoder_lock);
867
868 G_OBJECT_CLASS (parent_class)->finalize (object);
869 }
870
871 static void
gst_vpx_enc_set_auto_bitrate(GstVPXEnc * encoder)872 gst_vpx_enc_set_auto_bitrate (GstVPXEnc * encoder)
873 {
874 if (encoder->input_state != NULL) {
875 guint size;
876 guint pixels_per_sec;
877 guint target_bitrate;
878 guint fps_n, fps_d;
879
880 if (GST_VIDEO_INFO_FPS_N (&encoder->input_state->info) != 0) {
881 fps_n = GST_VIDEO_INFO_FPS_N (&encoder->input_state->info);
882 fps_d = GST_VIDEO_INFO_FPS_D (&encoder->input_state->info);
883 } else {
884 /* otherwise assume 30 frames per second as a fallback */
885 fps_n = 30;
886 fps_d = 1;
887 }
888
889 size =
890 GST_VIDEO_INFO_WIDTH (&encoder->input_state->info) *
891 GST_VIDEO_INFO_HEIGHT (&encoder->input_state->info);
892 pixels_per_sec = size * fps_n / fps_d;
893 target_bitrate = pixels_per_sec * encoder->bits_per_pixel;
894
895 GST_DEBUG_OBJECT (encoder,
896 "Setting autobitrate for %ux%ux @ %u/%ufps %.4f = %ubps",
897 GST_VIDEO_INFO_WIDTH (&encoder->input_state->info),
898 GST_VIDEO_INFO_HEIGHT (&encoder->input_state->info),
899 GST_VIDEO_INFO_FPS_N (&encoder->input_state->info),
900 GST_VIDEO_INFO_FPS_D (&encoder->input_state->info),
901 encoder->bits_per_pixel, target_bitrate);
902
903 encoder->cfg.rc_target_bitrate = target_bitrate / 1000;
904 }
905 }
906
907 static void
gst_vpx_enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)908 gst_vpx_enc_set_property (GObject * object, guint prop_id,
909 const GValue * value, GParamSpec * pspec)
910 {
911 GstVPXEnc *gst_vpx_enc;
912 gboolean global = FALSE;
913 vpx_codec_err_t status;
914
915 g_return_if_fail (GST_IS_VPX_ENC (object));
916 gst_vpx_enc = GST_VPX_ENC (object);
917
918 GST_DEBUG_OBJECT (object, "gst_vpx_enc_set_property");
919 g_mutex_lock (&gst_vpx_enc->encoder_lock);
920 switch (prop_id) {
921 case PROP_RC_END_USAGE:
922 gst_vpx_enc->cfg.rc_end_usage = g_value_get_enum (value);
923 global = TRUE;
924 break;
925 case PROP_RC_TARGET_BITRATE:
926 if (g_value_get_int (value) == 0) {
927 gst_vpx_enc_set_auto_bitrate (gst_vpx_enc);
928 gst_vpx_enc->rc_target_bitrate_auto = TRUE;
929 } else {
930 gst_vpx_enc->cfg.rc_target_bitrate = g_value_get_int (value) / 1000;
931 gst_vpx_enc->rc_target_bitrate_auto = FALSE;
932 }
933 global = TRUE;
934 break;
935 case PROP_RC_MIN_QUANTIZER:
936 gst_vpx_enc->cfg.rc_min_quantizer = g_value_get_int (value);
937 global = TRUE;
938 break;
939 case PROP_RC_MAX_QUANTIZER:
940 gst_vpx_enc->cfg.rc_max_quantizer = g_value_get_int (value);
941 global = TRUE;
942 break;
943 case PROP_RC_DROPFRAME_THRESH:
944 gst_vpx_enc->cfg.rc_dropframe_thresh = g_value_get_int (value);
945 global = TRUE;
946 break;
947 case PROP_RC_RESIZE_ALLOWED:
948 gst_vpx_enc->cfg.rc_resize_allowed = g_value_get_boolean (value);
949 global = TRUE;
950 break;
951 case PROP_RC_RESIZE_UP_THRESH:
952 gst_vpx_enc->cfg.rc_resize_up_thresh = g_value_get_int (value);
953 global = TRUE;
954 break;
955 case PROP_RC_RESIZE_DOWN_THRESH:
956 gst_vpx_enc->cfg.rc_resize_down_thresh = g_value_get_int (value);
957 global = TRUE;
958 break;
959 case PROP_RC_UNDERSHOOT_PCT:
960 gst_vpx_enc->cfg.rc_undershoot_pct = g_value_get_int (value);
961 global = TRUE;
962 break;
963 case PROP_RC_OVERSHOOT_PCT:
964 gst_vpx_enc->cfg.rc_overshoot_pct = g_value_get_int (value);
965 global = TRUE;
966 break;
967 case PROP_RC_BUF_SZ:
968 gst_vpx_enc->cfg.rc_buf_sz = g_value_get_int (value);
969 global = TRUE;
970 break;
971 case PROP_RC_BUF_INITIAL_SZ:
972 gst_vpx_enc->cfg.rc_buf_initial_sz = g_value_get_int (value);
973 global = TRUE;
974 break;
975 case PROP_RC_BUF_OPTIMAL_SZ:
976 gst_vpx_enc->cfg.rc_buf_optimal_sz = g_value_get_int (value);
977 global = TRUE;
978 break;
979 case PROP_RC_2PASS_VBR_BIAS_PCT:
980 gst_vpx_enc->cfg.rc_2pass_vbr_bias_pct = g_value_get_int (value);
981 global = TRUE;
982 break;
983 case PROP_RC_2PASS_VBR_MINSECTION_PCT:
984 gst_vpx_enc->cfg.rc_2pass_vbr_minsection_pct = g_value_get_int (value);
985 global = TRUE;
986 break;
987 case PROP_RC_2PASS_VBR_MAXSECTION_PCT:
988 gst_vpx_enc->cfg.rc_2pass_vbr_maxsection_pct = g_value_get_int (value);
989 global = TRUE;
990 break;
991 case PROP_KF_MODE:
992 gst_vpx_enc->cfg.kf_mode = g_value_get_enum (value);
993 global = TRUE;
994 break;
995 case PROP_KF_MAX_DIST:
996 gst_vpx_enc->cfg.kf_max_dist = g_value_get_int (value);
997 global = TRUE;
998 break;
999 case PROP_MULTIPASS_MODE:
1000 gst_vpx_enc->cfg.g_pass = g_value_get_enum (value);
1001 global = TRUE;
1002 break;
1003 case PROP_MULTIPASS_CACHE_FILE:
1004 if (gst_vpx_enc->multipass_cache_prefix)
1005 g_free (gst_vpx_enc->multipass_cache_prefix);
1006 gst_vpx_enc->multipass_cache_prefix = g_value_dup_string (value);
1007 break;
1008 case PROP_TS_NUMBER_LAYERS:
1009 gst_vpx_enc->cfg.ts_number_layers = g_value_get_int (value);
1010 global = TRUE;
1011 break;
1012 case PROP_TS_TARGET_BITRATE:{
1013 GValueArray *va = g_value_get_boxed (value);
1014
1015 memset (&gst_vpx_enc->cfg.ts_target_bitrate, 0,
1016 sizeof (gst_vpx_enc->cfg.ts_target_bitrate));
1017 if (va == NULL) {
1018 gst_vpx_enc->n_ts_target_bitrate = 0;
1019 } else if (va->n_values > VPX_TS_MAX_LAYERS) {
1020 g_warning ("%s: Only %d layers allowed at maximum",
1021 GST_ELEMENT_NAME (gst_vpx_enc), VPX_TS_MAX_LAYERS);
1022 } else {
1023 gint i;
1024
1025 for (i = 0; i < va->n_values; i++)
1026 gst_vpx_enc->cfg.ts_target_bitrate[i] =
1027 g_value_get_int (g_value_array_get_nth (va, i)) / 1000;
1028 gst_vpx_enc->n_ts_target_bitrate = va->n_values;
1029 }
1030 global = TRUE;
1031 break;
1032 }
1033 case PROP_TS_RATE_DECIMATOR:{
1034 GValueArray *va = g_value_get_boxed (value);
1035
1036 memset (&gst_vpx_enc->cfg.ts_rate_decimator, 0,
1037 sizeof (gst_vpx_enc->cfg.ts_rate_decimator));
1038 if (va == NULL) {
1039 gst_vpx_enc->n_ts_rate_decimator = 0;
1040 } else if (va->n_values > VPX_TS_MAX_LAYERS) {
1041 g_warning ("%s: Only %d layers allowed at maximum",
1042 GST_ELEMENT_NAME (gst_vpx_enc), VPX_TS_MAX_LAYERS);
1043 } else {
1044 gint i;
1045
1046 for (i = 0; i < va->n_values; i++)
1047 gst_vpx_enc->cfg.ts_rate_decimator[i] =
1048 g_value_get_int (g_value_array_get_nth (va, i));
1049 gst_vpx_enc->n_ts_rate_decimator = va->n_values;
1050 }
1051 global = TRUE;
1052 break;
1053 }
1054 case PROP_TS_PERIODICITY:
1055 gst_vpx_enc->cfg.ts_periodicity = g_value_get_int (value);
1056 global = TRUE;
1057 break;
1058 case PROP_TS_LAYER_ID:{
1059 GValueArray *va = g_value_get_boxed (value);
1060
1061 memset (&gst_vpx_enc->cfg.ts_layer_id, 0,
1062 sizeof (gst_vpx_enc->cfg.ts_layer_id));
1063 if (va && va->n_values > VPX_TS_MAX_PERIODICITY) {
1064 g_warning ("%s: Only %d sized layer sequences allowed at maximum",
1065 GST_ELEMENT_NAME (gst_vpx_enc), VPX_TS_MAX_PERIODICITY);
1066 } else if (va) {
1067 gint i;
1068
1069 for (i = 0; i < va->n_values; i++)
1070 gst_vpx_enc->cfg.ts_layer_id[i] =
1071 g_value_get_int (g_value_array_get_nth (va, i));
1072 gst_vpx_enc->n_ts_layer_id = va->n_values;
1073 } else {
1074 gst_vpx_enc->n_ts_layer_id = 0;
1075 }
1076 global = TRUE;
1077 break;
1078 }
1079 case PROP_TS_LAYER_FLAGS:{
1080 gint l = gst_value_array_get_size (value);
1081
1082 g_free (gst_vpx_enc->ts_layer_flags);
1083 gst_vpx_enc->n_ts_layer_flags = 0;
1084
1085 if (l > 0) {
1086 gint i;
1087
1088 gst_vpx_enc->ts_layer_flags = g_new (gint, l);
1089
1090 for (i = 0; i < l; i++)
1091 gst_vpx_enc->ts_layer_flags[i] =
1092 g_value_get_flags (gst_value_array_get_value (value, i));
1093 gst_vpx_enc->n_ts_layer_flags = l;
1094 } else {
1095 gst_vpx_enc->ts_layer_flags = NULL;
1096 }
1097 break;
1098 }
1099 case PROP_TS_LAYER_SYNC_FLAGS:{
1100 gint l = gst_value_array_get_size (value);
1101
1102 g_free (gst_vpx_enc->ts_layer_sync_flags);
1103 gst_vpx_enc->n_ts_layer_sync_flags = 0;
1104
1105 if (l > 0) {
1106 gint i;
1107
1108 gst_vpx_enc->ts_layer_sync_flags = g_new (gboolean, l);
1109 for (i = 0; i < l; i++)
1110 gst_vpx_enc->ts_layer_sync_flags[i] =
1111 g_value_get_boolean (gst_value_array_get_value (value, i));
1112 gst_vpx_enc->n_ts_layer_sync_flags = l;
1113 } else {
1114 gst_vpx_enc->ts_layer_sync_flags = NULL;
1115 }
1116 break;
1117 }
1118 case PROP_ERROR_RESILIENT:
1119 gst_vpx_enc->cfg.g_error_resilient = g_value_get_flags (value);
1120 global = TRUE;
1121 break;
1122 case PROP_LAG_IN_FRAMES:
1123 gst_vpx_enc->cfg.g_lag_in_frames = g_value_get_int (value);
1124 global = TRUE;
1125 break;
1126 case PROP_THREADS:
1127 gst_vpx_enc->cfg.g_threads = g_value_get_int (value);
1128 global = TRUE;
1129 break;
1130 case PROP_DEADLINE:
1131 gst_vpx_enc->deadline = g_value_get_int64 (value);
1132 break;
1133 case PROP_H_SCALING_MODE:
1134 gst_vpx_enc->h_scaling_mode = g_value_get_enum (value);
1135 if (gst_vpx_enc->inited) {
1136 vpx_scaling_mode_t sm;
1137
1138 sm.h_scaling_mode = gst_vpx_enc->h_scaling_mode;
1139 sm.v_scaling_mode = gst_vpx_enc->v_scaling_mode;
1140
1141 status =
1142 vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_SCALEMODE, &sm);
1143 if (status != VPX_CODEC_OK) {
1144 GST_WARNING_OBJECT (gst_vpx_enc,
1145 "Failed to set VP8E_SET_SCALEMODE: %s",
1146 gst_vpx_error_name (status));
1147 }
1148 }
1149 break;
1150 case PROP_V_SCALING_MODE:
1151 gst_vpx_enc->v_scaling_mode = g_value_get_enum (value);
1152 if (gst_vpx_enc->inited) {
1153 vpx_scaling_mode_t sm;
1154
1155 sm.h_scaling_mode = gst_vpx_enc->h_scaling_mode;
1156 sm.v_scaling_mode = gst_vpx_enc->v_scaling_mode;
1157
1158 status =
1159 vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_SCALEMODE, &sm);
1160 if (status != VPX_CODEC_OK) {
1161 GST_WARNING_OBJECT (gst_vpx_enc,
1162 "Failed to set VP8E_SET_SCALEMODE: %s",
1163 gst_vpx_error_name (status));
1164 }
1165 }
1166 break;
1167 case PROP_CPU_USED:
1168 gst_vpx_enc->cpu_used = g_value_get_int (value);
1169 if (gst_vpx_enc->inited) {
1170 status =
1171 vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_CPUUSED,
1172 gst_vpx_enc->cpu_used);
1173 if (status != VPX_CODEC_OK) {
1174 GST_WARNING_OBJECT (gst_vpx_enc, "Failed to set VP8E_SET_CPUUSED: %s",
1175 gst_vpx_error_name (status));
1176 }
1177 }
1178 break;
1179 case PROP_ENABLE_AUTO_ALT_REF:
1180 gst_vpx_enc->enable_auto_alt_ref = g_value_get_boolean (value);
1181 if (gst_vpx_enc->inited) {
1182 status =
1183 vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_ENABLEAUTOALTREF,
1184 (gst_vpx_enc->enable_auto_alt_ref ? 1 : 0));
1185 if (status != VPX_CODEC_OK) {
1186 GST_WARNING_OBJECT (gst_vpx_enc,
1187 "Failed to set VP8E_SET_ENABLEAUTOALTREF: %s",
1188 gst_vpx_error_name (status));
1189 }
1190 }
1191 break;
1192 case PROP_NOISE_SENSITIVITY:
1193 gst_vpx_enc->noise_sensitivity = g_value_get_int (value);
1194 if (gst_vpx_enc->inited) {
1195 status =
1196 vpx_codec_control (&gst_vpx_enc->encoder,
1197 VP8E_SET_NOISE_SENSITIVITY, gst_vpx_enc->noise_sensitivity);
1198 if (status != VPX_CODEC_OK) {
1199 GST_WARNING_OBJECT (gst_vpx_enc,
1200 "Failed to set VP8E_SET_NOISE_SENSITIVITY: %s",
1201 gst_vpx_error_name (status));
1202 }
1203 }
1204 break;
1205 case PROP_SHARPNESS:
1206 gst_vpx_enc->sharpness = g_value_get_int (value);
1207 if (gst_vpx_enc->inited) {
1208 status = vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_SHARPNESS,
1209 gst_vpx_enc->sharpness);
1210 if (status != VPX_CODEC_OK) {
1211 GST_WARNING_OBJECT (gst_vpx_enc,
1212 "Failed to set VP8E_SET_SHARPNESS: %s",
1213 gst_vpx_error_name (status));
1214 }
1215 }
1216 break;
1217 case PROP_STATIC_THRESHOLD:
1218 gst_vpx_enc->static_threshold = g_value_get_int (value);
1219 if (gst_vpx_enc->inited) {
1220 status =
1221 vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_STATIC_THRESHOLD,
1222 gst_vpx_enc->static_threshold);
1223 if (status != VPX_CODEC_OK) {
1224 GST_WARNING_OBJECT (gst_vpx_enc,
1225 "Failed to set VP8E_SET_STATIC_THRESHOLD: %s",
1226 gst_vpx_error_name (status));
1227 }
1228 }
1229 break;
1230 case PROP_TOKEN_PARTITIONS:
1231 gst_vpx_enc->token_partitions = g_value_get_enum (value);
1232 if (gst_vpx_enc->inited) {
1233 status =
1234 vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_TOKEN_PARTITIONS,
1235 gst_vpx_enc->token_partitions);
1236 if (status != VPX_CODEC_OK) {
1237 GST_WARNING_OBJECT (gst_vpx_enc,
1238 "Failed to set VP8E_SET_TOKEN_PARTIONS: %s",
1239 gst_vpx_error_name (status));
1240 }
1241 }
1242 break;
1243 case PROP_ARNR_MAXFRAMES:
1244 gst_vpx_enc->arnr_maxframes = g_value_get_int (value);
1245 if (gst_vpx_enc->inited) {
1246 status =
1247 vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_ARNR_MAXFRAMES,
1248 gst_vpx_enc->arnr_maxframes);
1249 if (status != VPX_CODEC_OK) {
1250 GST_WARNING_OBJECT (gst_vpx_enc,
1251 "Failed to set VP8E_SET_ARNR_MAXFRAMES: %s",
1252 gst_vpx_error_name (status));
1253 }
1254 }
1255 break;
1256 case PROP_ARNR_STRENGTH:
1257 gst_vpx_enc->arnr_strength = g_value_get_int (value);
1258 if (gst_vpx_enc->inited) {
1259 status =
1260 vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_ARNR_STRENGTH,
1261 gst_vpx_enc->arnr_strength);
1262 if (status != VPX_CODEC_OK) {
1263 GST_WARNING_OBJECT (gst_vpx_enc,
1264 "Failed to set VP8E_SET_ARNR_STRENGTH: %s",
1265 gst_vpx_error_name (status));
1266 }
1267 }
1268 break;
1269 case PROP_ARNR_TYPE:
1270 gst_vpx_enc->arnr_type = g_value_get_int (value);
1271 g_warning ("arnr-type is a no-op since control has been deprecated "
1272 "in libvpx");
1273 break;
1274 case PROP_TUNING:
1275 gst_vpx_enc->tuning = g_value_get_enum (value);
1276 if (gst_vpx_enc->inited) {
1277 status = vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_TUNING,
1278 gst_vpx_enc->tuning);
1279 if (status != VPX_CODEC_OK) {
1280 GST_WARNING_OBJECT (gst_vpx_enc,
1281 "Failed to set VP8E_SET_TUNING: %s", gst_vpx_error_name (status));
1282 }
1283 }
1284 break;
1285 case PROP_CQ_LEVEL:
1286 gst_vpx_enc->cq_level = g_value_get_int (value);
1287 if (gst_vpx_enc->inited) {
1288 status = vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_CQ_LEVEL,
1289 gst_vpx_enc->cq_level);
1290 if (status != VPX_CODEC_OK) {
1291 GST_WARNING_OBJECT (gst_vpx_enc,
1292 "Failed to set VP8E_SET_CQ_LEVEL: %s",
1293 gst_vpx_error_name (status));
1294 }
1295 }
1296 break;
1297 case PROP_MAX_INTRA_BITRATE_PCT:
1298 gst_vpx_enc->max_intra_bitrate_pct = g_value_get_int (value);
1299 if (gst_vpx_enc->inited) {
1300 status =
1301 vpx_codec_control (&gst_vpx_enc->encoder,
1302 VP8E_SET_MAX_INTRA_BITRATE_PCT, gst_vpx_enc->max_intra_bitrate_pct);
1303 if (status != VPX_CODEC_OK) {
1304 GST_WARNING_OBJECT (gst_vpx_enc,
1305 "Failed to set VP8E_SET_MAX_INTRA_BITRATE_PCT: %s",
1306 gst_vpx_error_name (status));
1307 }
1308 }
1309 break;
1310 case PROP_TIMEBASE:
1311 gst_vpx_enc->timebase_n = gst_value_get_fraction_numerator (value);
1312 gst_vpx_enc->timebase_d = gst_value_get_fraction_denominator (value);
1313 break;
1314 case PROP_BITS_PER_PIXEL:
1315 gst_vpx_enc->bits_per_pixel = g_value_get_float (value);
1316 if (gst_vpx_enc->rc_target_bitrate_auto) {
1317 gst_vpx_enc_set_auto_bitrate (gst_vpx_enc);
1318 global = TRUE;
1319 }
1320 break;
1321 default:
1322 break;
1323 }
1324
1325 if (global &&gst_vpx_enc->inited) {
1326 status =
1327 vpx_codec_enc_config_set (&gst_vpx_enc->encoder, &gst_vpx_enc->cfg);
1328 if (status != VPX_CODEC_OK) {
1329 g_mutex_unlock (&gst_vpx_enc->encoder_lock);
1330 GST_ELEMENT_ERROR (gst_vpx_enc, LIBRARY, INIT,
1331 ("Failed to set encoder configuration"), ("%s",
1332 gst_vpx_error_name (status)));
1333 } else {
1334 g_mutex_unlock (&gst_vpx_enc->encoder_lock);
1335 }
1336 } else {
1337 g_mutex_unlock (&gst_vpx_enc->encoder_lock);
1338 }
1339 }
1340
1341 static void
gst_vpx_enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1342 gst_vpx_enc_get_property (GObject * object, guint prop_id, GValue * value,
1343 GParamSpec * pspec)
1344 {
1345 GstVPXEnc *gst_vpx_enc;
1346
1347 g_return_if_fail (GST_IS_VPX_ENC (object));
1348 gst_vpx_enc = GST_VPX_ENC (object);
1349
1350 g_mutex_lock (&gst_vpx_enc->encoder_lock);
1351 switch (prop_id) {
1352 case PROP_RC_END_USAGE:
1353 g_value_set_enum (value, gst_vpx_enc->cfg.rc_end_usage);
1354 break;
1355 case PROP_RC_TARGET_BITRATE:
1356 g_value_set_int (value, gst_vpx_enc->cfg.rc_target_bitrate * 1000);
1357 break;
1358 case PROP_RC_MIN_QUANTIZER:
1359 g_value_set_int (value, gst_vpx_enc->cfg.rc_min_quantizer);
1360 break;
1361 case PROP_RC_MAX_QUANTIZER:
1362 g_value_set_int (value, gst_vpx_enc->cfg.rc_max_quantizer);
1363 break;
1364 case PROP_RC_DROPFRAME_THRESH:
1365 g_value_set_int (value, gst_vpx_enc->cfg.rc_dropframe_thresh);
1366 break;
1367 case PROP_RC_RESIZE_ALLOWED:
1368 g_value_set_boolean (value, gst_vpx_enc->cfg.rc_resize_allowed);
1369 break;
1370 case PROP_RC_RESIZE_UP_THRESH:
1371 g_value_set_int (value, gst_vpx_enc->cfg.rc_resize_up_thresh);
1372 break;
1373 case PROP_RC_RESIZE_DOWN_THRESH:
1374 g_value_set_int (value, gst_vpx_enc->cfg.rc_resize_down_thresh);
1375 break;
1376 case PROP_RC_UNDERSHOOT_PCT:
1377 g_value_set_int (value, gst_vpx_enc->cfg.rc_undershoot_pct);
1378 break;
1379 case PROP_RC_OVERSHOOT_PCT:
1380 g_value_set_int (value, gst_vpx_enc->cfg.rc_overshoot_pct);
1381 break;
1382 case PROP_RC_BUF_SZ:
1383 g_value_set_int (value, gst_vpx_enc->cfg.rc_buf_sz);
1384 break;
1385 case PROP_RC_BUF_INITIAL_SZ:
1386 g_value_set_int (value, gst_vpx_enc->cfg.rc_buf_initial_sz);
1387 break;
1388 case PROP_RC_BUF_OPTIMAL_SZ:
1389 g_value_set_int (value, gst_vpx_enc->cfg.rc_buf_optimal_sz);
1390 break;
1391 case PROP_RC_2PASS_VBR_BIAS_PCT:
1392 g_value_set_int (value, gst_vpx_enc->cfg.rc_2pass_vbr_bias_pct);
1393 break;
1394 case PROP_RC_2PASS_VBR_MINSECTION_PCT:
1395 g_value_set_int (value, gst_vpx_enc->cfg.rc_2pass_vbr_minsection_pct);
1396 break;
1397 case PROP_RC_2PASS_VBR_MAXSECTION_PCT:
1398 g_value_set_int (value, gst_vpx_enc->cfg.rc_2pass_vbr_maxsection_pct);
1399 break;
1400 case PROP_KF_MODE:
1401 g_value_set_enum (value, gst_vpx_enc->cfg.kf_mode);
1402 break;
1403 case PROP_KF_MAX_DIST:
1404 g_value_set_int (value, gst_vpx_enc->cfg.kf_max_dist);
1405 break;
1406 case PROP_MULTIPASS_MODE:
1407 g_value_set_enum (value, gst_vpx_enc->cfg.g_pass);
1408 break;
1409 case PROP_MULTIPASS_CACHE_FILE:
1410 g_value_set_string (value, gst_vpx_enc->multipass_cache_prefix);
1411 break;
1412 case PROP_TS_NUMBER_LAYERS:
1413 g_value_set_int (value, gst_vpx_enc->cfg.ts_number_layers);
1414 break;
1415 case PROP_TS_TARGET_BITRATE:{
1416 GValueArray *va;
1417
1418 if (gst_vpx_enc->n_ts_target_bitrate == 0) {
1419 g_value_set_boxed (value, NULL);
1420 } else {
1421 gint i;
1422
1423 va = g_value_array_new (gst_vpx_enc->n_ts_target_bitrate);
1424 for (i = 0; i < gst_vpx_enc->n_ts_target_bitrate; i++) {
1425 GValue v = { 0, };
1426
1427 g_value_init (&v, G_TYPE_INT);
1428 g_value_set_int (&v, gst_vpx_enc->cfg.ts_target_bitrate[i] * 1000);
1429 g_value_array_append (va, &v);
1430 g_value_unset (&v);
1431 }
1432 g_value_set_boxed (value, va);
1433 g_value_array_free (va);
1434 }
1435 break;
1436 }
1437 case PROP_TS_RATE_DECIMATOR:{
1438 GValueArray *va;
1439
1440 if (gst_vpx_enc->n_ts_rate_decimator == 0) {
1441 g_value_set_boxed (value, NULL);
1442 } else {
1443 gint i;
1444
1445 va = g_value_array_new (gst_vpx_enc->n_ts_rate_decimator);
1446 for (i = 0; i < gst_vpx_enc->n_ts_rate_decimator; i++) {
1447 GValue v = { 0, };
1448
1449 g_value_init (&v, G_TYPE_INT);
1450 g_value_set_int (&v, gst_vpx_enc->cfg.ts_rate_decimator[i]);
1451 g_value_array_append (va, &v);
1452 g_value_unset (&v);
1453 }
1454 g_value_set_boxed (value, va);
1455 g_value_array_free (va);
1456 }
1457 break;
1458 }
1459 case PROP_TS_PERIODICITY:
1460 g_value_set_int (value, gst_vpx_enc->cfg.ts_periodicity);
1461 break;
1462 case PROP_TS_LAYER_ID:{
1463 GValueArray *va;
1464
1465 if (gst_vpx_enc->n_ts_layer_id == 0) {
1466 g_value_set_boxed (value, NULL);
1467 } else {
1468 gint i;
1469
1470 va = g_value_array_new (gst_vpx_enc->n_ts_layer_id);
1471 for (i = 0; i < gst_vpx_enc->n_ts_layer_id; i++) {
1472 GValue v = { 0, };
1473
1474 g_value_init (&v, G_TYPE_INT);
1475 g_value_set_int (&v, gst_vpx_enc->cfg.ts_layer_id[i]);
1476 g_value_array_append (va, &v);
1477 g_value_unset (&v);
1478 }
1479 g_value_set_boxed (value, va);
1480 g_value_array_free (va);
1481 }
1482 break;
1483 }
1484 case PROP_TS_LAYER_FLAGS:{
1485 gint i;
1486
1487 for (i = 0; i < gst_vpx_enc->n_ts_layer_flags; i++) {
1488 GValue v = { 0, };
1489
1490 g_value_init (&v, GST_VPX_ENC_TS_LAYER_FLAGS_TYPE);
1491 g_value_set_flags (&v, gst_vpx_enc->ts_layer_flags[i]);
1492 gst_value_array_append_value (value, &v);
1493 g_value_unset (&v);
1494 }
1495 break;
1496 }
1497 case PROP_TS_LAYER_SYNC_FLAGS:{
1498 gint i;
1499
1500 for (i = 0; i < gst_vpx_enc->n_ts_layer_sync_flags; i++) {
1501 GValue v = { 0, };
1502
1503 g_value_init (&v, G_TYPE_BOOLEAN);
1504 g_value_set_boolean (&v, gst_vpx_enc->ts_layer_sync_flags[i]);
1505 gst_value_array_append_value (value, &v);
1506 g_value_unset (&v);
1507 }
1508 break;
1509 }
1510 case PROP_ERROR_RESILIENT:
1511 g_value_set_flags (value, gst_vpx_enc->cfg.g_error_resilient);
1512 break;
1513 case PROP_LAG_IN_FRAMES:
1514 g_value_set_int (value, gst_vpx_enc->cfg.g_lag_in_frames);
1515 break;
1516 case PROP_THREADS:
1517 g_value_set_int (value, gst_vpx_enc->cfg.g_threads);
1518 break;
1519 case PROP_DEADLINE:
1520 g_value_set_int64 (value, gst_vpx_enc->deadline);
1521 break;
1522 case PROP_H_SCALING_MODE:
1523 g_value_set_enum (value, gst_vpx_enc->h_scaling_mode);
1524 break;
1525 case PROP_V_SCALING_MODE:
1526 g_value_set_enum (value, gst_vpx_enc->v_scaling_mode);
1527 break;
1528 case PROP_CPU_USED:
1529 g_value_set_int (value, gst_vpx_enc->cpu_used);
1530 break;
1531 case PROP_ENABLE_AUTO_ALT_REF:
1532 g_value_set_boolean (value, gst_vpx_enc->enable_auto_alt_ref);
1533 break;
1534 case PROP_NOISE_SENSITIVITY:
1535 g_value_set_int (value, gst_vpx_enc->noise_sensitivity);
1536 break;
1537 case PROP_SHARPNESS:
1538 g_value_set_int (value, gst_vpx_enc->sharpness);
1539 break;
1540 case PROP_STATIC_THRESHOLD:
1541 g_value_set_int (value, gst_vpx_enc->static_threshold);
1542 break;
1543 case PROP_TOKEN_PARTITIONS:
1544 g_value_set_enum (value, gst_vpx_enc->token_partitions);
1545 break;
1546 case PROP_ARNR_MAXFRAMES:
1547 g_value_set_int (value, gst_vpx_enc->arnr_maxframes);
1548 break;
1549 case PROP_ARNR_STRENGTH:
1550 g_value_set_int (value, gst_vpx_enc->arnr_strength);
1551 break;
1552 case PROP_ARNR_TYPE:
1553 g_value_set_int (value, gst_vpx_enc->arnr_type);
1554 break;
1555 case PROP_TUNING:
1556 g_value_set_enum (value, gst_vpx_enc->tuning);
1557 break;
1558 case PROP_CQ_LEVEL:
1559 g_value_set_int (value, gst_vpx_enc->cq_level);
1560 break;
1561 case PROP_MAX_INTRA_BITRATE_PCT:
1562 g_value_set_int (value, gst_vpx_enc->max_intra_bitrate_pct);
1563 break;
1564 case PROP_TIMEBASE:
1565 gst_value_set_fraction (value, gst_vpx_enc->timebase_n,
1566 gst_vpx_enc->timebase_d);
1567 break;
1568 case PROP_BITS_PER_PIXEL:
1569 g_value_set_float (value, gst_vpx_enc->bits_per_pixel);
1570 break;
1571 default:
1572 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1573 break;
1574 }
1575
1576 g_mutex_unlock (&gst_vpx_enc->encoder_lock);
1577 }
1578
1579 static gboolean
gst_vpx_enc_start(GstVideoEncoder * video_encoder)1580 gst_vpx_enc_start (GstVideoEncoder * video_encoder)
1581 {
1582 GstVPXEnc *encoder = GST_VPX_ENC (video_encoder);
1583
1584 GST_DEBUG_OBJECT (video_encoder, "start");
1585
1586 if (!encoder->have_default_config) {
1587 GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
1588 ("Failed to get default encoder configuration"), (NULL));
1589 return FALSE;
1590 }
1591
1592 return TRUE;
1593 }
1594
1595 static void
gst_vpx_enc_destroy_encoder(GstVPXEnc * encoder)1596 gst_vpx_enc_destroy_encoder (GstVPXEnc * encoder)
1597 {
1598 g_mutex_lock (&encoder->encoder_lock);
1599 if (encoder->inited) {
1600 vpx_codec_destroy (&encoder->encoder);
1601 encoder->inited = FALSE;
1602 }
1603
1604 if (encoder->first_pass_cache_content) {
1605 g_byte_array_free (encoder->first_pass_cache_content, TRUE);
1606 encoder->first_pass_cache_content = NULL;
1607 }
1608
1609 if (encoder->cfg.rc_twopass_stats_in.buf) {
1610 g_free (encoder->cfg.rc_twopass_stats_in.buf);
1611 encoder->cfg.rc_twopass_stats_in.buf = NULL;
1612 encoder->cfg.rc_twopass_stats_in.sz = 0;
1613 }
1614 g_mutex_unlock (&encoder->encoder_lock);
1615 }
1616
1617 static gboolean
gst_vpx_enc_stop(GstVideoEncoder * video_encoder)1618 gst_vpx_enc_stop (GstVideoEncoder * video_encoder)
1619 {
1620 GstVPXEnc *encoder;
1621
1622 GST_DEBUG_OBJECT (video_encoder, "stop");
1623
1624 encoder = GST_VPX_ENC (video_encoder);
1625
1626 gst_vpx_enc_destroy_encoder (encoder);
1627
1628 gst_tag_setter_reset_tags (GST_TAG_SETTER (encoder));
1629
1630 g_free (encoder->multipass_cache_file);
1631 encoder->multipass_cache_file = NULL;
1632 encoder->multipass_cache_idx = 0;
1633
1634 return TRUE;
1635 }
1636
1637 #define INVALID_PROFILE -1
1638
1639 static gint
gst_vpx_gvalue_to_profile(const GValue * v)1640 gst_vpx_gvalue_to_profile (const GValue * v)
1641 {
1642 gchar *endptr = NULL;
1643 gint profile = g_ascii_strtoull (g_value_get_string (v), &endptr, 10);
1644
1645 if (*endptr != '\0') {
1646 profile = INVALID_PROFILE;
1647 }
1648
1649 return profile;
1650 }
1651
1652 static gint
gst_vpx_enc_get_downstream_profile(GstVPXEnc * encoder,GstVideoInfo * info)1653 gst_vpx_enc_get_downstream_profile (GstVPXEnc * encoder, GstVideoInfo * info)
1654 {
1655 GstCaps *allowed;
1656 GstStructure *s;
1657 gint min_profile;
1658 gint profile = INVALID_PROFILE;
1659
1660 switch (GST_VIDEO_INFO_FORMAT (info)) {
1661 case GST_VIDEO_FORMAT_Y444:
1662 min_profile = 1;
1663 break;
1664 case GST_VIDEO_FORMAT_I420_10LE:
1665 min_profile = 2;
1666 break;
1667 case GST_VIDEO_FORMAT_I422_10LE:
1668 min_profile = 3;
1669 break;
1670 default:
1671 min_profile = 0;
1672 }
1673
1674 allowed = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1675 if (allowed) {
1676 allowed = gst_caps_truncate (allowed);
1677 s = gst_caps_get_structure (allowed, 0);
1678 if (gst_structure_has_field (s, "profile")) {
1679 const GValue *v = gst_structure_get_value (s, "profile");
1680
1681 if (GST_VALUE_HOLDS_LIST (v)) {
1682 gint i;
1683
1684 for (i = 0; i != gst_value_list_get_size (v); ++i) {
1685 gint p = gst_vpx_gvalue_to_profile (gst_value_list_get_value (v, i));
1686 if (p >= min_profile) {
1687 profile = p;
1688 break;
1689 }
1690 }
1691 } else if (G_VALUE_HOLDS_STRING (v)) {
1692 profile = gst_vpx_gvalue_to_profile (v);
1693 }
1694
1695 if (profile < min_profile || profile > 3) {
1696 profile = INVALID_PROFILE;
1697 }
1698
1699 if (profile > 1 && info->finfo->bits == 8) {
1700 GST_DEBUG_OBJECT (encoder,
1701 "Codec bit-depth 8 not supported in profile > 1");
1702 profile = INVALID_PROFILE;
1703 }
1704 }
1705 gst_caps_unref (allowed);
1706 }
1707
1708 GST_DEBUG_OBJECT (encoder, "Using profile %d", profile);
1709
1710 return profile;
1711 }
1712
1713 static gboolean
gst_vpx_enc_set_format(GstVideoEncoder * video_encoder,GstVideoCodecState * state)1714 gst_vpx_enc_set_format (GstVideoEncoder * video_encoder,
1715 GstVideoCodecState * state)
1716 {
1717 GstVPXEnc *encoder;
1718 vpx_codec_err_t status;
1719 vpx_image_t *image;
1720 vpx_codec_flags_t flags = 0;
1721 GstCaps *caps;
1722 gboolean ret = TRUE;
1723 GstVideoInfo *info = &state->info;
1724 GstVideoCodecState *output_state;
1725 GstClockTime latency;
1726 GstVPXEncClass *vpx_enc_class;
1727
1728 encoder = GST_VPX_ENC (video_encoder);
1729 vpx_enc_class = GST_VPX_ENC_GET_CLASS (encoder);
1730 GST_DEBUG_OBJECT (video_encoder, "set_format");
1731
1732 if (encoder->inited) {
1733 gst_vpx_enc_drain (video_encoder);
1734 g_mutex_lock (&encoder->encoder_lock);
1735 vpx_codec_destroy (&encoder->encoder);
1736 encoder->inited = FALSE;
1737 encoder->multipass_cache_idx++;
1738 } else {
1739 g_mutex_lock (&encoder->encoder_lock);
1740 }
1741
1742 encoder->cfg.g_bit_depth = encoder->cfg.g_input_bit_depth = info->finfo->bits;
1743 if (encoder->cfg.g_bit_depth > 8) {
1744 flags |= VPX_CODEC_USE_HIGHBITDEPTH;
1745 }
1746
1747 encoder->cfg.g_profile = gst_vpx_enc_get_downstream_profile (encoder, info);
1748 if (encoder->cfg.g_profile == INVALID_PROFILE) {
1749 GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
1750 ("Invalid vpx profile"), (NULL));
1751 g_mutex_unlock (&encoder->encoder_lock);
1752 return FALSE;
1753 }
1754
1755 encoder->cfg.g_w = GST_VIDEO_INFO_WIDTH (info);
1756 encoder->cfg.g_h = GST_VIDEO_INFO_HEIGHT (info);
1757
1758 if (encoder->timebase_n != 0 && encoder->timebase_d != 0) {
1759 GST_DEBUG_OBJECT (video_encoder, "Using timebase configuration");
1760 encoder->cfg.g_timebase.num = encoder->timebase_n;
1761 encoder->cfg.g_timebase.den = encoder->timebase_d;
1762 } else {
1763 /* Zero framerate and max-framerate but still need to setup the timebase to avoid
1764 * a divide by zero error. Presuming the lowest common denominator will be RTP -
1765 * VP8 payload draft states clock rate of 90000 which should work for anyone where
1766 * FPS < 90000 (shouldn't be too many cases where it's higher) though wouldn't be optimal. RTP specification
1767 * http://tools.ietf.org/html/draft-ietf-payload-vp8-01 section 6.3.1 */
1768 encoder->cfg.g_timebase.num = 1;
1769 encoder->cfg.g_timebase.den = 90000;
1770 }
1771
1772 if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS ||
1773 encoder->cfg.g_pass == VPX_RC_LAST_PASS) {
1774 if (!encoder->multipass_cache_prefix) {
1775 GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
1776 ("No multipass cache file provided"), (NULL));
1777 g_mutex_unlock (&encoder->encoder_lock);
1778 return FALSE;
1779 }
1780
1781 g_free (encoder->multipass_cache_file);
1782
1783 if (encoder->multipass_cache_idx > 0)
1784 encoder->multipass_cache_file = g_strdup_printf ("%s.%u",
1785 encoder->multipass_cache_prefix, encoder->multipass_cache_idx);
1786 else
1787 encoder->multipass_cache_file =
1788 g_strdup (encoder->multipass_cache_prefix);
1789 }
1790
1791 if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS) {
1792 if (encoder->first_pass_cache_content != NULL)
1793 g_byte_array_free (encoder->first_pass_cache_content, TRUE);
1794
1795 encoder->first_pass_cache_content = g_byte_array_sized_new (4096);
1796
1797 } else if (encoder->cfg.g_pass == VPX_RC_LAST_PASS) {
1798 GError *err = NULL;
1799
1800 if (encoder->cfg.rc_twopass_stats_in.buf != NULL) {
1801 g_free (encoder->cfg.rc_twopass_stats_in.buf);
1802 encoder->cfg.rc_twopass_stats_in.buf = NULL;
1803 encoder->cfg.rc_twopass_stats_in.sz = 0;
1804 }
1805
1806 if (!g_file_get_contents (encoder->multipass_cache_file,
1807 (gchar **) & encoder->cfg.rc_twopass_stats_in.buf,
1808 &encoder->cfg.rc_twopass_stats_in.sz, &err)) {
1809 GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
1810 ("Failed to read multipass cache file provided"), ("%s",
1811 err->message));
1812 g_error_free (err);
1813 g_mutex_unlock (&encoder->encoder_lock);
1814 return FALSE;
1815 }
1816 }
1817
1818 status =
1819 vpx_codec_enc_init (&encoder->encoder, vpx_enc_class->get_algo (encoder),
1820 &encoder->cfg, flags);
1821 if (status != VPX_CODEC_OK) {
1822 GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
1823 ("Failed to initialize encoder"), ("%s", gst_vpx_error_name (status)));
1824 g_mutex_unlock (&encoder->encoder_lock);
1825 return FALSE;
1826 }
1827
1828 if (vpx_enc_class->enable_scaling (encoder)) {
1829 vpx_scaling_mode_t sm;
1830
1831 sm.h_scaling_mode = encoder->h_scaling_mode;
1832 sm.v_scaling_mode = encoder->v_scaling_mode;
1833
1834 status = vpx_codec_control (&encoder->encoder, VP8E_SET_SCALEMODE, &sm);
1835 if (status != VPX_CODEC_OK) {
1836 GST_WARNING_OBJECT (encoder, "Failed to set VP8E_SET_SCALEMODE: %s",
1837 gst_vpx_error_name (status));
1838 }
1839 }
1840
1841 status =
1842 vpx_codec_control (&encoder->encoder, VP8E_SET_CPUUSED,
1843 encoder->cpu_used);
1844 if (status != VPX_CODEC_OK) {
1845 GST_WARNING_OBJECT (encoder, "Failed to set VP8E_SET_CPUUSED: %s",
1846 gst_vpx_error_name (status));
1847 }
1848
1849 status =
1850 vpx_codec_control (&encoder->encoder, VP8E_SET_ENABLEAUTOALTREF,
1851 (encoder->enable_auto_alt_ref ? 1 : 0));
1852 if (status != VPX_CODEC_OK) {
1853 GST_WARNING_OBJECT (encoder,
1854 "Failed to set VP8E_SET_ENABLEAUTOALTREF: %s",
1855 gst_vpx_error_name (status));
1856 }
1857 status = vpx_codec_control (&encoder->encoder, VP8E_SET_NOISE_SENSITIVITY,
1858 encoder->noise_sensitivity);
1859 if (status != VPX_CODEC_OK) {
1860 GST_WARNING_OBJECT (encoder,
1861 "Failed to set VP8E_SET_NOISE_SENSITIVITY: %s",
1862 gst_vpx_error_name (status));
1863 }
1864 status = vpx_codec_control (&encoder->encoder, VP8E_SET_SHARPNESS,
1865 encoder->sharpness);
1866 if (status != VPX_CODEC_OK) {
1867 GST_WARNING_OBJECT (encoder,
1868 "Failed to set VP8E_SET_SHARPNESS: %s", gst_vpx_error_name (status));
1869 }
1870 status = vpx_codec_control (&encoder->encoder, VP8E_SET_STATIC_THRESHOLD,
1871 encoder->static_threshold);
1872 if (status != VPX_CODEC_OK) {
1873 GST_WARNING_OBJECT (encoder,
1874 "Failed to set VP8E_SET_STATIC_THRESHOLD: %s",
1875 gst_vpx_error_name (status));
1876 }
1877 status = vpx_codec_control (&encoder->encoder, VP8E_SET_TOKEN_PARTITIONS,
1878 encoder->token_partitions);
1879 if (status != VPX_CODEC_OK) {
1880 GST_WARNING_OBJECT (encoder,
1881 "Failed to set VP8E_SET_TOKEN_PARTIONS: %s",
1882 gst_vpx_error_name (status));
1883 }
1884 status = vpx_codec_control (&encoder->encoder, VP8E_SET_ARNR_MAXFRAMES,
1885 encoder->arnr_maxframes);
1886 if (status != VPX_CODEC_OK) {
1887 GST_WARNING_OBJECT (encoder,
1888 "Failed to set VP8E_SET_ARNR_MAXFRAMES: %s",
1889 gst_vpx_error_name (status));
1890 }
1891 status = vpx_codec_control (&encoder->encoder, VP8E_SET_ARNR_STRENGTH,
1892 encoder->arnr_strength);
1893 if (status != VPX_CODEC_OK) {
1894 GST_WARNING_OBJECT (encoder,
1895 "Failed to set VP8E_SET_ARNR_STRENGTH: %s",
1896 gst_vpx_error_name (status));
1897 }
1898 status = vpx_codec_control (&encoder->encoder, VP8E_SET_TUNING,
1899 encoder->tuning);
1900 if (status != VPX_CODEC_OK) {
1901 GST_WARNING_OBJECT (encoder,
1902 "Failed to set VP8E_SET_TUNING: %s", gst_vpx_error_name (status));
1903 }
1904 status = vpx_codec_control (&encoder->encoder, VP8E_SET_CQ_LEVEL,
1905 encoder->cq_level);
1906 if (status != VPX_CODEC_OK) {
1907 GST_WARNING_OBJECT (encoder,
1908 "Failed to set VP8E_SET_CQ_LEVEL: %s", gst_vpx_error_name (status));
1909 }
1910 status = vpx_codec_control (&encoder->encoder, VP8E_SET_MAX_INTRA_BITRATE_PCT,
1911 encoder->max_intra_bitrate_pct);
1912 if (status != VPX_CODEC_OK) {
1913 GST_WARNING_OBJECT (encoder,
1914 "Failed to set VP8E_SET_MAX_INTRA_BITRATE_PCT: %s",
1915 gst_vpx_error_name (status));
1916 }
1917
1918 if (vpx_enc_class->configure_encoder
1919 && !vpx_enc_class->configure_encoder (encoder, state)) {
1920 ret = FALSE;
1921 g_mutex_unlock (&encoder->encoder_lock);
1922 goto done;
1923 }
1924
1925 if (GST_VIDEO_INFO_FPS_D (info) == 0 || GST_VIDEO_INFO_FPS_N (info) == 0) {
1926 /* FIXME: Assume 25fps for unknown framerates. Better than reporting
1927 * that we introduce no latency while we actually do
1928 */
1929 latency = gst_util_uint64_scale (encoder->cfg.g_lag_in_frames,
1930 1 * GST_SECOND, 25);
1931 } else {
1932 latency = gst_util_uint64_scale (encoder->cfg.g_lag_in_frames,
1933 GST_VIDEO_INFO_FPS_D (info) * GST_SECOND, GST_VIDEO_INFO_FPS_N (info));
1934 }
1935 gst_video_encoder_set_latency (video_encoder, latency, latency);
1936 encoder->inited = TRUE;
1937
1938 /* Store input state */
1939 if (encoder->input_state)
1940 gst_video_codec_state_unref (encoder->input_state);
1941 encoder->input_state = gst_video_codec_state_ref (state);
1942
1943 /* Scale default bitrate to our size */
1944 if (encoder->rc_target_bitrate_auto)
1945 gst_vpx_enc_set_auto_bitrate (encoder);
1946
1947 /* prepare cached image buffer setup */
1948 image = &encoder->image;
1949 memset (image, 0, sizeof (*image));
1950
1951 vpx_enc_class->set_image_format (encoder, image);
1952
1953 image->w = image->d_w = GST_VIDEO_INFO_WIDTH (info);
1954 image->h = image->d_h = GST_VIDEO_INFO_HEIGHT (info);
1955
1956 image->stride[VPX_PLANE_Y] = GST_VIDEO_INFO_COMP_STRIDE (info, 0);
1957 image->stride[VPX_PLANE_U] = GST_VIDEO_INFO_COMP_STRIDE (info, 1);
1958 image->stride[VPX_PLANE_V] = GST_VIDEO_INFO_COMP_STRIDE (info, 2);
1959
1960 caps = vpx_enc_class->get_new_vpx_caps (encoder);
1961
1962 vpx_enc_class->set_stream_info (encoder, caps, info);
1963
1964 g_mutex_unlock (&encoder->encoder_lock);
1965
1966 output_state =
1967 gst_video_encoder_set_output_state (video_encoder, caps, state);
1968 gst_video_codec_state_unref (output_state);
1969
1970 gst_video_encoder_negotiate (GST_VIDEO_ENCODER (encoder));
1971
1972 done:
1973 return ret;
1974 }
1975
1976 static GstFlowReturn
gst_vpx_enc_process(GstVPXEnc * encoder)1977 gst_vpx_enc_process (GstVPXEnc * encoder)
1978 {
1979 vpx_codec_iter_t iter = NULL;
1980 const vpx_codec_cx_pkt_t *pkt;
1981 GstVideoEncoder *video_encoder;
1982 void *user_data;
1983 GstVideoCodecFrame *frame;
1984 GstFlowReturn ret = GST_FLOW_OK;
1985 GstVPXEncClass *vpx_enc_class;
1986 vpx_codec_pts_t pts;
1987 guint layer_id = 0;
1988 guint8 tl0picidx = 0;
1989 gboolean layer_sync = FALSE;
1990
1991 video_encoder = GST_VIDEO_ENCODER (encoder);
1992 vpx_enc_class = GST_VPX_ENC_GET_CLASS (encoder);
1993
1994 g_mutex_lock (&encoder->encoder_lock);
1995 pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
1996 while (pkt != NULL) {
1997 GstBuffer *buffer;
1998 gboolean invisible;
1999
2000 GST_DEBUG_OBJECT (encoder, "packet %u type %d", (guint) pkt->data.frame.sz,
2001 pkt->kind);
2002
2003 if (pkt->kind == VPX_CODEC_STATS_PKT
2004 && encoder->cfg.g_pass == VPX_RC_FIRST_PASS) {
2005 GST_LOG_OBJECT (encoder, "handling STATS packet");
2006
2007 g_byte_array_append (encoder->first_pass_cache_content,
2008 pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz);
2009
2010 frame = gst_video_encoder_get_oldest_frame (video_encoder);
2011 if (frame != NULL) {
2012 buffer = gst_buffer_new ();
2013 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_LIVE);
2014 frame->output_buffer = buffer;
2015 g_mutex_unlock (&encoder->encoder_lock);
2016 ret = gst_video_encoder_finish_frame (video_encoder, frame);
2017 g_mutex_lock (&encoder->encoder_lock);
2018 }
2019
2020 pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
2021 continue;
2022 } else if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) {
2023 GST_LOG_OBJECT (encoder, "non frame pkt: %d", pkt->kind);
2024 pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
2025 continue;
2026 }
2027
2028 invisible = (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) != 0;
2029
2030 /* discard older frames that were dropped by libvpx */
2031 frame = NULL;
2032 do {
2033 if (frame)
2034 gst_video_encoder_finish_frame (video_encoder, frame);
2035 frame = gst_video_encoder_get_oldest_frame (video_encoder);
2036 if (!frame) {
2037 GST_WARNING_OBJECT (encoder,
2038 "vpx pts %" G_GINT64_FORMAT
2039 " does not match input frames, discarding", pkt->data.frame.pts);
2040 goto out;
2041 }
2042
2043 pts =
2044 gst_util_uint64_scale (frame->pts,
2045 encoder->cfg.g_timebase.den,
2046 encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
2047 GST_TRACE_OBJECT (encoder, "vpx pts: %" G_GINT64_FORMAT
2048 ", gst frame pts: %" G_GINT64_FORMAT, (gint64) pkt->data.frame.pts,
2049 (gint64) pts);
2050 } while (pkt->data.frame.pts > pts);
2051
2052 g_assert (frame != NULL);
2053
2054 /* FIXME : It would be nice to avoid the memory copy ... */
2055 buffer = gst_buffer_new_memdup (pkt->data.frame.buf, pkt->data.frame.sz);
2056
2057 user_data = vpx_enc_class->process_frame_user_data (encoder, frame);
2058 if (vpx_enc_class->get_frame_temporal_settings &&
2059 encoder->cfg.ts_periodicity != 0) {
2060 vpx_enc_class->get_frame_temporal_settings (encoder, frame,
2061 &layer_id, &tl0picidx, &layer_sync);
2062 }
2063
2064 if (layer_id != 0 && encoder->prev_was_keyframe) {
2065 /* Non-base layer frame immediately after a keyframe is a layer sync */
2066 layer_sync = TRUE;
2067 }
2068
2069 if ((pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0) {
2070 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
2071 /* Key frames always live on layer 0 */
2072 layer_id = 0;
2073 layer_sync = TRUE;
2074 encoder->prev_was_keyframe = TRUE;
2075 } else {
2076 GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
2077 encoder->prev_was_keyframe = FALSE;
2078 }
2079
2080 if ((pkt->data.frame.flags & VPX_FRAME_IS_DROPPABLE) != 0)
2081 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DROPPABLE);
2082 else
2083 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DROPPABLE);
2084
2085 if (layer_id == 0) {
2086 /* Allocate a new tl0picidx if this is layer 0 */
2087 tl0picidx = ++encoder->tl0picidx;
2088 }
2089
2090 if (vpx_enc_class->preflight_buffer) {
2091 vpx_enc_class->preflight_buffer (encoder, frame, buffer,
2092 layer_sync, layer_id, tl0picidx);
2093 }
2094
2095 if (invisible) {
2096 ret =
2097 vpx_enc_class->handle_invisible_frame_buffer (encoder, user_data,
2098 buffer);
2099 gst_video_codec_frame_unref (frame);
2100 } else {
2101 frame->output_buffer = buffer;
2102 g_mutex_unlock (&encoder->encoder_lock);
2103 ret = gst_video_encoder_finish_frame (video_encoder, frame);
2104 g_mutex_lock (&encoder->encoder_lock);
2105 }
2106
2107 pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
2108 }
2109
2110 out:
2111 g_mutex_unlock (&encoder->encoder_lock);
2112
2113 return ret;
2114 }
2115
2116 /* This function should be called holding then stream lock*/
2117 static GstFlowReturn
gst_vpx_enc_drain(GstVideoEncoder * video_encoder)2118 gst_vpx_enc_drain (GstVideoEncoder * video_encoder)
2119 {
2120 GstVPXEnc *encoder;
2121 int flags = 0;
2122 vpx_codec_err_t status;
2123 gint64 deadline;
2124 vpx_codec_pts_t pts;
2125
2126 encoder = GST_VPX_ENC (video_encoder);
2127
2128 g_mutex_lock (&encoder->encoder_lock);
2129 deadline = encoder->deadline;
2130
2131 pts =
2132 gst_util_uint64_scale (encoder->last_pts,
2133 encoder->cfg.g_timebase.den,
2134 encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
2135
2136 status = vpx_codec_encode (&encoder->encoder, NULL, pts, 0, flags, deadline);
2137 g_mutex_unlock (&encoder->encoder_lock);
2138
2139 if (status != 0) {
2140 GST_ERROR_OBJECT (encoder, "encode returned %d %s", status,
2141 gst_vpx_error_name (status));
2142 return GST_FLOW_ERROR;
2143 }
2144
2145 /* dispatch remaining frames */
2146 gst_vpx_enc_process (encoder);
2147
2148 g_mutex_lock (&encoder->encoder_lock);
2149 if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS && encoder->multipass_cache_file) {
2150 GError *err = NULL;
2151
2152 if (!g_file_set_contents (encoder->multipass_cache_file,
2153 (const gchar *) encoder->first_pass_cache_content->data,
2154 encoder->first_pass_cache_content->len, &err)) {
2155 GST_ELEMENT_ERROR (encoder, RESOURCE, WRITE, (NULL),
2156 ("Failed to write multipass cache file: %s", err->message));
2157 g_error_free (err);
2158 }
2159 }
2160 g_mutex_unlock (&encoder->encoder_lock);
2161
2162 return GST_FLOW_OK;
2163 }
2164
2165 static gboolean
gst_vpx_enc_flush(GstVideoEncoder * video_encoder)2166 gst_vpx_enc_flush (GstVideoEncoder * video_encoder)
2167 {
2168 GstVPXEnc *encoder;
2169
2170 GST_DEBUG_OBJECT (video_encoder, "flush");
2171
2172 encoder = GST_VPX_ENC (video_encoder);
2173
2174 gst_vpx_enc_destroy_encoder (encoder);
2175 if (encoder->input_state) {
2176 gst_video_codec_state_ref (encoder->input_state);
2177 gst_vpx_enc_set_format (video_encoder, encoder->input_state);
2178 gst_video_codec_state_unref (encoder->input_state);
2179 }
2180
2181 return TRUE;
2182 }
2183
2184 static GstFlowReturn
gst_vpx_enc_finish(GstVideoEncoder * video_encoder)2185 gst_vpx_enc_finish (GstVideoEncoder * video_encoder)
2186 {
2187 GstVPXEnc *encoder;
2188 GstFlowReturn ret;
2189
2190 GST_DEBUG_OBJECT (video_encoder, "finish");
2191
2192 encoder = GST_VPX_ENC (video_encoder);
2193
2194 if (encoder->inited) {
2195 ret = gst_vpx_enc_drain (video_encoder);
2196 } else {
2197 ret = GST_FLOW_OK;
2198 }
2199
2200 return ret;
2201 }
2202
2203 static vpx_image_t *
gst_vpx_enc_buffer_to_image(GstVPXEnc * enc,GstVideoFrame * frame)2204 gst_vpx_enc_buffer_to_image (GstVPXEnc * enc, GstVideoFrame * frame)
2205 {
2206 vpx_image_t *image = g_slice_new (vpx_image_t);
2207
2208 memcpy (image, &enc->image, sizeof (*image));
2209
2210 image->planes[VPX_PLANE_Y] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
2211 image->planes[VPX_PLANE_U] = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
2212 image->planes[VPX_PLANE_V] = GST_VIDEO_FRAME_COMP_DATA (frame, 2);
2213
2214 image->stride[VPX_PLANE_Y] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
2215 image->stride[VPX_PLANE_U] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1);
2216 image->stride[VPX_PLANE_V] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2);
2217
2218 return image;
2219 }
2220
2221 static GstFlowReturn
gst_vpx_enc_handle_frame(GstVideoEncoder * video_encoder,GstVideoCodecFrame * frame)2222 gst_vpx_enc_handle_frame (GstVideoEncoder * video_encoder,
2223 GstVideoCodecFrame * frame)
2224 {
2225 GstVPXEnc *encoder;
2226 vpx_codec_err_t status;
2227 int flags = 0;
2228 vpx_image_t *image;
2229 GstVideoFrame vframe;
2230 vpx_codec_pts_t pts;
2231 unsigned long duration;
2232 GstVPXEncClass *vpx_enc_class;
2233
2234 GST_DEBUG_OBJECT (video_encoder, "handle_frame");
2235
2236 encoder = GST_VPX_ENC (video_encoder);
2237 vpx_enc_class = GST_VPX_ENC_GET_CLASS (encoder);
2238
2239 GST_DEBUG_OBJECT (video_encoder, "size %d %d",
2240 GST_VIDEO_INFO_WIDTH (&encoder->input_state->info),
2241 GST_VIDEO_INFO_HEIGHT (&encoder->input_state->info));
2242
2243 gst_video_frame_map (&vframe, &encoder->input_state->info,
2244 frame->input_buffer, GST_MAP_READ);
2245 image = gst_vpx_enc_buffer_to_image (encoder, &vframe);
2246
2247 vpx_enc_class->set_frame_user_data (encoder, frame, image);
2248
2249 if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
2250 flags |= VPX_EFLAG_FORCE_KF;
2251 }
2252
2253 g_mutex_lock (&encoder->encoder_lock);
2254 pts =
2255 gst_util_uint64_scale (frame->pts,
2256 encoder->cfg.g_timebase.den,
2257 encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
2258 encoder->last_pts = frame->pts;
2259
2260 if (frame->duration != GST_CLOCK_TIME_NONE) {
2261 duration =
2262 gst_util_uint64_scale (frame->duration, encoder->cfg.g_timebase.den,
2263 encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
2264
2265 if (duration > 0) {
2266 encoder->last_pts += frame->duration;
2267 } else {
2268 /* We force the path ignoring the duration if we end up with a zero
2269 * value for duration after scaling (e.g. duration value too small) */
2270 GST_WARNING_OBJECT (encoder,
2271 "Ignoring too small frame duration %" GST_TIME_FORMAT,
2272 GST_TIME_ARGS (frame->duration));
2273 duration = 1;
2274 }
2275 } else {
2276 duration = 1;
2277 }
2278
2279 if (encoder->n_ts_layer_flags != 0) {
2280 /* If we need a keyframe, then the pattern is irrelevant */
2281 if ((flags & VPX_EFLAG_FORCE_KF) == 0) {
2282 flags |=
2283 encoder->ts_layer_flags[frame->system_frame_number %
2284 encoder->n_ts_layer_flags];
2285 }
2286 }
2287
2288 if (vpx_enc_class->apply_frame_temporal_settings &&
2289 encoder->cfg.ts_periodicity != 0 &&
2290 encoder->n_ts_layer_id >= encoder->cfg.ts_periodicity) {
2291 vpx_enc_class->apply_frame_temporal_settings (encoder, frame,
2292 encoder->cfg.ts_layer_id[frame->system_frame_number %
2293 encoder->cfg.ts_periodicity], encoder->tl0picidx,
2294 encoder->ts_layer_sync_flags[frame->system_frame_number %
2295 encoder->n_ts_layer_sync_flags]);
2296 }
2297
2298 status = vpx_codec_encode (&encoder->encoder, image,
2299 pts, duration, flags, encoder->deadline);
2300
2301 g_mutex_unlock (&encoder->encoder_lock);
2302 gst_video_frame_unmap (&vframe);
2303
2304 if (status != 0) {
2305 GST_ELEMENT_ERROR (encoder, LIBRARY, ENCODE,
2306 ("Failed to encode frame"), ("%s", gst_vpx_error_name (status)));
2307 gst_video_codec_frame_set_user_data (frame, NULL, NULL);
2308 gst_video_codec_frame_unref (frame);
2309
2310 return GST_FLOW_ERROR;
2311 }
2312 gst_video_codec_frame_unref (frame);
2313 return gst_vpx_enc_process (encoder);
2314 }
2315
2316 static gboolean
gst_vpx_enc_sink_event(GstVideoEncoder * benc,GstEvent * event)2317 gst_vpx_enc_sink_event (GstVideoEncoder * benc, GstEvent * event)
2318 {
2319 GstVPXEnc *enc = GST_VPX_ENC (benc);
2320
2321 /* FIXME : Move this to base encoder class */
2322
2323 if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) {
2324 GstTagList *list;
2325 GstTagSetter *setter = GST_TAG_SETTER (enc);
2326 const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
2327
2328 gst_event_parse_tag (event, &list);
2329 gst_tag_setter_merge_tags (setter, list, mode);
2330 }
2331
2332 /* just peeked, baseclass handles the rest */
2333 return GST_VIDEO_ENCODER_CLASS (parent_class)->sink_event (benc, event);
2334 }
2335
2336 static gboolean
gst_vpx_enc_propose_allocation(GstVideoEncoder * encoder,GstQuery * query)2337 gst_vpx_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
2338 {
2339 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
2340
2341 return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
2342 query);
2343 }
2344
2345 static gboolean
gst_vpx_enc_transform_meta(GstVideoEncoder * encoder,GstVideoCodecFrame * frame,GstMeta * meta)2346 gst_vpx_enc_transform_meta (GstVideoEncoder * encoder,
2347 GstVideoCodecFrame * frame, GstMeta * meta)
2348 {
2349 const GstMetaInfo *info = meta->info;
2350 gboolean ret = FALSE;
2351
2352 /* Do not copy GstVP8Meta from input to output buffer */
2353 if (gst_meta_info_is_custom (info)
2354 && gst_custom_meta_has_name ((GstCustomMeta *) meta, "GstVP8Meta"))
2355 goto done;
2356
2357 ret = TRUE;
2358
2359 done:
2360 return ret;
2361 }
2362
2363 #endif /* HAVE_VP8_ENCODER || HAVE_VP9_ENCODER */
2364