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 256000
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 
79 #define DEFAULT_ERROR_RESILIENT 0
80 #define DEFAULT_LAG_IN_FRAMES 0
81 
82 #define DEFAULT_THREADS 0
83 
84 #define DEFAULT_H_SCALING_MODE VP8E_NORMAL
85 #define DEFAULT_V_SCALING_MODE VP8E_NORMAL
86 #define DEFAULT_CPU_USED 0
87 #define DEFAULT_ENABLE_AUTO_ALT_REF FALSE
88 #define DEFAULT_DEADLINE VPX_DL_BEST_QUALITY
89 #define DEFAULT_NOISE_SENSITIVITY 0
90 #define DEFAULT_SHARPNESS 0
91 #define DEFAULT_STATIC_THRESHOLD 0
92 #define DEFAULT_TOKEN_PARTITIONS 0
93 #define DEFAULT_ARNR_MAXFRAMES 0
94 #define DEFAULT_ARNR_STRENGTH 3
95 #define DEFAULT_ARNR_TYPE 3
96 #define DEFAULT_TUNING VP8_TUNE_PSNR
97 #define DEFAULT_CQ_LEVEL 10
98 #define DEFAULT_MAX_INTRA_BITRATE_PCT 0
99 #define DEFAULT_TIMEBASE_N 0
100 #define DEFAULT_TIMEBASE_D 1
101 
102 enum
103 {
104   PROP_0,
105   PROP_RC_END_USAGE,
106   PROP_RC_TARGET_BITRATE,
107   PROP_RC_MIN_QUANTIZER,
108   PROP_RC_MAX_QUANTIZER,
109   PROP_RC_DROPFRAME_THRESH,
110   PROP_RC_RESIZE_ALLOWED,
111   PROP_RC_RESIZE_UP_THRESH,
112   PROP_RC_RESIZE_DOWN_THRESH,
113   PROP_RC_UNDERSHOOT_PCT,
114   PROP_RC_OVERSHOOT_PCT,
115   PROP_RC_BUF_SZ,
116   PROP_RC_BUF_INITIAL_SZ,
117   PROP_RC_BUF_OPTIMAL_SZ,
118   PROP_RC_2PASS_VBR_BIAS_PCT,
119   PROP_RC_2PASS_VBR_MINSECTION_PCT,
120   PROP_RC_2PASS_VBR_MAXSECTION_PCT,
121   PROP_KF_MODE,
122   PROP_KF_MAX_DIST,
123   PROP_TS_NUMBER_LAYERS,
124   PROP_TS_TARGET_BITRATE,
125   PROP_TS_RATE_DECIMATOR,
126   PROP_TS_PERIODICITY,
127   PROP_TS_LAYER_ID,
128   PROP_MULTIPASS_MODE,
129   PROP_MULTIPASS_CACHE_FILE,
130   PROP_ERROR_RESILIENT,
131   PROP_LAG_IN_FRAMES,
132   PROP_THREADS,
133   PROP_DEADLINE,
134   PROP_H_SCALING_MODE,
135   PROP_V_SCALING_MODE,
136   PROP_CPU_USED,
137   PROP_ENABLE_AUTO_ALT_REF,
138   PROP_NOISE_SENSITIVITY,
139   PROP_SHARPNESS,
140   PROP_STATIC_THRESHOLD,
141   PROP_TOKEN_PARTITIONS,
142   PROP_ARNR_MAXFRAMES,
143   PROP_ARNR_STRENGTH,
144   PROP_ARNR_TYPE,
145   PROP_TUNING,
146   PROP_CQ_LEVEL,
147   PROP_MAX_INTRA_BITRATE_PCT,
148   PROP_TIMEBASE
149 };
150 
151 
152 #define GST_VPX_ENC_END_USAGE_TYPE (gst_vpx_enc_end_usage_get_type())
153 static GType
gst_vpx_enc_end_usage_get_type(void)154 gst_vpx_enc_end_usage_get_type (void)
155 {
156   static const GEnumValue values[] = {
157     {VPX_VBR, "Variable Bit Rate (VBR) mode", "vbr"},
158     {VPX_CBR, "Constant Bit Rate (CBR) mode", "cbr"},
159     {VPX_CQ, "Constant Quality Mode (CQ) mode", "cq"},
160     {0, NULL, NULL}
161   };
162   static volatile GType id = 0;
163 
164   if (g_once_init_enter ((gsize *) & id)) {
165     GType _id;
166 
167     _id = g_enum_register_static ("GstVPXEncEndUsage", values);
168 
169     g_once_init_leave ((gsize *) & id, _id);
170   }
171 
172   return id;
173 }
174 
175 #define GST_VPX_ENC_MULTIPASS_MODE_TYPE (gst_vpx_enc_multipass_mode_get_type())
176 static GType
gst_vpx_enc_multipass_mode_get_type(void)177 gst_vpx_enc_multipass_mode_get_type (void)
178 {
179   static const GEnumValue values[] = {
180     {VPX_RC_ONE_PASS, "One pass encoding (default)", "one-pass"},
181     {VPX_RC_FIRST_PASS, "First pass of multipass encoding", "first-pass"},
182     {VPX_RC_LAST_PASS, "Last pass of multipass encoding", "last-pass"},
183     {0, NULL, NULL}
184   };
185   static volatile GType id = 0;
186 
187   if (g_once_init_enter ((gsize *) & id)) {
188     GType _id;
189 
190     _id = g_enum_register_static ("GstVPXEncMultipassMode", values);
191 
192     g_once_init_leave ((gsize *) & id, _id);
193   }
194 
195   return id;
196 }
197 
198 #define GST_VPX_ENC_KF_MODE_TYPE (gst_vpx_enc_kf_mode_get_type())
199 static GType
gst_vpx_enc_kf_mode_get_type(void)200 gst_vpx_enc_kf_mode_get_type (void)
201 {
202   static const GEnumValue values[] = {
203     {VPX_KF_AUTO, "Determine optimal placement automatically", "auto"},
204     {VPX_KF_DISABLED, "Don't automatically place keyframes", "disabled"},
205     {0, NULL, NULL}
206   };
207   static volatile GType id = 0;
208 
209   if (g_once_init_enter ((gsize *) & id)) {
210     GType _id;
211 
212     _id = g_enum_register_static ("GstVPXEncKfMode", values);
213 
214     g_once_init_leave ((gsize *) & id, _id);
215   }
216 
217   return id;
218 }
219 
220 #define GST_VPX_ENC_TUNING_TYPE (gst_vpx_enc_tuning_get_type())
221 static GType
gst_vpx_enc_tuning_get_type(void)222 gst_vpx_enc_tuning_get_type (void)
223 {
224   static const GEnumValue values[] = {
225     {VP8_TUNE_PSNR, "Tune for PSNR", "psnr"},
226     {VP8_TUNE_SSIM, "Tune for SSIM", "ssim"},
227     {0, NULL, NULL}
228   };
229   static volatile GType id = 0;
230 
231   if (g_once_init_enter ((gsize *) & id)) {
232     GType _id;
233 
234     _id = g_enum_register_static ("GstVPXEncTuning", values);
235 
236     g_once_init_leave ((gsize *) & id, _id);
237   }
238 
239   return id;
240 }
241 
242 #define GST_VPX_ENC_SCALING_MODE_TYPE (gst_vpx_enc_scaling_mode_get_type())
243 static GType
gst_vpx_enc_scaling_mode_get_type(void)244 gst_vpx_enc_scaling_mode_get_type (void)
245 {
246   static const GEnumValue values[] = {
247     {VP8E_NORMAL, "Normal", "normal"},
248     {VP8E_FOURFIVE, "4:5", "4:5"},
249     {VP8E_THREEFIVE, "3:5", "3:5"},
250     {VP8E_ONETWO, "1:2", "1:2"},
251     {0, NULL, NULL}
252   };
253   static volatile GType id = 0;
254 
255   if (g_once_init_enter ((gsize *) & id)) {
256     GType _id;
257 
258     _id = g_enum_register_static ("GstVPXEncScalingMode", values);
259 
260     g_once_init_leave ((gsize *) & id, _id);
261   }
262 
263   return id;
264 }
265 
266 #define GST_VPX_ENC_TOKEN_PARTITIONS_TYPE (gst_vpx_enc_token_partitions_get_type())
267 static GType
gst_vpx_enc_token_partitions_get_type(void)268 gst_vpx_enc_token_partitions_get_type (void)
269 {
270   static const GEnumValue values[] = {
271     {VP8_ONE_TOKENPARTITION, "One token partition", "1"},
272     {VP8_TWO_TOKENPARTITION, "Two token partitions", "2"},
273     {VP8_FOUR_TOKENPARTITION, "Four token partitions", "4"},
274     {VP8_EIGHT_TOKENPARTITION, "Eight token partitions", "8"},
275     {0, NULL, NULL}
276   };
277   static volatile GType id = 0;
278 
279   if (g_once_init_enter ((gsize *) & id)) {
280     GType _id;
281 
282     _id = g_enum_register_static ("GstVPXEncTokenPartitions", values);
283 
284     g_once_init_leave ((gsize *) & id, _id);
285   }
286 
287   return id;
288 }
289 
290 #define GST_VPX_ENC_ER_FLAGS_TYPE (gst_vpx_enc_er_flags_get_type())
291 static GType
gst_vpx_enc_er_flags_get_type(void)292 gst_vpx_enc_er_flags_get_type (void)
293 {
294   static const GFlagsValue values[] = {
295     {VPX_ERROR_RESILIENT_DEFAULT, "Default error resilience", "default"},
296     {VPX_ERROR_RESILIENT_PARTITIONS,
297         "Allow partitions to be decoded independently", "partitions"},
298     {0, NULL, NULL}
299   };
300   static volatile GType id = 0;
301 
302   if (g_once_init_enter ((gsize *) & id)) {
303     GType _id;
304 
305     _id = g_flags_register_static ("GstVPXEncErFlags", values);
306 
307     g_once_init_leave ((gsize *) & id, _id);
308   }
309 
310   return id;
311 }
312 
313 static void gst_vpx_enc_finalize (GObject * object);
314 static void gst_vpx_enc_set_property (GObject * object, guint prop_id,
315     const GValue * value, GParamSpec * pspec);
316 static void gst_vpx_enc_get_property (GObject * object, guint prop_id,
317     GValue * value, GParamSpec * pspec);
318 
319 static gboolean gst_vpx_enc_start (GstVideoEncoder * encoder);
320 static gboolean gst_vpx_enc_stop (GstVideoEncoder * encoder);
321 static gboolean gst_vpx_enc_set_format (GstVideoEncoder *
322     video_encoder, GstVideoCodecState * state);
323 static GstFlowReturn gst_vpx_enc_finish (GstVideoEncoder * video_encoder);
324 static gboolean gst_vpx_enc_flush (GstVideoEncoder * video_encoder);
325 static GstFlowReturn gst_vpx_enc_drain (GstVideoEncoder * video_encoder);
326 static GstFlowReturn gst_vpx_enc_handle_frame (GstVideoEncoder *
327     video_encoder, GstVideoCodecFrame * frame);
328 static gboolean gst_vpx_enc_sink_event (GstVideoEncoder *
329     video_encoder, GstEvent * event);
330 static gboolean gst_vpx_enc_propose_allocation (GstVideoEncoder * encoder,
331     GstQuery * query);
332 
333 #define parent_class gst_vpx_enc_parent_class
334 G_DEFINE_TYPE_WITH_CODE (GstVPXEnc, gst_vpx_enc, GST_TYPE_VIDEO_ENCODER,
335     G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
336     G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL););
337 
338 static void
gst_vpx_enc_class_init(GstVPXEncClass * klass)339 gst_vpx_enc_class_init (GstVPXEncClass * klass)
340 {
341   GObjectClass *gobject_class;
342   GstVideoEncoderClass *video_encoder_class;
343 
344   gobject_class = G_OBJECT_CLASS (klass);
345   video_encoder_class = GST_VIDEO_ENCODER_CLASS (klass);
346 
347   gobject_class->set_property = gst_vpx_enc_set_property;
348   gobject_class->get_property = gst_vpx_enc_get_property;
349   gobject_class->finalize = gst_vpx_enc_finalize;
350 
351   video_encoder_class->start = gst_vpx_enc_start;
352   video_encoder_class->stop = gst_vpx_enc_stop;
353   video_encoder_class->handle_frame = gst_vpx_enc_handle_frame;
354   video_encoder_class->set_format = gst_vpx_enc_set_format;
355   video_encoder_class->flush = gst_vpx_enc_flush;
356   video_encoder_class->finish = gst_vpx_enc_finish;
357   video_encoder_class->sink_event = gst_vpx_enc_sink_event;
358   video_encoder_class->propose_allocation = gst_vpx_enc_propose_allocation;
359 
360   g_object_class_install_property (gobject_class, PROP_RC_END_USAGE,
361       g_param_spec_enum ("end-usage", "Rate control mode",
362           "Rate control mode",
363           GST_VPX_ENC_END_USAGE_TYPE, DEFAULT_RC_END_USAGE,
364           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
365 
366   g_object_class_install_property (gobject_class, PROP_RC_TARGET_BITRATE,
367       g_param_spec_int ("target-bitrate", "Target bitrate",
368           "Target bitrate (in bits/sec)",
369           0, G_MAXINT, DEFAULT_RC_TARGET_BITRATE,
370           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
371 
372   g_object_class_install_property (gobject_class, PROP_RC_MIN_QUANTIZER,
373       g_param_spec_int ("min-quantizer", "Minimum Quantizer",
374           "Minimum Quantizer (best)",
375           0, 63, DEFAULT_RC_MIN_QUANTIZER,
376           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
377 
378   g_object_class_install_property (gobject_class, PROP_RC_MAX_QUANTIZER,
379       g_param_spec_int ("max-quantizer", "Maximum Quantizer",
380           "Maximum Quantizer (worst)",
381           0, 63, DEFAULT_RC_MAX_QUANTIZER,
382           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
383 
384   g_object_class_install_property (gobject_class, PROP_RC_DROPFRAME_THRESH,
385       g_param_spec_int ("dropframe-threshold", "Drop Frame Threshold",
386           "Temporal resampling threshold (buf %)",
387           0, 100, DEFAULT_RC_DROPFRAME_THRESH,
388           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
389 
390   g_object_class_install_property (gobject_class, PROP_RC_RESIZE_ALLOWED,
391       g_param_spec_boolean ("resize-allowed", "Resize Allowed",
392           "Allow spatial resampling",
393           DEFAULT_RC_RESIZE_ALLOWED,
394           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
395 
396   g_object_class_install_property (gobject_class, PROP_RC_RESIZE_UP_THRESH,
397       g_param_spec_int ("resize-up-threshold", "Resize Up Threshold",
398           "Upscale threshold (buf %)",
399           0, 100, DEFAULT_RC_RESIZE_UP_THRESH,
400           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
401 
402   g_object_class_install_property (gobject_class, PROP_RC_RESIZE_DOWN_THRESH,
403       g_param_spec_int ("resize-down-threshold", "Resize Down Threshold",
404           "Downscale threshold (buf %)",
405           0, 100, DEFAULT_RC_RESIZE_DOWN_THRESH,
406           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
407 
408   g_object_class_install_property (gobject_class, PROP_RC_UNDERSHOOT_PCT,
409       g_param_spec_int ("undershoot", "Undershoot PCT",
410           "Datarate undershoot (min) target (%)",
411           0, 1000, DEFAULT_RC_UNDERSHOOT_PCT,
412           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
413 
414   g_object_class_install_property (gobject_class, PROP_RC_OVERSHOOT_PCT,
415       g_param_spec_int ("overshoot", "Overshoot PCT",
416           "Datarate overshoot (max) target (%)",
417           0, 1000, DEFAULT_RC_OVERSHOOT_PCT,
418           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
419 
420   g_object_class_install_property (gobject_class, PROP_RC_BUF_SZ,
421       g_param_spec_int ("buffer-size", "Buffer size",
422           "Client buffer size (ms)",
423           0, G_MAXINT, DEFAULT_RC_BUF_SZ,
424           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
425 
426   g_object_class_install_property (gobject_class, PROP_RC_BUF_INITIAL_SZ,
427       g_param_spec_int ("buffer-initial-size", "Buffer initial size",
428           "Initial client buffer size (ms)",
429           0, G_MAXINT, DEFAULT_RC_BUF_INITIAL_SZ,
430           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
431 
432   g_object_class_install_property (gobject_class, PROP_RC_BUF_OPTIMAL_SZ,
433       g_param_spec_int ("buffer-optimal-size", "Buffer optimal size",
434           "Optimal client buffer size (ms)",
435           0, G_MAXINT, DEFAULT_RC_BUF_OPTIMAL_SZ,
436           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
437 
438   g_object_class_install_property (gobject_class, PROP_RC_2PASS_VBR_BIAS_PCT,
439       g_param_spec_int ("twopass-vbr-bias", "2-pass VBR bias",
440           "CBR/VBR bias (0=CBR, 100=VBR)",
441           0, 100, DEFAULT_RC_2PASS_VBR_BIAS_PCT,
442           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
443 
444   g_object_class_install_property (gobject_class,
445       PROP_RC_2PASS_VBR_MINSECTION_PCT,
446       g_param_spec_int ("twopass-vbr-minsection", "2-pass GOP min bitrate",
447           "GOP minimum bitrate (% target)", 0, G_MAXINT,
448           DEFAULT_RC_2PASS_VBR_MINSECTION_PCT,
449           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
450 
451   g_object_class_install_property (gobject_class,
452       PROP_RC_2PASS_VBR_MAXSECTION_PCT,
453       g_param_spec_int ("twopass-vbr-maxsection", "2-pass GOP max bitrate",
454           "GOP maximum bitrate (% target)", 0, G_MAXINT,
455           DEFAULT_RC_2PASS_VBR_MINSECTION_PCT,
456           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
457 
458   g_object_class_install_property (gobject_class, PROP_KF_MODE,
459       g_param_spec_enum ("keyframe-mode", "Keyframe Mode",
460           "Keyframe placement",
461           GST_VPX_ENC_KF_MODE_TYPE, DEFAULT_KF_MODE,
462           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
463 
464   g_object_class_install_property (gobject_class, PROP_KF_MAX_DIST,
465       g_param_spec_int ("keyframe-max-dist", "Keyframe max distance",
466           "Maximum distance between keyframes (number of frames)",
467           0, G_MAXINT, DEFAULT_KF_MAX_DIST,
468           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
469 
470   g_object_class_install_property (gobject_class, PROP_MULTIPASS_MODE,
471       g_param_spec_enum ("multipass-mode", "Multipass Mode",
472           "Multipass encode mode",
473           GST_VPX_ENC_MULTIPASS_MODE_TYPE, DEFAULT_MULTIPASS_MODE,
474           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
475 
476   g_object_class_install_property (gobject_class, PROP_MULTIPASS_CACHE_FILE,
477       g_param_spec_string ("multipass-cache-file", "Multipass Cache File",
478           "Multipass cache file. "
479           "If stream caps reinited, multiple files will be created: "
480           "file, file.1, file.2, ... and so on.",
481           DEFAULT_MULTIPASS_CACHE_FILE,
482           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
483 
484   g_object_class_install_property (gobject_class, PROP_TS_NUMBER_LAYERS,
485       g_param_spec_int ("temporal-scalability-number-layers",
486           "Number of coding layers", "Number of coding layers to use", 1, 5,
487           DEFAULT_TS_NUMBER_LAYERS,
488           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
489 
490   g_object_class_install_property (gobject_class, PROP_TS_TARGET_BITRATE,
491       g_param_spec_value_array ("temporal-scalability-target-bitrate",
492           "Coding layer target bitrates",
493           "Target bitrates for coding layers (one per layer, decreasing)",
494           g_param_spec_int ("target-bitrate", "Target bitrate",
495               "Target bitrate", 0, G_MAXINT, DEFAULT_RC_TARGET_BITRATE,
496               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
497           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
498 
499   g_object_class_install_property (gobject_class, PROP_TS_RATE_DECIMATOR,
500       g_param_spec_value_array ("temporal-scalability-rate-decimator",
501           "Coding layer rate decimator",
502           "Rate decimation factors for each layer",
503           g_param_spec_int ("rate-decimator", "Rate decimator",
504               "Rate decimator", 0, 1000000000, 0,
505               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
506           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
507 
508   g_object_class_install_property (gobject_class, PROP_TS_PERIODICITY,
509       g_param_spec_int ("temporal-scalability-periodicity",
510           "Coding layer periodicity",
511           "Length of sequence that defines layer membership periodicity", 0, 16,
512           DEFAULT_TS_PERIODICITY,
513           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
514 
515   g_object_class_install_property (gobject_class, PROP_TS_LAYER_ID,
516       g_param_spec_value_array ("temporal-scalability-layer-id",
517           "Coding layer identification",
518           "Sequence defining coding layer membership",
519           g_param_spec_int ("layer-id", "Layer ID", "Layer ID", 0, 4, 0,
520               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
521           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
522 
523   g_object_class_install_property (gobject_class, PROP_LAG_IN_FRAMES,
524       g_param_spec_int ("lag-in-frames", "Lag in frames",
525           "Maximum number of frames to lag",
526           0, 25, DEFAULT_LAG_IN_FRAMES,
527           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
528 
529   g_object_class_install_property (gobject_class, PROP_ERROR_RESILIENT,
530       g_param_spec_flags ("error-resilient", "Error resilient",
531           "Error resilience flags",
532           GST_VPX_ENC_ER_FLAGS_TYPE, DEFAULT_ERROR_RESILIENT,
533           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
534 
535   g_object_class_install_property (gobject_class, PROP_THREADS,
536       g_param_spec_int ("threads", "Threads",
537           "Number of threads to use",
538           0, 64, DEFAULT_THREADS,
539           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
540 
541   g_object_class_install_property (gobject_class, PROP_DEADLINE,
542       g_param_spec_int64 ("deadline", "Deadline",
543           "Deadline per frame (usec, 0=disabled)",
544           0, G_MAXINT64, DEFAULT_DEADLINE,
545           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
546 
547   g_object_class_install_property (gobject_class, PROP_H_SCALING_MODE,
548       g_param_spec_enum ("horizontal-scaling-mode", "Horizontal scaling mode",
549           "Horizontal scaling mode",
550           GST_VPX_ENC_SCALING_MODE_TYPE, DEFAULT_H_SCALING_MODE,
551           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
552 
553   g_object_class_install_property (gobject_class, PROP_V_SCALING_MODE,
554       g_param_spec_enum ("vertical-scaling-mode", "Vertical scaling mode",
555           "Vertical scaling mode",
556           GST_VPX_ENC_SCALING_MODE_TYPE, DEFAULT_V_SCALING_MODE,
557           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
558 
559   g_object_class_install_property (gobject_class, PROP_CPU_USED,
560       g_param_spec_int ("cpu-used", "CPU used",
561           "CPU used",
562           -16, 16, DEFAULT_CPU_USED,
563           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
564 
565   g_object_class_install_property (gobject_class, PROP_ENABLE_AUTO_ALT_REF,
566       g_param_spec_boolean ("auto-alt-ref", "Auto alt reference frames",
567           "Automatically generate AltRef frames",
568           DEFAULT_ENABLE_AUTO_ALT_REF,
569           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
570 
571   g_object_class_install_property (gobject_class, PROP_NOISE_SENSITIVITY,
572       g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
573           "Noise sensisivity (frames to blur)",
574           0, 6, DEFAULT_NOISE_SENSITIVITY,
575           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
576 
577   g_object_class_install_property (gobject_class, PROP_SHARPNESS,
578       g_param_spec_int ("sharpness", "Sharpness",
579           "Filter sharpness",
580           0, 7, DEFAULT_SHARPNESS,
581           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
582 
583   g_object_class_install_property (gobject_class, PROP_STATIC_THRESHOLD,
584       g_param_spec_int ("static-threshold", "Static Threshold",
585           "Motion detection threshold",
586           0, G_MAXINT, DEFAULT_STATIC_THRESHOLD,
587           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
588 
589   g_object_class_install_property (gobject_class, PROP_TOKEN_PARTITIONS,
590       g_param_spec_enum ("token-partitions", "Token partitions",
591           "Number of token partitions",
592           GST_VPX_ENC_TOKEN_PARTITIONS_TYPE, DEFAULT_TOKEN_PARTITIONS,
593           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
594 
595   g_object_class_install_property (gobject_class, PROP_ARNR_MAXFRAMES,
596       g_param_spec_int ("arnr-maxframes", "AltRef max frames",
597           "AltRef maximum number of frames",
598           0, 15, DEFAULT_ARNR_MAXFRAMES,
599           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
600 
601   g_object_class_install_property (gobject_class, PROP_ARNR_STRENGTH,
602       g_param_spec_int ("arnr-strength", "AltRef strength",
603           "AltRef strength",
604           0, 6, DEFAULT_ARNR_STRENGTH,
605           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
606 
607   g_object_class_install_property (gobject_class, PROP_ARNR_TYPE,
608       g_param_spec_int ("arnr-type", "AltRef type",
609           "AltRef type",
610           1, 3, DEFAULT_ARNR_TYPE,
611           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
612               G_PARAM_DEPRECATED)));
613 
614   g_object_class_install_property (gobject_class, PROP_TUNING,
615       g_param_spec_enum ("tuning", "Tuning",
616           "Tuning",
617           GST_VPX_ENC_TUNING_TYPE, DEFAULT_TUNING,
618           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
619 
620   g_object_class_install_property (gobject_class, PROP_CQ_LEVEL,
621       g_param_spec_int ("cq-level", "Constrained quality level",
622           "Constrained quality level",
623           0, 63, DEFAULT_CQ_LEVEL,
624           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
625 
626   g_object_class_install_property (gobject_class, PROP_MAX_INTRA_BITRATE_PCT,
627       g_param_spec_int ("max-intra-bitrate", "Max Intra bitrate",
628           "Maximum Intra frame bitrate",
629           0, G_MAXINT, DEFAULT_MAX_INTRA_BITRATE_PCT,
630           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
631 
632   g_object_class_install_property (gobject_class, PROP_TIMEBASE,
633       gst_param_spec_fraction ("timebase", "Shortest interframe time",
634           "Fraction of one second that is the shortest interframe time - normally left as zero which will default to the framerate",
635           0, 1, G_MAXINT, 1, DEFAULT_TIMEBASE_N, DEFAULT_TIMEBASE_D,
636           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
637 
638   GST_DEBUG_CATEGORY_INIT (gst_vpxenc_debug, "vpxenc", 0, "VPX Encoder");
639 }
640 
641 static void
gst_vpx_enc_init(GstVPXEnc * gst_vpx_enc)642 gst_vpx_enc_init (GstVPXEnc * gst_vpx_enc)
643 {
644   GST_DEBUG_OBJECT (gst_vpx_enc, "init");
645   GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (gst_vpx_enc));
646 
647   gst_vpx_enc->cfg.rc_end_usage = DEFAULT_RC_END_USAGE;
648   gst_vpx_enc->cfg.rc_target_bitrate = DEFAULT_RC_TARGET_BITRATE / 1000;
649   gst_vpx_enc->rc_target_bitrate_set = FALSE;
650   gst_vpx_enc->cfg.rc_min_quantizer = DEFAULT_RC_MIN_QUANTIZER;
651   gst_vpx_enc->cfg.rc_max_quantizer = DEFAULT_RC_MAX_QUANTIZER;
652   gst_vpx_enc->cfg.rc_dropframe_thresh = DEFAULT_RC_DROPFRAME_THRESH;
653   gst_vpx_enc->cfg.rc_resize_allowed = DEFAULT_RC_RESIZE_ALLOWED;
654   gst_vpx_enc->cfg.rc_resize_up_thresh = DEFAULT_RC_RESIZE_UP_THRESH;
655   gst_vpx_enc->cfg.rc_resize_down_thresh = DEFAULT_RC_RESIZE_DOWN_THRESH;
656   gst_vpx_enc->cfg.rc_undershoot_pct = DEFAULT_RC_UNDERSHOOT_PCT;
657   gst_vpx_enc->cfg.rc_overshoot_pct = DEFAULT_RC_OVERSHOOT_PCT;
658   gst_vpx_enc->cfg.rc_buf_sz = DEFAULT_RC_BUF_SZ;
659   gst_vpx_enc->cfg.rc_buf_initial_sz = DEFAULT_RC_BUF_INITIAL_SZ;
660   gst_vpx_enc->cfg.rc_buf_optimal_sz = DEFAULT_RC_BUF_OPTIMAL_SZ;
661   gst_vpx_enc->cfg.rc_2pass_vbr_bias_pct = DEFAULT_RC_2PASS_VBR_BIAS_PCT;
662   gst_vpx_enc->cfg.rc_2pass_vbr_minsection_pct =
663       DEFAULT_RC_2PASS_VBR_MINSECTION_PCT;
664   gst_vpx_enc->cfg.rc_2pass_vbr_maxsection_pct =
665       DEFAULT_RC_2PASS_VBR_MAXSECTION_PCT;
666   gst_vpx_enc->cfg.kf_mode = DEFAULT_KF_MODE;
667   gst_vpx_enc->cfg.kf_max_dist = DEFAULT_KF_MAX_DIST;
668   gst_vpx_enc->cfg.g_pass = DEFAULT_MULTIPASS_MODE;
669   gst_vpx_enc->multipass_cache_prefix = g_strdup (DEFAULT_MULTIPASS_CACHE_FILE);
670   gst_vpx_enc->multipass_cache_file = NULL;
671   gst_vpx_enc->multipass_cache_idx = 0;
672   gst_vpx_enc->cfg.ts_number_layers = DEFAULT_TS_NUMBER_LAYERS;
673   gst_vpx_enc->n_ts_target_bitrate = 0;
674   gst_vpx_enc->n_ts_rate_decimator = 0;
675   gst_vpx_enc->cfg.ts_periodicity = DEFAULT_TS_PERIODICITY;
676   gst_vpx_enc->n_ts_layer_id = 0;
677   gst_vpx_enc->cfg.g_error_resilient = DEFAULT_ERROR_RESILIENT;
678   gst_vpx_enc->cfg.g_lag_in_frames = DEFAULT_LAG_IN_FRAMES;
679   gst_vpx_enc->cfg.g_threads = DEFAULT_THREADS;
680   gst_vpx_enc->deadline = DEFAULT_DEADLINE;
681   gst_vpx_enc->h_scaling_mode = DEFAULT_H_SCALING_MODE;
682   gst_vpx_enc->v_scaling_mode = DEFAULT_V_SCALING_MODE;
683   gst_vpx_enc->cpu_used = DEFAULT_CPU_USED;
684   gst_vpx_enc->enable_auto_alt_ref = DEFAULT_ENABLE_AUTO_ALT_REF;
685   gst_vpx_enc->noise_sensitivity = DEFAULT_NOISE_SENSITIVITY;
686   gst_vpx_enc->sharpness = DEFAULT_SHARPNESS;
687   gst_vpx_enc->static_threshold = DEFAULT_STATIC_THRESHOLD;
688   gst_vpx_enc->token_partitions = DEFAULT_TOKEN_PARTITIONS;
689   gst_vpx_enc->arnr_maxframes = DEFAULT_ARNR_MAXFRAMES;
690   gst_vpx_enc->arnr_strength = DEFAULT_ARNR_STRENGTH;
691   gst_vpx_enc->arnr_type = DEFAULT_ARNR_TYPE;
692   gst_vpx_enc->tuning = DEFAULT_TUNING;
693   gst_vpx_enc->cq_level = DEFAULT_CQ_LEVEL;
694   gst_vpx_enc->max_intra_bitrate_pct = DEFAULT_MAX_INTRA_BITRATE_PCT;
695   gst_vpx_enc->timebase_n = DEFAULT_TIMEBASE_N;
696   gst_vpx_enc->timebase_d = DEFAULT_TIMEBASE_D;
697 
698   gst_vpx_enc->cfg.g_profile = DEFAULT_PROFILE;
699 
700   g_mutex_init (&gst_vpx_enc->encoder_lock);
701 }
702 
703 static void
gst_vpx_enc_finalize(GObject * object)704 gst_vpx_enc_finalize (GObject * object)
705 {
706   GstVPXEnc *gst_vpx_enc;
707 
708   GST_DEBUG_OBJECT (object, "finalize");
709 
710   g_return_if_fail (GST_IS_VPX_ENC (object));
711   gst_vpx_enc = GST_VPX_ENC (object);
712 
713   g_free (gst_vpx_enc->multipass_cache_prefix);
714   g_free (gst_vpx_enc->multipass_cache_file);
715   gst_vpx_enc->multipass_cache_idx = 0;
716 
717 
718   if (gst_vpx_enc->input_state)
719     gst_video_codec_state_unref (gst_vpx_enc->input_state);
720 
721   g_mutex_clear (&gst_vpx_enc->encoder_lock);
722 
723   G_OBJECT_CLASS (parent_class)->finalize (object);
724 }
725 
726 static void
gst_vpx_enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)727 gst_vpx_enc_set_property (GObject * object, guint prop_id,
728     const GValue * value, GParamSpec * pspec)
729 {
730   GstVPXEnc *gst_vpx_enc;
731   gboolean global = FALSE;
732   vpx_codec_err_t status;
733 
734   g_return_if_fail (GST_IS_VPX_ENC (object));
735   gst_vpx_enc = GST_VPX_ENC (object);
736 
737   GST_DEBUG_OBJECT (object, "gst_vpx_enc_set_property");
738   g_mutex_lock (&gst_vpx_enc->encoder_lock);
739   switch (prop_id) {
740     case PROP_RC_END_USAGE:
741       gst_vpx_enc->cfg.rc_end_usage = g_value_get_enum (value);
742       global = TRUE;
743       break;
744     case PROP_RC_TARGET_BITRATE:
745       gst_vpx_enc->cfg.rc_target_bitrate = g_value_get_int (value) / 1000;
746       gst_vpx_enc->rc_target_bitrate_set = TRUE;
747       global = TRUE;
748       break;
749     case PROP_RC_MIN_QUANTIZER:
750       gst_vpx_enc->cfg.rc_min_quantizer = g_value_get_int (value);
751       global = TRUE;
752       break;
753     case PROP_RC_MAX_QUANTIZER:
754       gst_vpx_enc->cfg.rc_max_quantizer = g_value_get_int (value);
755       global = TRUE;
756       break;
757     case PROP_RC_DROPFRAME_THRESH:
758       gst_vpx_enc->cfg.rc_dropframe_thresh = g_value_get_int (value);
759       global = TRUE;
760       break;
761     case PROP_RC_RESIZE_ALLOWED:
762       gst_vpx_enc->cfg.rc_resize_allowed = g_value_get_boolean (value);
763       global = TRUE;
764       break;
765     case PROP_RC_RESIZE_UP_THRESH:
766       gst_vpx_enc->cfg.rc_resize_up_thresh = g_value_get_int (value);
767       global = TRUE;
768       break;
769     case PROP_RC_RESIZE_DOWN_THRESH:
770       gst_vpx_enc->cfg.rc_resize_down_thresh = g_value_get_int (value);
771       global = TRUE;
772       break;
773     case PROP_RC_UNDERSHOOT_PCT:
774       gst_vpx_enc->cfg.rc_undershoot_pct = g_value_get_int (value);
775       global = TRUE;
776       break;
777     case PROP_RC_OVERSHOOT_PCT:
778       gst_vpx_enc->cfg.rc_overshoot_pct = g_value_get_int (value);
779       global = TRUE;
780       break;
781     case PROP_RC_BUF_SZ:
782       gst_vpx_enc->cfg.rc_buf_sz = g_value_get_int (value);
783       global = TRUE;
784       break;
785     case PROP_RC_BUF_INITIAL_SZ:
786       gst_vpx_enc->cfg.rc_buf_initial_sz = g_value_get_int (value);
787       global = TRUE;
788       break;
789     case PROP_RC_BUF_OPTIMAL_SZ:
790       gst_vpx_enc->cfg.rc_buf_optimal_sz = g_value_get_int (value);
791       global = TRUE;
792       break;
793     case PROP_RC_2PASS_VBR_BIAS_PCT:
794       gst_vpx_enc->cfg.rc_2pass_vbr_bias_pct = g_value_get_int (value);
795       global = TRUE;
796       break;
797     case PROP_RC_2PASS_VBR_MINSECTION_PCT:
798       gst_vpx_enc->cfg.rc_2pass_vbr_minsection_pct = g_value_get_int (value);
799       global = TRUE;
800       break;
801     case PROP_RC_2PASS_VBR_MAXSECTION_PCT:
802       gst_vpx_enc->cfg.rc_2pass_vbr_maxsection_pct = g_value_get_int (value);
803       global = TRUE;
804       break;
805     case PROP_KF_MODE:
806       gst_vpx_enc->cfg.kf_mode = g_value_get_enum (value);
807       global = TRUE;
808       break;
809     case PROP_KF_MAX_DIST:
810       gst_vpx_enc->cfg.kf_max_dist = g_value_get_int (value);
811       global = TRUE;
812       break;
813     case PROP_MULTIPASS_MODE:
814       gst_vpx_enc->cfg.g_pass = g_value_get_enum (value);
815       global = TRUE;
816       break;
817     case PROP_MULTIPASS_CACHE_FILE:
818       if (gst_vpx_enc->multipass_cache_prefix)
819         g_free (gst_vpx_enc->multipass_cache_prefix);
820       gst_vpx_enc->multipass_cache_prefix = g_value_dup_string (value);
821       break;
822     case PROP_TS_NUMBER_LAYERS:
823       gst_vpx_enc->cfg.ts_number_layers = g_value_get_int (value);
824       global = TRUE;
825       break;
826     case PROP_TS_TARGET_BITRATE:{
827       GValueArray *va = g_value_get_boxed (value);
828 
829       memset (&gst_vpx_enc->cfg.ts_target_bitrate, 0,
830           sizeof (gst_vpx_enc->cfg.ts_target_bitrate));
831       if (va == NULL) {
832         gst_vpx_enc->n_ts_target_bitrate = 0;
833       } else if (va->n_values > VPX_TS_MAX_LAYERS) {
834         g_warning ("%s: Only %d layers allowed at maximum",
835             GST_ELEMENT_NAME (gst_vpx_enc), VPX_TS_MAX_LAYERS);
836       } else {
837         gint i;
838 
839         for (i = 0; i < va->n_values; i++)
840           gst_vpx_enc->cfg.ts_target_bitrate[i] =
841               g_value_get_int (g_value_array_get_nth (va, i));
842         gst_vpx_enc->n_ts_target_bitrate = va->n_values;
843       }
844       global = TRUE;
845       break;
846     }
847     case PROP_TS_RATE_DECIMATOR:{
848       GValueArray *va = g_value_get_boxed (value);
849 
850       memset (&gst_vpx_enc->cfg.ts_rate_decimator, 0,
851           sizeof (gst_vpx_enc->cfg.ts_rate_decimator));
852       if (va == NULL) {
853         gst_vpx_enc->n_ts_rate_decimator = 0;
854       } else if (va->n_values > VPX_TS_MAX_LAYERS) {
855         g_warning ("%s: Only %d layers allowed at maximum",
856             GST_ELEMENT_NAME (gst_vpx_enc), VPX_TS_MAX_LAYERS);
857       } else {
858         gint i;
859 
860         for (i = 0; i < va->n_values; i++)
861           gst_vpx_enc->cfg.ts_rate_decimator[i] =
862               g_value_get_int (g_value_array_get_nth (va, i));
863         gst_vpx_enc->n_ts_rate_decimator = va->n_values;
864       }
865       global = TRUE;
866       break;
867     }
868     case PROP_TS_PERIODICITY:
869       gst_vpx_enc->cfg.ts_periodicity = g_value_get_int (value);
870       global = TRUE;
871       break;
872     case PROP_TS_LAYER_ID:{
873       GValueArray *va = g_value_get_boxed (value);
874 
875       memset (&gst_vpx_enc->cfg.ts_layer_id, 0,
876           sizeof (gst_vpx_enc->cfg.ts_layer_id));
877       if (va && va->n_values > VPX_TS_MAX_PERIODICITY) {
878         g_warning ("%s: Only %d sized layer sequences allowed at maximum",
879             GST_ELEMENT_NAME (gst_vpx_enc), VPX_TS_MAX_PERIODICITY);
880       } else if (va) {
881         gint i;
882 
883         for (i = 0; i < va->n_values; i++)
884           gst_vpx_enc->cfg.ts_layer_id[i] =
885               g_value_get_int (g_value_array_get_nth (va, i));
886         gst_vpx_enc->n_ts_layer_id = va->n_values;
887       } else {
888         gst_vpx_enc->n_ts_layer_id = 0;
889       }
890       global = TRUE;
891       break;
892     }
893     case PROP_ERROR_RESILIENT:
894       gst_vpx_enc->cfg.g_error_resilient = g_value_get_flags (value);
895       global = TRUE;
896       break;
897     case PROP_LAG_IN_FRAMES:
898       gst_vpx_enc->cfg.g_lag_in_frames = g_value_get_int (value);
899       global = TRUE;
900       break;
901     case PROP_THREADS:
902       gst_vpx_enc->cfg.g_threads = g_value_get_int (value);
903       global = TRUE;
904       break;
905     case PROP_DEADLINE:
906       gst_vpx_enc->deadline = g_value_get_int64 (value);
907       break;
908     case PROP_H_SCALING_MODE:
909       gst_vpx_enc->h_scaling_mode = g_value_get_enum (value);
910       if (gst_vpx_enc->inited) {
911         vpx_scaling_mode_t sm;
912 
913         sm.h_scaling_mode = gst_vpx_enc->h_scaling_mode;
914         sm.v_scaling_mode = gst_vpx_enc->v_scaling_mode;
915 
916         status =
917             vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_SCALEMODE, &sm);
918         if (status != VPX_CODEC_OK) {
919           GST_WARNING_OBJECT (gst_vpx_enc,
920               "Failed to set VP8E_SET_SCALEMODE: %s",
921               gst_vpx_error_name (status));
922         }
923       }
924       break;
925     case PROP_V_SCALING_MODE:
926       gst_vpx_enc->v_scaling_mode = g_value_get_enum (value);
927       if (gst_vpx_enc->inited) {
928         vpx_scaling_mode_t sm;
929 
930         sm.h_scaling_mode = gst_vpx_enc->h_scaling_mode;
931         sm.v_scaling_mode = gst_vpx_enc->v_scaling_mode;
932 
933         status =
934             vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_SCALEMODE, &sm);
935         if (status != VPX_CODEC_OK) {
936           GST_WARNING_OBJECT (gst_vpx_enc,
937               "Failed to set VP8E_SET_SCALEMODE: %s",
938               gst_vpx_error_name (status));
939         }
940       }
941       break;
942     case PROP_CPU_USED:
943       gst_vpx_enc->cpu_used = g_value_get_int (value);
944       if (gst_vpx_enc->inited) {
945         status =
946             vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_CPUUSED,
947             gst_vpx_enc->cpu_used);
948         if (status != VPX_CODEC_OK) {
949           GST_WARNING_OBJECT (gst_vpx_enc, "Failed to set VP8E_SET_CPUUSED: %s",
950               gst_vpx_error_name (status));
951         }
952       }
953       break;
954     case PROP_ENABLE_AUTO_ALT_REF:
955       gst_vpx_enc->enable_auto_alt_ref = g_value_get_boolean (value);
956       if (gst_vpx_enc->inited) {
957         status =
958             vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_ENABLEAUTOALTREF,
959             (gst_vpx_enc->enable_auto_alt_ref ? 1 : 0));
960         if (status != VPX_CODEC_OK) {
961           GST_WARNING_OBJECT (gst_vpx_enc,
962               "Failed to set VP8E_SET_ENABLEAUTOALTREF: %s",
963               gst_vpx_error_name (status));
964         }
965       }
966       break;
967     case PROP_NOISE_SENSITIVITY:
968       gst_vpx_enc->noise_sensitivity = g_value_get_int (value);
969       if (gst_vpx_enc->inited) {
970         status =
971             vpx_codec_control (&gst_vpx_enc->encoder,
972             VP8E_SET_NOISE_SENSITIVITY, gst_vpx_enc->noise_sensitivity);
973         if (status != VPX_CODEC_OK) {
974           GST_WARNING_OBJECT (gst_vpx_enc,
975               "Failed to set VP8E_SET_NOISE_SENSITIVITY: %s",
976               gst_vpx_error_name (status));
977         }
978       }
979       break;
980     case PROP_SHARPNESS:
981       gst_vpx_enc->sharpness = g_value_get_int (value);
982       if (gst_vpx_enc->inited) {
983         status = vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_SHARPNESS,
984             gst_vpx_enc->sharpness);
985         if (status != VPX_CODEC_OK) {
986           GST_WARNING_OBJECT (gst_vpx_enc,
987               "Failed to set VP8E_SET_SHARPNESS: %s",
988               gst_vpx_error_name (status));
989         }
990       }
991       break;
992     case PROP_STATIC_THRESHOLD:
993       gst_vpx_enc->static_threshold = g_value_get_int (value);
994       if (gst_vpx_enc->inited) {
995         status =
996             vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_STATIC_THRESHOLD,
997             gst_vpx_enc->static_threshold);
998         if (status != VPX_CODEC_OK) {
999           GST_WARNING_OBJECT (gst_vpx_enc,
1000               "Failed to set VP8E_SET_STATIC_THRESHOLD: %s",
1001               gst_vpx_error_name (status));
1002         }
1003       }
1004       break;
1005     case PROP_TOKEN_PARTITIONS:
1006       gst_vpx_enc->token_partitions = g_value_get_enum (value);
1007       if (gst_vpx_enc->inited) {
1008         status =
1009             vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_TOKEN_PARTITIONS,
1010             gst_vpx_enc->token_partitions);
1011         if (status != VPX_CODEC_OK) {
1012           GST_WARNING_OBJECT (gst_vpx_enc,
1013               "Failed to set VP8E_SET_TOKEN_PARTIONS: %s",
1014               gst_vpx_error_name (status));
1015         }
1016       }
1017       break;
1018     case PROP_ARNR_MAXFRAMES:
1019       gst_vpx_enc->arnr_maxframes = g_value_get_int (value);
1020       if (gst_vpx_enc->inited) {
1021         status =
1022             vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_ARNR_MAXFRAMES,
1023             gst_vpx_enc->arnr_maxframes);
1024         if (status != VPX_CODEC_OK) {
1025           GST_WARNING_OBJECT (gst_vpx_enc,
1026               "Failed to set VP8E_SET_ARNR_MAXFRAMES: %s",
1027               gst_vpx_error_name (status));
1028         }
1029       }
1030       break;
1031     case PROP_ARNR_STRENGTH:
1032       gst_vpx_enc->arnr_strength = g_value_get_int (value);
1033       if (gst_vpx_enc->inited) {
1034         status =
1035             vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_ARNR_STRENGTH,
1036             gst_vpx_enc->arnr_strength);
1037         if (status != VPX_CODEC_OK) {
1038           GST_WARNING_OBJECT (gst_vpx_enc,
1039               "Failed to set VP8E_SET_ARNR_STRENGTH: %s",
1040               gst_vpx_error_name (status));
1041         }
1042       }
1043       break;
1044     case PROP_ARNR_TYPE:
1045       gst_vpx_enc->arnr_type = g_value_get_int (value);
1046       g_warning ("arnr-type is a no-op since control has been deprecated "
1047           "in libvpx");
1048       break;
1049     case PROP_TUNING:
1050       gst_vpx_enc->tuning = g_value_get_enum (value);
1051       if (gst_vpx_enc->inited) {
1052         status = vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_TUNING,
1053             gst_vpx_enc->tuning);
1054         if (status != VPX_CODEC_OK) {
1055           GST_WARNING_OBJECT (gst_vpx_enc,
1056               "Failed to set VP8E_SET_TUNING: %s", gst_vpx_error_name (status));
1057         }
1058       }
1059       break;
1060     case PROP_CQ_LEVEL:
1061       gst_vpx_enc->cq_level = g_value_get_int (value);
1062       if (gst_vpx_enc->inited) {
1063         status = vpx_codec_control (&gst_vpx_enc->encoder, VP8E_SET_CQ_LEVEL,
1064             gst_vpx_enc->cq_level);
1065         if (status != VPX_CODEC_OK) {
1066           GST_WARNING_OBJECT (gst_vpx_enc,
1067               "Failed to set VP8E_SET_CQ_LEVEL: %s",
1068               gst_vpx_error_name (status));
1069         }
1070       }
1071       break;
1072     case PROP_MAX_INTRA_BITRATE_PCT:
1073       gst_vpx_enc->max_intra_bitrate_pct = g_value_get_int (value);
1074       if (gst_vpx_enc->inited) {
1075         status =
1076             vpx_codec_control (&gst_vpx_enc->encoder,
1077             VP8E_SET_MAX_INTRA_BITRATE_PCT, gst_vpx_enc->max_intra_bitrate_pct);
1078         if (status != VPX_CODEC_OK) {
1079           GST_WARNING_OBJECT (gst_vpx_enc,
1080               "Failed to set VP8E_SET_MAX_INTRA_BITRATE_PCT: %s",
1081               gst_vpx_error_name (status));
1082         }
1083       }
1084       break;
1085     case PROP_TIMEBASE:
1086       gst_vpx_enc->timebase_n = gst_value_get_fraction_numerator (value);
1087       gst_vpx_enc->timebase_d = gst_value_get_fraction_denominator (value);
1088       break;
1089     default:
1090       break;
1091   }
1092 
1093   if (global &&gst_vpx_enc->inited) {
1094     status =
1095         vpx_codec_enc_config_set (&gst_vpx_enc->encoder, &gst_vpx_enc->cfg);
1096     if (status != VPX_CODEC_OK) {
1097       g_mutex_unlock (&gst_vpx_enc->encoder_lock);
1098       GST_ELEMENT_ERROR (gst_vpx_enc, LIBRARY, INIT,
1099           ("Failed to set encoder configuration"), ("%s",
1100               gst_vpx_error_name (status)));
1101     } else {
1102       g_mutex_unlock (&gst_vpx_enc->encoder_lock);
1103     }
1104   } else {
1105     g_mutex_unlock (&gst_vpx_enc->encoder_lock);
1106   }
1107 }
1108 
1109 static void
gst_vpx_enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1110 gst_vpx_enc_get_property (GObject * object, guint prop_id, GValue * value,
1111     GParamSpec * pspec)
1112 {
1113   GstVPXEnc *gst_vpx_enc;
1114 
1115   g_return_if_fail (GST_IS_VPX_ENC (object));
1116   gst_vpx_enc = GST_VPX_ENC (object);
1117 
1118   g_mutex_lock (&gst_vpx_enc->encoder_lock);
1119   switch (prop_id) {
1120     case PROP_RC_END_USAGE:
1121       g_value_set_enum (value, gst_vpx_enc->cfg.rc_end_usage);
1122       break;
1123     case PROP_RC_TARGET_BITRATE:
1124       g_value_set_int (value, gst_vpx_enc->cfg.rc_target_bitrate * 1000);
1125       break;
1126     case PROP_RC_MIN_QUANTIZER:
1127       g_value_set_int (value, gst_vpx_enc->cfg.rc_min_quantizer);
1128       break;
1129     case PROP_RC_MAX_QUANTIZER:
1130       g_value_set_int (value, gst_vpx_enc->cfg.rc_max_quantizer);
1131       break;
1132     case PROP_RC_DROPFRAME_THRESH:
1133       g_value_set_int (value, gst_vpx_enc->cfg.rc_dropframe_thresh);
1134       break;
1135     case PROP_RC_RESIZE_ALLOWED:
1136       g_value_set_boolean (value, gst_vpx_enc->cfg.rc_resize_allowed);
1137       break;
1138     case PROP_RC_RESIZE_UP_THRESH:
1139       g_value_set_int (value, gst_vpx_enc->cfg.rc_resize_up_thresh);
1140       break;
1141     case PROP_RC_RESIZE_DOWN_THRESH:
1142       g_value_set_int (value, gst_vpx_enc->cfg.rc_resize_down_thresh);
1143       break;
1144     case PROP_RC_UNDERSHOOT_PCT:
1145       g_value_set_int (value, gst_vpx_enc->cfg.rc_undershoot_pct);
1146       break;
1147     case PROP_RC_OVERSHOOT_PCT:
1148       g_value_set_int (value, gst_vpx_enc->cfg.rc_overshoot_pct);
1149       break;
1150     case PROP_RC_BUF_SZ:
1151       g_value_set_int (value, gst_vpx_enc->cfg.rc_buf_sz);
1152       break;
1153     case PROP_RC_BUF_INITIAL_SZ:
1154       g_value_set_int (value, gst_vpx_enc->cfg.rc_buf_initial_sz);
1155       break;
1156     case PROP_RC_BUF_OPTIMAL_SZ:
1157       g_value_set_int (value, gst_vpx_enc->cfg.rc_buf_optimal_sz);
1158       break;
1159     case PROP_RC_2PASS_VBR_BIAS_PCT:
1160       g_value_set_int (value, gst_vpx_enc->cfg.rc_2pass_vbr_bias_pct);
1161       break;
1162     case PROP_RC_2PASS_VBR_MINSECTION_PCT:
1163       g_value_set_int (value, gst_vpx_enc->cfg.rc_2pass_vbr_minsection_pct);
1164       break;
1165     case PROP_RC_2PASS_VBR_MAXSECTION_PCT:
1166       g_value_set_int (value, gst_vpx_enc->cfg.rc_2pass_vbr_maxsection_pct);
1167       break;
1168     case PROP_KF_MODE:
1169       g_value_set_enum (value, gst_vpx_enc->cfg.kf_mode);
1170       break;
1171     case PROP_KF_MAX_DIST:
1172       g_value_set_int (value, gst_vpx_enc->cfg.kf_max_dist);
1173       break;
1174     case PROP_MULTIPASS_MODE:
1175       g_value_set_enum (value, gst_vpx_enc->cfg.g_pass);
1176       break;
1177     case PROP_MULTIPASS_CACHE_FILE:
1178       g_value_set_string (value, gst_vpx_enc->multipass_cache_prefix);
1179       break;
1180     case PROP_TS_NUMBER_LAYERS:
1181       g_value_set_int (value, gst_vpx_enc->cfg.ts_number_layers);
1182       break;
1183     case PROP_TS_TARGET_BITRATE:{
1184       GValueArray *va;
1185 
1186       if (gst_vpx_enc->n_ts_target_bitrate == 0) {
1187         g_value_set_boxed (value, NULL);
1188       } else {
1189         gint i;
1190 
1191         va = g_value_array_new (gst_vpx_enc->n_ts_target_bitrate);
1192         for (i = 0; i < gst_vpx_enc->n_ts_target_bitrate; i++) {
1193           GValue v = { 0, };
1194 
1195           g_value_init (&v, G_TYPE_INT);
1196           g_value_set_int (&v, gst_vpx_enc->cfg.ts_target_bitrate[i]);
1197           g_value_array_append (va, &v);
1198           g_value_unset (&v);
1199         }
1200         g_value_set_boxed (value, va);
1201         g_value_array_free (va);
1202       }
1203       break;
1204     }
1205     case PROP_TS_RATE_DECIMATOR:{
1206       GValueArray *va;
1207 
1208       if (gst_vpx_enc->n_ts_rate_decimator == 0) {
1209         g_value_set_boxed (value, NULL);
1210       } else {
1211         gint i;
1212 
1213         va = g_value_array_new (gst_vpx_enc->n_ts_rate_decimator);
1214         for (i = 0; i < gst_vpx_enc->n_ts_rate_decimator; i++) {
1215           GValue v = { 0, };
1216 
1217           g_value_init (&v, G_TYPE_INT);
1218           g_value_set_int (&v, gst_vpx_enc->cfg.ts_rate_decimator[i]);
1219           g_value_array_append (va, &v);
1220           g_value_unset (&v);
1221         }
1222         g_value_set_boxed (value, va);
1223         g_value_array_free (va);
1224       }
1225       break;
1226     }
1227     case PROP_TS_PERIODICITY:
1228       g_value_set_int (value, gst_vpx_enc->cfg.ts_periodicity);
1229       break;
1230     case PROP_TS_LAYER_ID:{
1231       GValueArray *va;
1232 
1233       if (gst_vpx_enc->n_ts_layer_id == 0) {
1234         g_value_set_boxed (value, NULL);
1235       } else {
1236         gint i;
1237 
1238         va = g_value_array_new (gst_vpx_enc->n_ts_layer_id);
1239         for (i = 0; i < gst_vpx_enc->n_ts_layer_id; i++) {
1240           GValue v = { 0, };
1241 
1242           g_value_init (&v, G_TYPE_INT);
1243           g_value_set_int (&v, gst_vpx_enc->cfg.ts_layer_id[i]);
1244           g_value_array_append (va, &v);
1245           g_value_unset (&v);
1246         }
1247         g_value_set_boxed (value, va);
1248         g_value_array_free (va);
1249       }
1250       break;
1251     }
1252     case PROP_ERROR_RESILIENT:
1253       g_value_set_flags (value, gst_vpx_enc->cfg.g_error_resilient);
1254       break;
1255     case PROP_LAG_IN_FRAMES:
1256       g_value_set_int (value, gst_vpx_enc->cfg.g_lag_in_frames);
1257       break;
1258     case PROP_THREADS:
1259       g_value_set_int (value, gst_vpx_enc->cfg.g_threads);
1260       break;
1261     case PROP_DEADLINE:
1262       g_value_set_int64 (value, gst_vpx_enc->deadline);
1263       break;
1264     case PROP_H_SCALING_MODE:
1265       g_value_set_enum (value, gst_vpx_enc->h_scaling_mode);
1266       break;
1267     case PROP_V_SCALING_MODE:
1268       g_value_set_enum (value, gst_vpx_enc->v_scaling_mode);
1269       break;
1270     case PROP_CPU_USED:
1271       g_value_set_int (value, gst_vpx_enc->cpu_used);
1272       break;
1273     case PROP_ENABLE_AUTO_ALT_REF:
1274       g_value_set_boolean (value, gst_vpx_enc->enable_auto_alt_ref);
1275       break;
1276     case PROP_NOISE_SENSITIVITY:
1277       g_value_set_int (value, gst_vpx_enc->noise_sensitivity);
1278       break;
1279     case PROP_SHARPNESS:
1280       g_value_set_int (value, gst_vpx_enc->sharpness);
1281       break;
1282     case PROP_STATIC_THRESHOLD:
1283       g_value_set_int (value, gst_vpx_enc->static_threshold);
1284       break;
1285     case PROP_TOKEN_PARTITIONS:
1286       g_value_set_enum (value, gst_vpx_enc->token_partitions);
1287       break;
1288     case PROP_ARNR_MAXFRAMES:
1289       g_value_set_int (value, gst_vpx_enc->arnr_maxframes);
1290       break;
1291     case PROP_ARNR_STRENGTH:
1292       g_value_set_int (value, gst_vpx_enc->arnr_strength);
1293       break;
1294     case PROP_ARNR_TYPE:
1295       g_value_set_int (value, gst_vpx_enc->arnr_type);
1296       break;
1297     case PROP_TUNING:
1298       g_value_set_enum (value, gst_vpx_enc->tuning);
1299       break;
1300     case PROP_CQ_LEVEL:
1301       g_value_set_int (value, gst_vpx_enc->cq_level);
1302       break;
1303     case PROP_MAX_INTRA_BITRATE_PCT:
1304       g_value_set_int (value, gst_vpx_enc->max_intra_bitrate_pct);
1305       break;
1306     case PROP_TIMEBASE:
1307       gst_value_set_fraction (value, gst_vpx_enc->timebase_n,
1308           gst_vpx_enc->timebase_d);
1309       break;
1310     default:
1311       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1312       break;
1313   }
1314 
1315   g_mutex_unlock (&gst_vpx_enc->encoder_lock);
1316 }
1317 
1318 static gboolean
gst_vpx_enc_start(GstVideoEncoder * video_encoder)1319 gst_vpx_enc_start (GstVideoEncoder * video_encoder)
1320 {
1321   GstVPXEnc *encoder = GST_VPX_ENC (video_encoder);
1322 
1323   GST_DEBUG_OBJECT (video_encoder, "start");
1324 
1325   if (!encoder->have_default_config) {
1326     GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
1327         ("Failed to get default encoder configuration"), (NULL));
1328     return FALSE;
1329   }
1330 
1331   return TRUE;
1332 }
1333 
1334 static void
gst_vpx_enc_destroy_encoder(GstVPXEnc * encoder)1335 gst_vpx_enc_destroy_encoder (GstVPXEnc * encoder)
1336 {
1337   g_mutex_lock (&encoder->encoder_lock);
1338   if (encoder->inited) {
1339     vpx_codec_destroy (&encoder->encoder);
1340     encoder->inited = FALSE;
1341   }
1342 
1343   if (encoder->first_pass_cache_content) {
1344     g_byte_array_free (encoder->first_pass_cache_content, TRUE);
1345     encoder->first_pass_cache_content = NULL;
1346   }
1347 
1348   if (encoder->cfg.rc_twopass_stats_in.buf) {
1349     g_free (encoder->cfg.rc_twopass_stats_in.buf);
1350     encoder->cfg.rc_twopass_stats_in.buf = NULL;
1351     encoder->cfg.rc_twopass_stats_in.sz = 0;
1352   }
1353   g_mutex_unlock (&encoder->encoder_lock);
1354 }
1355 
1356 static gboolean
gst_vpx_enc_stop(GstVideoEncoder * video_encoder)1357 gst_vpx_enc_stop (GstVideoEncoder * video_encoder)
1358 {
1359   GstVPXEnc *encoder;
1360 
1361   GST_DEBUG_OBJECT (video_encoder, "stop");
1362 
1363   encoder = GST_VPX_ENC (video_encoder);
1364 
1365   gst_vpx_enc_destroy_encoder (encoder);
1366 
1367   gst_tag_setter_reset_tags (GST_TAG_SETTER (encoder));
1368 
1369   g_free (encoder->multipass_cache_file);
1370   encoder->multipass_cache_file = NULL;
1371   encoder->multipass_cache_idx = 0;
1372 
1373   return TRUE;
1374 }
1375 
1376 static gint
gst_vpx_enc_get_downstream_profile(GstVPXEnc * encoder)1377 gst_vpx_enc_get_downstream_profile (GstVPXEnc * encoder)
1378 {
1379   GstCaps *allowed;
1380   GstStructure *s;
1381   gint profile = DEFAULT_PROFILE;
1382 
1383   allowed = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1384   if (allowed) {
1385     allowed = gst_caps_truncate (allowed);
1386     s = gst_caps_get_structure (allowed, 0);
1387     if (gst_structure_has_field (s, "profile")) {
1388       const GValue *v = gst_structure_get_value (s, "profile");
1389       const gchar *profile_str = NULL;
1390 
1391       if (GST_VALUE_HOLDS_LIST (v) && gst_value_list_get_size (v) > 0) {
1392         profile_str = g_value_get_string (gst_value_list_get_value (v, 0));
1393       } else if (G_VALUE_HOLDS_STRING (v)) {
1394         profile_str = g_value_get_string (v);
1395       }
1396 
1397       if (profile_str) {
1398         gchar *endptr = NULL;
1399 
1400         profile = g_ascii_strtoull (profile_str, &endptr, 10);
1401         if (*endptr != '\0' || profile < 0 || profile > 3) {
1402           GST_ERROR_OBJECT (encoder, "Invalid profile '%s'", profile_str);
1403           profile = DEFAULT_PROFILE;
1404         }
1405       }
1406     }
1407     gst_caps_unref (allowed);
1408   }
1409 
1410   GST_DEBUG_OBJECT (encoder, "Using profile %d", profile);
1411 
1412   return profile;
1413 }
1414 
1415 static gboolean
gst_vpx_enc_set_format(GstVideoEncoder * video_encoder,GstVideoCodecState * state)1416 gst_vpx_enc_set_format (GstVideoEncoder * video_encoder,
1417     GstVideoCodecState * state)
1418 {
1419   GstVPXEnc *encoder;
1420   vpx_codec_err_t status;
1421   vpx_image_t *image;
1422   GstCaps *caps;
1423   gboolean ret = TRUE;
1424   GstVideoInfo *info = &state->info;
1425   GstVideoCodecState *output_state;
1426   GstClockTime latency;
1427   GstVPXEncClass *vpx_enc_class;
1428 
1429   encoder = GST_VPX_ENC (video_encoder);
1430   vpx_enc_class = GST_VPX_ENC_GET_CLASS (encoder);
1431   GST_DEBUG_OBJECT (video_encoder, "set_format");
1432 
1433   if (encoder->inited) {
1434     gst_vpx_enc_drain (video_encoder);
1435     g_mutex_lock (&encoder->encoder_lock);
1436     vpx_codec_destroy (&encoder->encoder);
1437     encoder->inited = FALSE;
1438     encoder->multipass_cache_idx++;
1439   } else {
1440     g_mutex_lock (&encoder->encoder_lock);
1441   }
1442 
1443   encoder->cfg.g_profile = gst_vpx_enc_get_downstream_profile (encoder);
1444 
1445   /* Scale default bitrate to our size */
1446   if (!encoder->rc_target_bitrate_set)
1447     encoder->cfg.rc_target_bitrate =
1448         gst_util_uint64_scale (DEFAULT_RC_TARGET_BITRATE,
1449         GST_VIDEO_INFO_WIDTH (info) * GST_VIDEO_INFO_HEIGHT (info),
1450         320 * 240 * 1000);
1451 
1452   encoder->cfg.g_w = GST_VIDEO_INFO_WIDTH (info);
1453   encoder->cfg.g_h = GST_VIDEO_INFO_HEIGHT (info);
1454 
1455   if (encoder->timebase_n != 0 && encoder->timebase_d != 0) {
1456     GST_DEBUG_OBJECT (video_encoder, "Using timebase configuration");
1457     encoder->cfg.g_timebase.num = encoder->timebase_n;
1458     encoder->cfg.g_timebase.den = encoder->timebase_d;
1459   } else {
1460     /* Zero framerate and max-framerate but still need to setup the timebase to avoid
1461      * a divide by zero error. Presuming the lowest common denominator will be RTP -
1462      * VP8 payload draft states clock rate of 90000 which should work for anyone where
1463      * FPS < 90000 (shouldn't be too many cases where it's higher) though wouldn't be optimal. RTP specification
1464      * http://tools.ietf.org/html/draft-ietf-payload-vp8-01 section 6.3.1 */
1465     encoder->cfg.g_timebase.num = 1;
1466     encoder->cfg.g_timebase.den = 90000;
1467   }
1468 
1469   if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS ||
1470       encoder->cfg.g_pass == VPX_RC_LAST_PASS) {
1471     if (!encoder->multipass_cache_prefix) {
1472       GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
1473           ("No multipass cache file provided"), (NULL));
1474       g_mutex_unlock (&encoder->encoder_lock);
1475       return FALSE;
1476     }
1477 
1478     g_free (encoder->multipass_cache_file);
1479 
1480     if (encoder->multipass_cache_idx > 0)
1481       encoder->multipass_cache_file = g_strdup_printf ("%s.%u",
1482           encoder->multipass_cache_prefix, encoder->multipass_cache_idx);
1483     else
1484       encoder->multipass_cache_file =
1485           g_strdup (encoder->multipass_cache_prefix);
1486   }
1487 
1488   if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS) {
1489     if (encoder->first_pass_cache_content != NULL)
1490       g_byte_array_free (encoder->first_pass_cache_content, TRUE);
1491 
1492     encoder->first_pass_cache_content = g_byte_array_sized_new (4096);
1493 
1494   } else if (encoder->cfg.g_pass == VPX_RC_LAST_PASS) {
1495     GError *err = NULL;
1496 
1497     if (encoder->cfg.rc_twopass_stats_in.buf != NULL) {
1498       g_free (encoder->cfg.rc_twopass_stats_in.buf);
1499       encoder->cfg.rc_twopass_stats_in.buf = NULL;
1500       encoder->cfg.rc_twopass_stats_in.sz = 0;
1501     }
1502 
1503     if (!g_file_get_contents (encoder->multipass_cache_file,
1504             (gchar **) & encoder->cfg.rc_twopass_stats_in.buf,
1505             &encoder->cfg.rc_twopass_stats_in.sz, &err)) {
1506       GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
1507           ("Failed to read multipass cache file provided"), ("%s",
1508               err->message));
1509       g_error_free (err);
1510       g_mutex_unlock (&encoder->encoder_lock);
1511       return FALSE;
1512     }
1513   }
1514 
1515   status =
1516       vpx_codec_enc_init (&encoder->encoder, vpx_enc_class->get_algo (encoder),
1517       &encoder->cfg, 0);
1518   if (status != VPX_CODEC_OK) {
1519     GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
1520         ("Failed to initialize encoder"), ("%s", gst_vpx_error_name (status)));
1521     g_mutex_unlock (&encoder->encoder_lock);
1522     return FALSE;
1523   }
1524 
1525   if (vpx_enc_class->enable_scaling (encoder)) {
1526     vpx_scaling_mode_t sm;
1527 
1528     sm.h_scaling_mode = encoder->h_scaling_mode;
1529     sm.v_scaling_mode = encoder->v_scaling_mode;
1530 
1531     status = vpx_codec_control (&encoder->encoder, VP8E_SET_SCALEMODE, &sm);
1532     if (status != VPX_CODEC_OK) {
1533       GST_WARNING_OBJECT (encoder, "Failed to set VP8E_SET_SCALEMODE: %s",
1534           gst_vpx_error_name (status));
1535     }
1536   }
1537 
1538   status =
1539       vpx_codec_control (&encoder->encoder, VP8E_SET_CPUUSED,
1540       encoder->cpu_used);
1541   if (status != VPX_CODEC_OK) {
1542     GST_WARNING_OBJECT (encoder, "Failed to set VP8E_SET_CPUUSED: %s",
1543         gst_vpx_error_name (status));
1544   }
1545 
1546   status =
1547       vpx_codec_control (&encoder->encoder, VP8E_SET_ENABLEAUTOALTREF,
1548       (encoder->enable_auto_alt_ref ? 1 : 0));
1549   if (status != VPX_CODEC_OK) {
1550     GST_WARNING_OBJECT (encoder,
1551         "Failed to set VP8E_SET_ENABLEAUTOALTREF: %s",
1552         gst_vpx_error_name (status));
1553   }
1554   status = vpx_codec_control (&encoder->encoder, VP8E_SET_NOISE_SENSITIVITY,
1555       encoder->noise_sensitivity);
1556   if (status != VPX_CODEC_OK) {
1557     GST_WARNING_OBJECT (encoder,
1558         "Failed to set VP8E_SET_NOISE_SENSITIVITY: %s",
1559         gst_vpx_error_name (status));
1560   }
1561   status = vpx_codec_control (&encoder->encoder, VP8E_SET_SHARPNESS,
1562       encoder->sharpness);
1563   if (status != VPX_CODEC_OK) {
1564     GST_WARNING_OBJECT (encoder,
1565         "Failed to set VP8E_SET_SHARPNESS: %s", gst_vpx_error_name (status));
1566   }
1567   status = vpx_codec_control (&encoder->encoder, VP8E_SET_STATIC_THRESHOLD,
1568       encoder->static_threshold);
1569   if (status != VPX_CODEC_OK) {
1570     GST_WARNING_OBJECT (encoder,
1571         "Failed to set VP8E_SET_STATIC_THRESHOLD: %s",
1572         gst_vpx_error_name (status));
1573   }
1574   status = vpx_codec_control (&encoder->encoder, VP8E_SET_TOKEN_PARTITIONS,
1575       encoder->token_partitions);
1576   if (status != VPX_CODEC_OK) {
1577     GST_WARNING_OBJECT (encoder,
1578         "Failed to set VP8E_SET_TOKEN_PARTIONS: %s",
1579         gst_vpx_error_name (status));
1580   }
1581   status = vpx_codec_control (&encoder->encoder, VP8E_SET_ARNR_MAXFRAMES,
1582       encoder->arnr_maxframes);
1583   if (status != VPX_CODEC_OK) {
1584     GST_WARNING_OBJECT (encoder,
1585         "Failed to set VP8E_SET_ARNR_MAXFRAMES: %s",
1586         gst_vpx_error_name (status));
1587   }
1588   status = vpx_codec_control (&encoder->encoder, VP8E_SET_ARNR_STRENGTH,
1589       encoder->arnr_strength);
1590   if (status != VPX_CODEC_OK) {
1591     GST_WARNING_OBJECT (encoder,
1592         "Failed to set VP8E_SET_ARNR_STRENGTH: %s",
1593         gst_vpx_error_name (status));
1594   }
1595   status = vpx_codec_control (&encoder->encoder, VP8E_SET_TUNING,
1596       encoder->tuning);
1597   if (status != VPX_CODEC_OK) {
1598     GST_WARNING_OBJECT (encoder,
1599         "Failed to set VP8E_SET_TUNING: %s", gst_vpx_error_name (status));
1600   }
1601   status = vpx_codec_control (&encoder->encoder, VP8E_SET_CQ_LEVEL,
1602       encoder->cq_level);
1603   if (status != VPX_CODEC_OK) {
1604     GST_WARNING_OBJECT (encoder,
1605         "Failed to set VP8E_SET_CQ_LEVEL: %s", gst_vpx_error_name (status));
1606   }
1607   status = vpx_codec_control (&encoder->encoder, VP8E_SET_MAX_INTRA_BITRATE_PCT,
1608       encoder->max_intra_bitrate_pct);
1609   if (status != VPX_CODEC_OK) {
1610     GST_WARNING_OBJECT (encoder,
1611         "Failed to set VP8E_SET_MAX_INTRA_BITRATE_PCT: %s",
1612         gst_vpx_error_name (status));
1613   }
1614 
1615   if (GST_VIDEO_INFO_FPS_D (info) == 0 || GST_VIDEO_INFO_FPS_N (info) == 0) {
1616     /* FIXME: Assume 25fps for unknown framerates. Better than reporting
1617      * that we introduce no latency while we actually do
1618      */
1619     latency = gst_util_uint64_scale (encoder->cfg.g_lag_in_frames,
1620         1 * GST_SECOND, 25);
1621   } else {
1622     latency = gst_util_uint64_scale (encoder->cfg.g_lag_in_frames,
1623         GST_VIDEO_INFO_FPS_D (info) * GST_SECOND, GST_VIDEO_INFO_FPS_N (info));
1624   }
1625   gst_video_encoder_set_latency (video_encoder, latency, latency);
1626   encoder->inited = TRUE;
1627 
1628   /* Store input state */
1629   if (encoder->input_state)
1630     gst_video_codec_state_unref (encoder->input_state);
1631   encoder->input_state = gst_video_codec_state_ref (state);
1632 
1633   /* prepare cached image buffer setup */
1634   image = &encoder->image;
1635   memset (image, 0, sizeof (*image));
1636 
1637   vpx_enc_class->set_image_format (encoder, image);
1638 
1639   image->w = image->d_w = GST_VIDEO_INFO_WIDTH (info);
1640   image->h = image->d_h = GST_VIDEO_INFO_HEIGHT (info);
1641 
1642   image->stride[VPX_PLANE_Y] = GST_VIDEO_INFO_COMP_STRIDE (info, 0);
1643   image->stride[VPX_PLANE_U] = GST_VIDEO_INFO_COMP_STRIDE (info, 1);
1644   image->stride[VPX_PLANE_V] = GST_VIDEO_INFO_COMP_STRIDE (info, 2);
1645 
1646   caps = vpx_enc_class->get_new_vpx_caps (encoder);
1647 
1648   vpx_enc_class->set_stream_info (encoder, caps, info);
1649 
1650   g_mutex_unlock (&encoder->encoder_lock);
1651 
1652   output_state =
1653       gst_video_encoder_set_output_state (video_encoder, caps, state);
1654   gst_video_codec_state_unref (output_state);
1655 
1656   gst_video_encoder_negotiate (GST_VIDEO_ENCODER (encoder));
1657 
1658   return ret;
1659 }
1660 
1661 static GstFlowReturn
gst_vpx_enc_process(GstVPXEnc * encoder)1662 gst_vpx_enc_process (GstVPXEnc * encoder)
1663 {
1664   vpx_codec_iter_t iter = NULL;
1665   const vpx_codec_cx_pkt_t *pkt;
1666   GstVideoEncoder *video_encoder;
1667   void *user_data;
1668   GstVideoCodecFrame *frame;
1669   GstFlowReturn ret = GST_FLOW_OK;
1670   GstVPXEncClass *vpx_enc_class;
1671   vpx_codec_pts_t pts;
1672 
1673   video_encoder = GST_VIDEO_ENCODER (encoder);
1674   vpx_enc_class = GST_VPX_ENC_GET_CLASS (encoder);
1675 
1676   g_mutex_lock (&encoder->encoder_lock);
1677   pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
1678   while (pkt != NULL) {
1679     GstBuffer *buffer;
1680     gboolean invisible;
1681 
1682     GST_DEBUG_OBJECT (encoder, "packet %u type %d", (guint) pkt->data.frame.sz,
1683         pkt->kind);
1684 
1685     if (pkt->kind == VPX_CODEC_STATS_PKT
1686         && encoder->cfg.g_pass == VPX_RC_FIRST_PASS) {
1687       GST_LOG_OBJECT (encoder, "handling STATS packet");
1688 
1689       g_byte_array_append (encoder->first_pass_cache_content,
1690           pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz);
1691 
1692       frame = gst_video_encoder_get_oldest_frame (video_encoder);
1693       if (frame != NULL) {
1694         buffer = gst_buffer_new ();
1695         GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_LIVE);
1696         frame->output_buffer = buffer;
1697         g_mutex_unlock (&encoder->encoder_lock);
1698         ret = gst_video_encoder_finish_frame (video_encoder, frame);
1699         g_mutex_lock (&encoder->encoder_lock);
1700       }
1701 
1702       pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
1703       continue;
1704     } else if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) {
1705       GST_LOG_OBJECT (encoder, "non frame pkt: %d", pkt->kind);
1706       pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
1707       continue;
1708     }
1709 
1710     invisible = (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) != 0;
1711 
1712     /* discard older frames that were dropped by libvpx */
1713     frame = NULL;
1714     do {
1715       if (frame)
1716         gst_video_encoder_finish_frame (video_encoder, frame);
1717       frame = gst_video_encoder_get_oldest_frame (video_encoder);
1718       pts =
1719           gst_util_uint64_scale (frame->pts,
1720           encoder->cfg.g_timebase.den,
1721           encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
1722       GST_TRACE_OBJECT (encoder, "vpx pts: %" G_GINT64_FORMAT
1723           ", gst frame pts: %" G_GINT64_FORMAT, pkt->data.frame.pts, pts);
1724     } while (pkt->data.frame.pts > pts);
1725 
1726     g_assert (frame != NULL);
1727     if ((pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0)
1728       GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
1729     else
1730       GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
1731 
1732     /* FIXME : It would be nice to avoid the memory copy ... */
1733     buffer =
1734         gst_buffer_new_wrapped (g_memdup (pkt->data.frame.buf,
1735             pkt->data.frame.sz), pkt->data.frame.sz);
1736 
1737     user_data = vpx_enc_class->process_frame_user_data (encoder, frame);
1738 
1739     if (invisible) {
1740       ret =
1741           vpx_enc_class->handle_invisible_frame_buffer (encoder, user_data,
1742           buffer);
1743       gst_video_codec_frame_unref (frame);
1744     } else {
1745       frame->output_buffer = buffer;
1746       g_mutex_unlock (&encoder->encoder_lock);
1747       ret = gst_video_encoder_finish_frame (video_encoder, frame);
1748       g_mutex_lock (&encoder->encoder_lock);
1749     }
1750 
1751     pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter);
1752   }
1753   g_mutex_unlock (&encoder->encoder_lock);
1754 
1755   return ret;
1756 }
1757 
1758 /* This function should be called holding then stream lock*/
1759 static GstFlowReturn
gst_vpx_enc_drain(GstVideoEncoder * video_encoder)1760 gst_vpx_enc_drain (GstVideoEncoder * video_encoder)
1761 {
1762   GstVPXEnc *encoder;
1763   int flags = 0;
1764   vpx_codec_err_t status;
1765   gint64 deadline;
1766   vpx_codec_pts_t pts;
1767 
1768   encoder = GST_VPX_ENC (video_encoder);
1769 
1770   g_mutex_lock (&encoder->encoder_lock);
1771   deadline = encoder->deadline;
1772 
1773   pts =
1774       gst_util_uint64_scale (encoder->last_pts,
1775       encoder->cfg.g_timebase.den,
1776       encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
1777 
1778   status = vpx_codec_encode (&encoder->encoder, NULL, pts, 0, flags, deadline);
1779   g_mutex_unlock (&encoder->encoder_lock);
1780 
1781   if (status != 0) {
1782     GST_ERROR_OBJECT (encoder, "encode returned %d %s", status,
1783         gst_vpx_error_name (status));
1784     return GST_FLOW_ERROR;
1785   }
1786 
1787   /* dispatch remaining frames */
1788   gst_vpx_enc_process (encoder);
1789 
1790   g_mutex_lock (&encoder->encoder_lock);
1791   if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS && encoder->multipass_cache_file) {
1792     GError *err = NULL;
1793 
1794     if (!g_file_set_contents (encoder->multipass_cache_file,
1795             (const gchar *) encoder->first_pass_cache_content->data,
1796             encoder->first_pass_cache_content->len, &err)) {
1797       GST_ELEMENT_ERROR (encoder, RESOURCE, WRITE, (NULL),
1798           ("Failed to write multipass cache file: %s", err->message));
1799       g_error_free (err);
1800     }
1801   }
1802   g_mutex_unlock (&encoder->encoder_lock);
1803 
1804   return GST_FLOW_OK;
1805 }
1806 
1807 static gboolean
gst_vpx_enc_flush(GstVideoEncoder * video_encoder)1808 gst_vpx_enc_flush (GstVideoEncoder * video_encoder)
1809 {
1810   GstVPXEnc *encoder;
1811 
1812   GST_DEBUG_OBJECT (video_encoder, "flush");
1813 
1814   encoder = GST_VPX_ENC (video_encoder);
1815 
1816   gst_vpx_enc_destroy_encoder (encoder);
1817   if (encoder->input_state) {
1818     gst_video_codec_state_ref (encoder->input_state);
1819     gst_vpx_enc_set_format (video_encoder, encoder->input_state);
1820     gst_video_codec_state_unref (encoder->input_state);
1821   }
1822 
1823   return TRUE;
1824 }
1825 
1826 static GstFlowReturn
gst_vpx_enc_finish(GstVideoEncoder * video_encoder)1827 gst_vpx_enc_finish (GstVideoEncoder * video_encoder)
1828 {
1829   GstVPXEnc *encoder;
1830   GstFlowReturn ret;
1831 
1832   GST_DEBUG_OBJECT (video_encoder, "finish");
1833 
1834   encoder = GST_VPX_ENC (video_encoder);
1835 
1836   if (encoder->inited) {
1837     ret = gst_vpx_enc_drain (video_encoder);
1838   } else {
1839     ret = GST_FLOW_OK;
1840   }
1841 
1842   return ret;
1843 }
1844 
1845 static vpx_image_t *
gst_vpx_enc_buffer_to_image(GstVPXEnc * enc,GstVideoFrame * frame)1846 gst_vpx_enc_buffer_to_image (GstVPXEnc * enc, GstVideoFrame * frame)
1847 {
1848   vpx_image_t *image = g_slice_new (vpx_image_t);
1849 
1850   memcpy (image, &enc->image, sizeof (*image));
1851 
1852   image->planes[VPX_PLANE_Y] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
1853   image->planes[VPX_PLANE_U] = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
1854   image->planes[VPX_PLANE_V] = GST_VIDEO_FRAME_COMP_DATA (frame, 2);
1855 
1856   image->stride[VPX_PLANE_Y] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
1857   image->stride[VPX_PLANE_U] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1);
1858   image->stride[VPX_PLANE_V] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2);
1859 
1860   return image;
1861 }
1862 
1863 static GstFlowReturn
gst_vpx_enc_handle_frame(GstVideoEncoder * video_encoder,GstVideoCodecFrame * frame)1864 gst_vpx_enc_handle_frame (GstVideoEncoder * video_encoder,
1865     GstVideoCodecFrame * frame)
1866 {
1867   GstVPXEnc *encoder;
1868   vpx_codec_err_t status;
1869   int flags = 0;
1870   vpx_image_t *image;
1871   GstVideoFrame vframe;
1872   vpx_codec_pts_t pts;
1873   unsigned long duration;
1874   GstVPXEncClass *vpx_enc_class;
1875 
1876   GST_DEBUG_OBJECT (video_encoder, "handle_frame");
1877 
1878   encoder = GST_VPX_ENC (video_encoder);
1879   vpx_enc_class = GST_VPX_ENC_GET_CLASS (encoder);
1880 
1881   GST_DEBUG_OBJECT (video_encoder, "size %d %d",
1882       GST_VIDEO_INFO_WIDTH (&encoder->input_state->info),
1883       GST_VIDEO_INFO_HEIGHT (&encoder->input_state->info));
1884 
1885   gst_video_frame_map (&vframe, &encoder->input_state->info,
1886       frame->input_buffer, GST_MAP_READ);
1887   image = gst_vpx_enc_buffer_to_image (encoder, &vframe);
1888 
1889   vpx_enc_class->set_frame_user_data (encoder, frame, image);
1890 
1891   if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
1892     flags |= VPX_EFLAG_FORCE_KF;
1893   }
1894 
1895   g_mutex_lock (&encoder->encoder_lock);
1896   pts =
1897       gst_util_uint64_scale (frame->pts,
1898       encoder->cfg.g_timebase.den,
1899       encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
1900   encoder->last_pts = frame->pts;
1901 
1902   if (frame->duration != GST_CLOCK_TIME_NONE) {
1903     duration =
1904         gst_util_uint64_scale (frame->duration, encoder->cfg.g_timebase.den,
1905         encoder->cfg.g_timebase.num * (GstClockTime) GST_SECOND);
1906 
1907     if (duration > 0) {
1908       encoder->last_pts += frame->duration;
1909     } else {
1910       /* We force the path ignoring the duration if we end up with a zero
1911        * value for duration after scaling (e.g. duration value too small) */
1912       GST_WARNING_OBJECT (encoder,
1913           "Ignoring too small frame duration %" GST_TIME_FORMAT,
1914           GST_TIME_ARGS (frame->duration));
1915       duration = 1;
1916     }
1917   } else {
1918     duration = 1;
1919   }
1920 
1921   status = vpx_codec_encode (&encoder->encoder, image,
1922       pts, duration, flags, encoder->deadline);
1923 
1924   g_mutex_unlock (&encoder->encoder_lock);
1925   gst_video_frame_unmap (&vframe);
1926 
1927   if (status != 0) {
1928     GST_ELEMENT_ERROR (encoder, LIBRARY, ENCODE,
1929         ("Failed to encode frame"), ("%s", gst_vpx_error_name (status)));
1930     gst_video_codec_frame_set_user_data (frame, NULL, NULL);
1931     gst_video_codec_frame_unref (frame);
1932 
1933     return GST_FLOW_ERROR;
1934   }
1935   gst_video_codec_frame_unref (frame);
1936   return gst_vpx_enc_process (encoder);
1937 }
1938 
1939 static gboolean
gst_vpx_enc_sink_event(GstVideoEncoder * benc,GstEvent * event)1940 gst_vpx_enc_sink_event (GstVideoEncoder * benc, GstEvent * event)
1941 {
1942   GstVPXEnc *enc = GST_VPX_ENC (benc);
1943 
1944   /* FIXME : Move this to base encoder class */
1945 
1946   if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) {
1947     GstTagList *list;
1948     GstTagSetter *setter = GST_TAG_SETTER (enc);
1949     const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
1950 
1951     gst_event_parse_tag (event, &list);
1952     gst_tag_setter_merge_tags (setter, list, mode);
1953   }
1954 
1955   /* just peeked, baseclass handles the rest */
1956   return GST_VIDEO_ENCODER_CLASS (parent_class)->sink_event (benc, event);
1957 }
1958 
1959 static gboolean
gst_vpx_enc_propose_allocation(GstVideoEncoder * encoder,GstQuery * query)1960 gst_vpx_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
1961 {
1962   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
1963 
1964   return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
1965       query);
1966 }
1967 
1968 #endif /* HAVE_VP8_ENCODER || HAVE_VP9_ENCODER */
1969