1 /* GStreamer
2  * Copyright (C) <2017> Sean DuBois <sean@siobud.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 /**
20  * SECTION:element-av1enc
21  *
22  * AV1 Encoder.
23  *
24  * <refsect2>
25  * <title>Example launch line</title>
26  * |[
27  * gst-launch-1.0 videotestsrc num-buffers=50 ! av1enc ! webmmux ! filesink location=av1.webm
28  * ]|
29  * </refsect2>
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include "gstav1enc.h"
37 #include "gstav1utils.h"
38 #include <gst/video/video.h>
39 #include <gst/video/gstvideometa.h>
40 #include <gst/base/base.h>
41 
42 #define GST_AV1_ENC_APPLY_CODEC_CONTROL(av1enc, flag, value)             \
43   if (av1enc->encoder_inited) {                                        \
44     if (aom_codec_control (&av1enc->encoder, flag,                     \
45             value) != AOM_CODEC_OK) {                                  \
46       gst_av1_codec_error (&av1enc->encoder, "Failed to set " #flag);  \
47     }                                                                  \
48   }
49 
50 GST_DEBUG_CATEGORY_STATIC (av1_enc_debug);
51 #define GST_CAT_DEFAULT av1_enc_debug
52 
53 #define GST_TYPE_RESIZE_MODE (gst_resize_mode_get_type())
54 static GType
gst_resize_mode_get_type(void)55 gst_resize_mode_get_type (void)
56 {
57   static GType resize_mode_type = 0;
58   static const GEnumValue resize_mode[] = {
59     {GST_AV1_ENC_RESIZE_NONE, "No frame resizing allowed", "none"},
60     {GST_AV1_ENC_RESIZE_FIXED, "All frames are coded at the specified scale",
61         "fixed"},
62     {GST_AV1_ENC_RESIZE_RANDOM, "All frames are coded at a random scale",
63         "random"},
64     {0, NULL, NULL},
65   };
66 
67   if (!resize_mode_type) {
68     resize_mode_type =
69         g_enum_register_static ("GstAV1EncResizeMode", resize_mode);
70   }
71   return resize_mode_type;
72 }
73 
74 #define GST_TYPE_SUPERRES_MODE (gst_superres_mode_get_type())
75 static GType
gst_superres_mode_get_type(void)76 gst_superres_mode_get_type (void)
77 {
78   static GType superres_mode_type = 0;
79   static const GEnumValue superres_mode[] = {
80     {GST_AV1_ENC_SUPERRES_NONE, "No frame superres allowed", "none"},
81     {GST_AV1_ENC_SUPERRES_FIXED,
82           "All frames are coded at the specified scale and super-resolved",
83         "fixed"},
84     {GST_AV1_ENC_SUPERRES_RANDOM,
85           "All frames are coded at a random scale and super-resolved",
86         "random"},
87     {GST_AV1_ENC_SUPERRES_QTHRESH,
88           "Superres scale for a frame is determined based on q_index",
89         "qthresh"},
90     {0, NULL, NULL},
91   };
92 
93   if (!superres_mode_type) {
94     superres_mode_type =
95         g_enum_register_static ("GstAV1EncSuperresMode", superres_mode);
96   }
97   return superres_mode_type;
98 }
99 
100 #define GST_TYPE_END_USAGE_MODE (gst_end_usage_mode_get_type())
101 static GType
gst_end_usage_mode_get_type(void)102 gst_end_usage_mode_get_type (void)
103 {
104   static GType end_usage_mode_type = 0;
105   static const GEnumValue end_usage_mode[] = {
106     {GST_AV1_ENC_END_USAGE_VBR, "Variable Bit Rate Mode", "vbr"},
107     {GST_AV1_ENC_END_USAGE_CBR, "Constant Bit Rate Mode", "cbr"},
108     {GST_AV1_ENC_END_USAGE_CQ, "Constrained Quality Mode", "cq"},
109     {GST_AV1_ENC_END_USAGE_Q, "Constant Quality Mode", "q"},
110     {0, NULL, NULL},
111   };
112 
113   if (!end_usage_mode_type) {
114     end_usage_mode_type =
115         g_enum_register_static ("GstAV1EncEndUsageMode", end_usage_mode);
116   }
117   return end_usage_mode_type;
118 }
119 
120 enum
121 {
122   LAST_SIGNAL
123 };
124 
125 enum
126 {
127   PROP_0,
128   PROP_CPU_USED,
129   PROP_DROP_FRAME,
130   PROP_RESIZE_MODE,
131   PROP_RESIZE_DENOMINATOR,
132   PROP_RESIZE_KF_DENOMINATOR,
133   PROP_SUPERRES_MODE,
134   PROP_SUPERRES_DENOMINATOR,
135   PROP_SUPERRES_KF_DENOMINATOR,
136   PROP_SUPERRES_QTHRESH,
137   PROP_SUPERRES_KF_QTHRESH,
138   PROP_END_USAGE,
139   PROP_TARGET_BITRATE,
140   PROP_MIN_QUANTIZER,
141   PROP_MAX_QUANTIZER,
142   PROP_UNDERSHOOT_PCT,
143   PROP_OVERSHOOT_PCT,
144   PROP_BUF_SZ,
145   PROP_BUF_INITIAL_SZ,
146   PROP_BUF_OPTIMAL_SZ
147 };
148 
149 /* From av1/av1_cx_iface.c */
150 #define DEFAULT_PROFILE                                         0
151 #define DEFAULT_CPU_USED                                        0
152 #define DEFAULT_DROP_FRAME                                      0
153 #define DEFAULT_RESIZE_MODE               GST_AV1_ENC_RESIZE_NONE
154 #define DEFAULT_RESIZE_DENOMINATOR                              8
155 #define DEFAULT_RESIZE_KF_DENOMINATOR                           8
156 #define DEFAULT_SUPERRES_MODE           GST_AV1_ENC_SUPERRES_NONE
157 #define DEFAULT_SUPERRES_DENOMINATOR                            8
158 #define DEFAULT_SUPERRES_KF_DENOMINATOR                         8
159 #define DEFAULT_SUPERRES_QTHRESH                               63
160 #define DEFAULT_SUPERRES_KF_QTHRESH                            63
161 #define DEFAULT_END_USAGE               GST_AV1_ENC_END_USAGE_VBR
162 #define DEFAULT_TARGET_BITRATE                                256
163 #define DEFAULT_MIN_QUANTIZER                                   0
164 #define DEFAULT_MAX_QUANTIZER                                   0
165 #define DEFAULT_UNDERSHOOT_PCT                                 25
166 #define DEFAULT_OVERSHOOT_PCT                                  25
167 #define DEFAULT_BUF_SZ                                       6000
168 #define DEFAULT_BUF_INITIAL_SZ                               4000
169 #define DEFAULT_BUF_OPTIMAL_SZ                               5000
170 #define DEFAULT_TIMEBASE_N                                      1
171 #define DEFAULT_TIMEBASE_D                                     30
172 #define DEFAULT_BIT_DEPTH                              AOM_BITS_8
173 
174 static void gst_av1_enc_finalize (GObject * object);
175 static void gst_av1_enc_set_property (GObject * object, guint prop_id,
176     const GValue * value, GParamSpec * pspec);
177 static void gst_av1_enc_get_property (GObject * object, guint prop_id,
178     GValue * value, GParamSpec * pspec);
179 
180 static gboolean gst_av1_enc_start (GstVideoEncoder * encoder);
181 static gboolean gst_av1_enc_stop (GstVideoEncoder * encoder);
182 static gboolean gst_av1_enc_set_format (GstVideoEncoder * encoder,
183     GstVideoCodecState * state);
184 static GstFlowReturn gst_av1_enc_handle_frame (GstVideoEncoder * encoder,
185     GstVideoCodecFrame * frame);
186 static GstFlowReturn gst_av1_enc_finish (GstVideoEncoder * encoder);
187 static gboolean gst_av1_enc_propose_allocation (GstVideoEncoder * encoder,
188     GstQuery * query);
189 
190 static void gst_av1_enc_destroy_encoder (GstAV1Enc * av1enc);
191 
192 #define gst_av1_enc_parent_class parent_class
193 G_DEFINE_TYPE (GstAV1Enc, gst_av1_enc, GST_TYPE_VIDEO_ENCODER);
194 
195 /* *INDENT-OFF* */
196 static GstStaticPadTemplate gst_av1_enc_sink_pad_template =
197 GST_STATIC_PAD_TEMPLATE ("sink",
198     GST_PAD_SINK,
199     GST_PAD_ALWAYS,
200         GST_STATIC_CAPS ("video/x-raw, "
201         "format = (string) { I420, Y42B, Y444, YV12 }, "
202         "framerate = (fraction) [0, MAX], "
203         "width = (int) [ 4, MAX ], "
204         "height = (int) [ 4, MAX ]")
205     );
206 /* *INDENT-ON* */
207 
208 static GstStaticPadTemplate gst_av1_enc_src_pad_template =
209 GST_STATIC_PAD_TEMPLATE ("src",
210     GST_PAD_SRC,
211     GST_PAD_ALWAYS,
212     GST_STATIC_CAPS ("video/x-av1")
213     );
214 
215 static void
gst_av1_enc_class_init(GstAV1EncClass * klass)216 gst_av1_enc_class_init (GstAV1EncClass * klass)
217 {
218   GObjectClass *gobject_class;
219   GstElementClass *element_class;
220   GstVideoEncoderClass *venc_class;
221 
222   gobject_class = (GObjectClass *) klass;
223   element_class = (GstElementClass *) klass;
224   venc_class = (GstVideoEncoderClass *) klass;
225 
226   parent_class = g_type_class_peek_parent (klass);
227 
228   gobject_class->finalize = gst_av1_enc_finalize;
229   gobject_class->set_property = gst_av1_enc_set_property;
230   gobject_class->get_property = gst_av1_enc_get_property;
231 
232   gst_element_class_add_static_pad_template (element_class,
233       &gst_av1_enc_sink_pad_template);
234   gst_element_class_add_static_pad_template (element_class,
235       &gst_av1_enc_src_pad_template);
236   gst_element_class_set_static_metadata (element_class, "AV1 Encoder",
237       "Codec/Encoder/Video", "Encode AV1 video streams",
238       "Sean DuBois <sean@siobud.com>");
239 
240   venc_class->start = gst_av1_enc_start;
241   venc_class->stop = gst_av1_enc_stop;
242   venc_class->set_format = gst_av1_enc_set_format;
243   venc_class->handle_frame = gst_av1_enc_handle_frame;
244   venc_class->finish = gst_av1_enc_finish;
245   venc_class->propose_allocation = gst_av1_enc_propose_allocation;
246 
247   klass->codec_algo = &aom_codec_av1_cx_algo;
248   GST_DEBUG_CATEGORY_INIT (av1_enc_debug, "av1enc", 0, "AV1 encoding element");
249 
250   g_object_class_install_property (gobject_class, PROP_CPU_USED,
251       g_param_spec_int ("cpu-used", "CPU Used",
252           "CPU Used. A Value greater than 0 will increase encoder speed at the expense of quality.",
253           0, 8, DEFAULT_CPU_USED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
254 
255   /* Rate control configurations */
256   g_object_class_install_property (gobject_class, PROP_DROP_FRAME,
257       g_param_spec_uint ("drop-frame", "Drop frame",
258           "Temporal resampling configuration, drop frames as a strategy to meet "
259           "its target data rate Set to zero (0) to disable this feature.",
260           0, G_MAXUINT, DEFAULT_DROP_FRAME,
261           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
262 
263   g_object_class_install_property (gobject_class, PROP_RESIZE_MODE,
264       g_param_spec_enum ("resize-mode", "Resize mode",
265           "Frame resize mode", GST_TYPE_RESIZE_MODE,
266           DEFAULT_RESIZE_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
267 
268   g_object_class_install_property (gobject_class, PROP_RESIZE_DENOMINATOR,
269       g_param_spec_uint ("resize-denominator", "Resize denominator",
270           "Frame resize denominator, assuming 8 as the numerator",
271           8, 16, DEFAULT_RESIZE_DENOMINATOR,
272           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
273 
274   g_object_class_install_property (gobject_class, PROP_RESIZE_KF_DENOMINATOR,
275       g_param_spec_uint ("resize-kf-denominator", "Resize keyframe denominator",
276           "Frame resize keyframe denominator, assuming 8 as the numerator",
277           8, 16, DEFAULT_RESIZE_KF_DENOMINATOR,
278           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
279 
280   g_object_class_install_property (gobject_class, PROP_SUPERRES_MODE,
281       g_param_spec_enum ("superres-mode", "Super-resolution scaling mode",
282           "It integrates upscaling after the encode/decode process",
283           GST_TYPE_SUPERRES_MODE,
284           DEFAULT_SUPERRES_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
285 
286   g_object_class_install_property (gobject_class, PROP_SUPERRES_DENOMINATOR,
287       g_param_spec_uint ("superres-denominator", "Super-resolution denominator",
288           "Frame super-resolution denominator, used only by SUPERRES_FIXED mode",
289           8, 16, DEFAULT_SUPERRES_DENOMINATOR,
290           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
291 
292   g_object_class_install_property (gobject_class, PROP_SUPERRES_KF_DENOMINATOR,
293       g_param_spec_uint ("superres-kf-denominator",
294           "Keyframe super-resolution denominator",
295           "Keyframe super-resolution denominator",
296           8, 16, DEFAULT_SUPERRES_KF_DENOMINATOR,
297           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
298 
299   g_object_class_install_property (gobject_class, PROP_SUPERRES_QTHRESH,
300       g_param_spec_uint ("superres-qthresh",
301           "Frame super-resolution qindex threshold",
302           "Frame super-resolution qindex threshold, used only by SUPERRES_QTHRESH mode",
303           1, 63, DEFAULT_SUPERRES_QTHRESH,
304           (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
305 
306   g_object_class_install_property (gobject_class, PROP_SUPERRES_KF_QTHRESH,
307       g_param_spec_uint ("superres-kf-qthresh",
308           "Keyframe super-resolution qindex threshold",
309           "Keyframe super-resolution qindex threshold, used only by SUPERRES_QTHRESH mode",
310           1, 63, DEFAULT_SUPERRES_KF_QTHRESH,
311           (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
312 
313   g_object_class_install_property (gobject_class, PROP_END_USAGE,
314       g_param_spec_enum ("end-usage", "Rate control mode",
315           "Rate control algorithm to use, indicates the end usage of this stream",
316           GST_TYPE_END_USAGE_MODE, DEFAULT_END_USAGE,
317           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
318 
319   g_object_class_install_property (gobject_class, PROP_TARGET_BITRATE,
320       g_param_spec_uint ("target-bitrate", "Target bitrate",
321           "Target bitrate, in kilobits per second",
322           1, G_MAXUINT, DEFAULT_TARGET_BITRATE,
323           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
324 
325   g_object_class_install_property (gobject_class, PROP_MIN_QUANTIZER,
326       g_param_spec_uint ("min-quantizer", "Minimum (best quality) quantizer",
327           "Mininum (best quality) quantizer",
328           0, G_MAXUINT, DEFAULT_MIN_QUANTIZER,
329           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
330 
331   g_object_class_install_property (gobject_class, PROP_MAX_QUANTIZER,
332       g_param_spec_uint ("max-quantizer", "Maximum (worst quality) quantizer",
333           "Maximum (worst quality) quantizer",
334           0, G_MAXUINT, DEFAULT_MAX_QUANTIZER,
335           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
336 
337   g_object_class_install_property (gobject_class, PROP_UNDERSHOOT_PCT,
338       g_param_spec_uint ("undershoot-pct", "Datarate undershoot (min) target",
339           "Rate control adaptation undershoot control",
340           0, 1000, DEFAULT_UNDERSHOOT_PCT,
341           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
342 
343   g_object_class_install_property (gobject_class, PROP_OVERSHOOT_PCT,
344       g_param_spec_uint ("overshoot-pct", "Datarate overshoot (max) target",
345           "Rate control adaptation overshoot control",
346           0, 1000, DEFAULT_OVERSHOOT_PCT,
347           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
348 
349   g_object_class_install_property (gobject_class, PROP_BUF_SZ,
350       g_param_spec_uint ("buf-sz", "Decoder buffer size",
351           "Decoder buffer size, expressed in units of time (milliseconds)",
352           0, G_MAXUINT, DEFAULT_BUF_SZ,
353           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
354 
355   g_object_class_install_property (gobject_class, PROP_BUF_INITIAL_SZ,
356       g_param_spec_uint ("buf-initial-sz", "Decoder buffer initial size",
357           "Decoder buffer initial size, expressed in units of time (milliseconds)",
358           0, G_MAXUINT, DEFAULT_BUF_INITIAL_SZ,
359           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
360 
361   g_object_class_install_property (gobject_class, PROP_BUF_OPTIMAL_SZ,
362       g_param_spec_uint ("buf-optimal-sz", "Decoder buffer optimal size",
363           "Decoder buffer optimal size, expressed in units of time (milliseconds)",
364           0, G_MAXUINT, DEFAULT_BUF_OPTIMAL_SZ,
365           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
366 }
367 
368 static void
gst_av1_codec_error(aom_codec_ctx_t * ctx,const char * s)369 gst_av1_codec_error (aom_codec_ctx_t * ctx, const char *s)
370 {
371   const char *detail = aom_codec_error_detail (ctx);
372 
373   GST_ERROR ("%s: %s %s", s, aom_codec_error (ctx), detail ? detail : "");
374 }
375 
376 static void
gst_av1_enc_init(GstAV1Enc * av1enc)377 gst_av1_enc_init (GstAV1Enc * av1enc)
378 {
379   GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (av1enc));
380 
381   av1enc->encoder_inited = FALSE;
382 
383   av1enc->keyframe_dist = 30;
384   av1enc->cpu_used = DEFAULT_CPU_USED;
385   av1enc->format = AOM_IMG_FMT_I420;
386 
387   av1enc->aom_cfg.rc_dropframe_thresh = DEFAULT_DROP_FRAME;
388   av1enc->aom_cfg.rc_resize_mode = DEFAULT_RESIZE_MODE;
389   av1enc->aom_cfg.rc_resize_denominator = DEFAULT_RESIZE_DENOMINATOR;
390   av1enc->aom_cfg.rc_resize_kf_denominator = DEFAULT_RESIZE_KF_DENOMINATOR;
391   av1enc->aom_cfg.rc_superres_mode = DEFAULT_SUPERRES_MODE;
392   av1enc->aom_cfg.rc_superres_denominator = DEFAULT_SUPERRES_DENOMINATOR;
393   av1enc->aom_cfg.rc_superres_kf_denominator = DEFAULT_SUPERRES_KF_DENOMINATOR;
394   av1enc->aom_cfg.rc_superres_qthresh = DEFAULT_SUPERRES_QTHRESH;
395   av1enc->aom_cfg.rc_superres_kf_qthresh = DEFAULT_SUPERRES_KF_QTHRESH;
396   av1enc->aom_cfg.rc_end_usage = DEFAULT_END_USAGE;
397   av1enc->aom_cfg.rc_target_bitrate = DEFAULT_TARGET_BITRATE;
398   av1enc->aom_cfg.rc_min_quantizer = DEFAULT_MIN_QUANTIZER;
399   av1enc->aom_cfg.rc_max_quantizer = DEFAULT_MAX_QUANTIZER;
400   av1enc->aom_cfg.rc_undershoot_pct = DEFAULT_UNDERSHOOT_PCT;
401   av1enc->aom_cfg.rc_overshoot_pct = DEFAULT_OVERSHOOT_PCT;
402   av1enc->aom_cfg.rc_buf_sz = DEFAULT_BUF_SZ;
403   av1enc->aom_cfg.rc_buf_initial_sz = DEFAULT_BUF_INITIAL_SZ;
404   av1enc->aom_cfg.rc_buf_optimal_sz = DEFAULT_BUF_OPTIMAL_SZ;
405   av1enc->aom_cfg.g_timebase.num = DEFAULT_TIMEBASE_N;
406   av1enc->aom_cfg.g_timebase.den = DEFAULT_TIMEBASE_D;
407   av1enc->aom_cfg.g_bit_depth = DEFAULT_BIT_DEPTH;
408   av1enc->aom_cfg.g_input_bit_depth = (unsigned int) DEFAULT_BIT_DEPTH;
409 
410   g_mutex_init (&av1enc->encoder_lock);
411 }
412 
413 static void
gst_av1_enc_finalize(GObject * object)414 gst_av1_enc_finalize (GObject * object)
415 {
416   GstAV1Enc *av1enc = GST_AV1_ENC (object);
417 
418   if (av1enc->input_state) {
419     gst_video_codec_state_unref (av1enc->input_state);
420   }
421   av1enc->input_state = NULL;
422 
423   gst_av1_enc_destroy_encoder (av1enc);
424   g_mutex_clear (&av1enc->encoder_lock);
425 
426   G_OBJECT_CLASS (parent_class)->finalize (object);
427 }
428 
429 static void
gst_av1_enc_set_latency(GstAV1Enc * av1enc)430 gst_av1_enc_set_latency (GstAV1Enc * av1enc)
431 {
432   GstClockTime latency;
433   gint fps_n, fps_d;
434 
435   if (av1enc->input_state->info.fps_n && av1enc->input_state->info.fps_d) {
436     fps_n = av1enc->input_state->info.fps_n;
437     fps_d = av1enc->input_state->info.fps_d;
438   } else {
439     fps_n = 25;
440     fps_d = 1;
441   }
442 
443   latency =
444       gst_util_uint64_scale (av1enc->aom_cfg.g_lag_in_frames * GST_SECOND,
445       fps_d, fps_n);
446   gst_video_encoder_set_latency (GST_VIDEO_ENCODER (av1enc), latency, latency);
447 
448   GST_DEBUG_OBJECT (av1enc, "Latency set to %" GST_TIME_FORMAT
449       " = %d frames at %d/%d fps ", GST_TIME_ARGS (latency),
450       av1enc->aom_cfg.g_lag_in_frames, fps_n, fps_d);
451 }
452 
453 static const gchar *
gst_av1_enc_get_aom_rc_mode_name(enum aom_rc_mode rc_mode)454 gst_av1_enc_get_aom_rc_mode_name (enum aom_rc_mode rc_mode)
455 {
456   switch (rc_mode) {
457     case AOM_VBR:
458       return "VBR (Variable Bit Rate)";
459     case AOM_CBR:
460       return "CBR (Constant Bit Rate)";
461     case AOM_CQ:
462       return "CQ (Constrained Quality)";
463     case AOM_Q:
464       return "Q (Constant Quality)";
465     default:
466       return "<UNKNOWN>";
467   }
468 }
469 
470 static void
gst_av1_enc_debug_encoder_cfg(struct aom_codec_enc_cfg * cfg)471 gst_av1_enc_debug_encoder_cfg (struct aom_codec_enc_cfg *cfg)
472 {
473   GST_DEBUG ("g_usage : %u", cfg->g_usage);
474   GST_DEBUG ("g_threads : %u", cfg->g_threads);
475   GST_DEBUG ("g_profile : %u", cfg->g_profile);
476   GST_DEBUG ("g_w x g_h : %u x %u", cfg->g_w, cfg->g_h);
477   GST_DEBUG ("g_bit_depth : %d", cfg->g_bit_depth);
478   GST_DEBUG ("g_input_bit_depth : %u", cfg->g_input_bit_depth);
479   GST_DEBUG ("g_timebase : %d / %d", cfg->g_timebase.num, cfg->g_timebase.den);
480   GST_DEBUG ("g_error_resilient : 0x%x", cfg->g_error_resilient);
481   GST_DEBUG ("g_pass : %d", cfg->g_pass);
482   GST_DEBUG ("g_lag_in_frames : %u", cfg->g_lag_in_frames);
483   GST_DEBUG ("rc_dropframe_thresh : %u", cfg->rc_dropframe_thresh);
484   GST_DEBUG ("rc_resize_mode : %u", cfg->rc_resize_mode);
485   GST_DEBUG ("rc_resize_denominator : %u", cfg->rc_resize_denominator);
486   GST_DEBUG ("rc_resize_kf_denominator : %u", cfg->rc_resize_kf_denominator);
487   GST_DEBUG ("rc_superres_mode : %u", cfg->rc_superres_mode);
488   GST_DEBUG ("rc_superres_denominator : %u", cfg->rc_superres_denominator);
489   GST_DEBUG ("rc_superres_kf_denominator : %u",
490       cfg->rc_superres_kf_denominator);
491   GST_DEBUG ("rc_superres_qthresh : %u", cfg->rc_superres_qthresh);
492   GST_DEBUG ("rc_superres_kf_qthresh : %u", cfg->rc_superres_kf_qthresh);
493   GST_DEBUG ("rc_end_usage : %s",
494       gst_av1_enc_get_aom_rc_mode_name (cfg->rc_end_usage));
495   /* rc_twopass_stats_in */
496   /* rc_firstpass_mb_stats_in */
497   GST_DEBUG ("rc_target_bitrate : %u (kbps)", cfg->rc_target_bitrate);
498   GST_DEBUG ("rc_min_quantizer : %u", cfg->rc_min_quantizer);
499   GST_DEBUG ("rc_max_quantizer : %u", cfg->rc_max_quantizer);
500   GST_DEBUG ("rc_undershoot_pct : %u", cfg->rc_undershoot_pct);
501   GST_DEBUG ("rc_overshoot_pct : %u", cfg->rc_overshoot_pct);
502   GST_DEBUG ("rc_buf_sz : %u (ms)", cfg->rc_buf_sz);
503   GST_DEBUG ("rc_buf_initial_sz : %u (ms)", cfg->rc_buf_initial_sz);
504   GST_DEBUG ("rc_buf_optimal_sz : %u (ms)", cfg->rc_buf_optimal_sz);
505   GST_DEBUG ("rc_2pass_vbr_bias_pct : %u (%%)", cfg->rc_2pass_vbr_bias_pct);
506   GST_DEBUG ("rc_2pass_vbr_minsection_pct : %u (%%)",
507       cfg->rc_2pass_vbr_minsection_pct);
508   GST_DEBUG ("rc_2pass_vbr_maxsection_pct : %u (%%)",
509       cfg->rc_2pass_vbr_maxsection_pct);
510   GST_DEBUG ("kf_mode : %u", cfg->kf_mode);
511   GST_DEBUG ("kf_min_dist : %u", cfg->kf_min_dist);
512   GST_DEBUG ("kf_max_dist : %u", cfg->kf_max_dist);
513   GST_DEBUG ("large_scale_tile : %u", cfg->large_scale_tile);
514   /* Tile-related values */
515 }
516 
517 static gint
gst_av1_enc_get_downstream_profile(GstAV1Enc * av1enc)518 gst_av1_enc_get_downstream_profile (GstAV1Enc * av1enc)
519 {
520   GstCaps *allowed;
521   GstStructure *s;
522   gint profile = DEFAULT_PROFILE;
523 
524   allowed = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (av1enc));
525   if (allowed) {
526     allowed = gst_caps_truncate (allowed);
527     s = gst_caps_get_structure (allowed, 0);
528     if (gst_structure_has_field (s, "profile")) {
529       const GValue *v = gst_structure_get_value (s, "profile");
530       const gchar *profile_str = NULL;
531 
532       if (GST_VALUE_HOLDS_LIST (v) && gst_value_list_get_size (v) > 0) {
533         profile_str = g_value_get_string (gst_value_list_get_value (v, 0));
534       } else if (G_VALUE_HOLDS_STRING (v)) {
535         profile_str = g_value_get_string (v);
536       }
537 
538       if (profile_str) {
539         gchar *endptr = NULL;
540 
541         profile = g_ascii_strtoull (profile_str, &endptr, 10);
542         if (*endptr != '\0' || profile < 0 || profile > 3) {
543           GST_ERROR_OBJECT (av1enc, "Invalid profile '%s'", profile_str);
544           profile = DEFAULT_PROFILE;
545         }
546       }
547     }
548     gst_caps_unref (allowed);
549   }
550 
551   GST_DEBUG_OBJECT (av1enc, "Using profile %d", profile);
552 
553   return profile;
554 }
555 
556 static void
gst_av1_enc_adjust_profile(GstAV1Enc * av1enc,GstVideoFormat format)557 gst_av1_enc_adjust_profile (GstAV1Enc * av1enc, GstVideoFormat format)
558 {
559   guint depth = av1enc->aom_cfg.g_bit_depth;
560   guint profile = av1enc->aom_cfg.g_profile;
561   gboolean update = FALSE;
562 
563   switch (profile) {
564     case 0:
565       if (depth < 12 && format == GST_VIDEO_FORMAT_Y444) {
566         profile = 1;
567         update = TRUE;
568       } else if (depth == 12 || format == GST_VIDEO_FORMAT_Y42B) {
569         profile = 2;
570         update = TRUE;
571       }
572       break;
573     case 1:
574       if (depth == 12 || format == GST_VIDEO_FORMAT_Y42B) {
575         profile = 2;
576         update = TRUE;
577       } else if (depth < 12 && format == GST_VIDEO_FORMAT_I420) {
578         profile = 0;
579         update = TRUE;
580       }
581       break;
582     case 2:
583       if (depth < 12) {
584         if (format == GST_VIDEO_FORMAT_Y444) {
585           profile = 1;
586           update = TRUE;
587         } else if (format == GST_VIDEO_FORMAT_I420) {
588           profile = 0;
589           update = TRUE;
590         }
591       }
592       break;
593     default:
594       break;
595   }
596 
597   if (update) {
598     GST_INFO_OBJECT (av1enc, "profile updated to %d from %d",
599         profile, av1enc->aom_cfg.g_profile);
600     av1enc->aom_cfg.g_profile = profile;
601   }
602 }
603 
604 static gboolean
gst_av1_enc_set_format(GstVideoEncoder * encoder,GstVideoCodecState * state)605 gst_av1_enc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state)
606 {
607   GstVideoCodecState *output_state;
608   GstAV1Enc *av1enc = GST_AV1_ENC_CAST (encoder);
609   GstAV1EncClass *av1enc_class = GST_AV1_ENC_GET_CLASS (av1enc);
610   GstVideoInfo *info = &state->info;
611 
612   output_state =
613       gst_video_encoder_set_output_state (encoder,
614       gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder)),
615       state);
616   gst_video_codec_state_unref (output_state);
617 
618   if (av1enc->input_state) {
619     gst_video_codec_state_unref (av1enc->input_state);
620   }
621   av1enc->input_state = gst_video_codec_state_ref (state);
622 
623   g_mutex_lock (&av1enc->encoder_lock);
624   gst_av1_enc_set_latency (av1enc);
625 
626   av1enc->aom_cfg.g_profile = gst_av1_enc_get_downstream_profile (av1enc);
627 
628   /* Scale default bitrate to our size */
629   if (!av1enc->target_bitrate_set)
630     av1enc->aom_cfg.rc_target_bitrate =
631         gst_util_uint64_scale (DEFAULT_TARGET_BITRATE,
632         GST_VIDEO_INFO_WIDTH (info) * GST_VIDEO_INFO_HEIGHT (info), 320 * 240);
633 
634   av1enc->aom_cfg.g_w = GST_VIDEO_INFO_WIDTH (info);
635   av1enc->aom_cfg.g_h = GST_VIDEO_INFO_HEIGHT (info);
636   /* Recommended method is to set the timebase to that of the parent
637    * container or multimedia framework (ex: 1/1000 for ms, as in FLV) */
638   av1enc->aom_cfg.g_timebase.num = GST_VIDEO_INFO_FPS_D (info);
639   av1enc->aom_cfg.g_timebase.den = GST_VIDEO_INFO_FPS_N (info);
640   av1enc->aom_cfg.g_error_resilient = AOM_ERROR_RESILIENT_DEFAULT;
641   /* TODO: do more configuration including bit_depth config */
642 
643   av1enc->format =
644       gst_video_format_to_av1_img_format (GST_VIDEO_INFO_FORMAT (info));
645 
646   if (av1enc->aom_cfg.g_bit_depth != DEFAULT_BIT_DEPTH) {
647     av1enc->aom_cfg.g_input_bit_depth = av1enc->aom_cfg.g_bit_depth;
648     if (av1enc->aom_cfg.g_bit_depth > 8)
649       av1enc->format |= AOM_IMG_FMT_HIGHBITDEPTH;
650   }
651 
652   /* Adjust profile according to format and bit-depth */
653   gst_av1_enc_adjust_profile (av1enc, GST_VIDEO_INFO_FORMAT (info));
654 
655   GST_DEBUG_OBJECT (av1enc, "Calling encoder init with config:");
656   gst_av1_enc_debug_encoder_cfg (&av1enc->aom_cfg);
657 
658   if (aom_codec_enc_init (&av1enc->encoder, av1enc_class->codec_algo,
659           &av1enc->aom_cfg, 0)) {
660     gst_av1_codec_error (&av1enc->encoder, "Failed to initialize encoder");
661     return FALSE;
662   }
663   av1enc->encoder_inited = TRUE;
664 
665   GST_AV1_ENC_APPLY_CODEC_CONTROL (av1enc, AOME_SET_CPUUSED, av1enc->cpu_used);
666   g_mutex_unlock (&av1enc->encoder_lock);
667 
668   return TRUE;
669 }
670 
671 static GstFlowReturn
gst_av1_enc_process(GstAV1Enc * encoder)672 gst_av1_enc_process (GstAV1Enc * encoder)
673 {
674   aom_codec_iter_t iter = NULL;
675   const aom_codec_cx_pkt_t *pkt;
676   GstVideoCodecFrame *frame;
677   GstVideoEncoder *video_encoder;
678   GstFlowReturn ret = GST_FLOW_CUSTOM_SUCCESS;
679 
680   video_encoder = GST_VIDEO_ENCODER (encoder);
681 
682   while ((pkt = aom_codec_get_cx_data (&encoder->encoder, &iter)) != NULL) {
683     if (pkt->kind == AOM_CODEC_STATS_PKT) {
684       GST_WARNING_OBJECT (encoder, "Unhandled stats packet");
685     } else if (pkt->kind == AOM_CODEC_FPMB_STATS_PKT) {
686       GST_WARNING_OBJECT (encoder, "Unhandled FPMB pkt");
687     } else if (pkt->kind == AOM_CODEC_PSNR_PKT) {
688       GST_WARNING_OBJECT (encoder, "Unhandled PSNR packet");
689     } else if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
690       frame = gst_video_encoder_get_oldest_frame (video_encoder);
691       g_assert (frame != NULL);
692       if ((pkt->data.frame.flags & AOM_FRAME_IS_KEY) != 0) {
693         GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
694       } else {
695         GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
696       }
697 
698       frame->output_buffer =
699           gst_buffer_new_wrapped (g_memdup (pkt->data.frame.buf,
700               pkt->data.frame.sz), pkt->data.frame.sz);
701 
702       if ((pkt->data.frame.flags & AOM_FRAME_IS_DROPPABLE) != 0)
703         GST_BUFFER_FLAG_SET (frame->output_buffer, GST_BUFFER_FLAG_DROPPABLE);
704 
705       ret = gst_video_encoder_finish_frame (video_encoder, frame);
706       if (ret != GST_FLOW_OK)
707         break;
708     }
709   }
710 
711   return ret;
712 }
713 
714 static void
gst_av1_enc_fill_image(GstAV1Enc * enc,GstVideoFrame * frame,aom_image_t * image)715 gst_av1_enc_fill_image (GstAV1Enc * enc, GstVideoFrame * frame,
716     aom_image_t * image)
717 {
718   image->planes[AOM_PLANE_Y] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
719   image->planes[AOM_PLANE_U] = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
720   image->planes[AOM_PLANE_V] = GST_VIDEO_FRAME_COMP_DATA (frame, 2);
721 
722   image->stride[AOM_PLANE_Y] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
723   image->stride[AOM_PLANE_U] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1);
724   image->stride[AOM_PLANE_V] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2);
725 }
726 
727 static GstFlowReturn
gst_av1_enc_handle_frame(GstVideoEncoder * encoder,GstVideoCodecFrame * frame)728 gst_av1_enc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
729 {
730   GstAV1Enc *av1enc = GST_AV1_ENC_CAST (encoder);
731   aom_image_t raw;
732   int flags = 0;
733   GstFlowReturn ret = GST_FLOW_OK;
734   GstVideoFrame vframe;
735 
736   if (!aom_img_alloc (&raw, av1enc->format, av1enc->aom_cfg.g_w,
737           av1enc->aom_cfg.g_h, 1)) {
738     GST_ERROR_OBJECT (encoder, "Failed to initialize encoder");
739     return FALSE;
740   }
741 
742   gst_video_frame_map (&vframe, &av1enc->input_state->info,
743       frame->input_buffer, GST_MAP_READ);
744   gst_av1_enc_fill_image (av1enc, &vframe, &raw);
745   gst_video_frame_unmap (&vframe);
746 
747   if (av1enc->keyframe_dist >= 30) {
748     av1enc->keyframe_dist = 0;
749     flags |= AOM_EFLAG_FORCE_KF;
750   }
751   av1enc->keyframe_dist++;
752 
753   g_mutex_lock (&av1enc->encoder_lock);
754   if (aom_codec_encode (&av1enc->encoder, &raw, frame->pts, 1, flags)
755       != AOM_CODEC_OK) {
756     gst_av1_codec_error (&av1enc->encoder, "Failed to encode frame");
757     ret = GST_FLOW_ERROR;
758   }
759   g_mutex_unlock (&av1enc->encoder_lock);
760 
761   aom_img_free (&raw);
762   gst_video_codec_frame_unref (frame);
763 
764   if (ret == GST_FLOW_ERROR)
765     return ret;
766 
767   ret = gst_av1_enc_process (av1enc);
768 
769   if (ret == GST_FLOW_CUSTOM_SUCCESS)
770     ret = GST_FLOW_OK;
771 
772   return ret;
773 }
774 
775 static GstFlowReturn
gst_av1_enc_finish(GstVideoEncoder * encoder)776 gst_av1_enc_finish (GstVideoEncoder * encoder)
777 {
778   GstFlowReturn ret = GST_FLOW_OK;
779   GstAV1Enc *av1enc = GST_AV1_ENC_CAST (encoder);
780 
781   while (ret == GST_FLOW_OK) {
782     GST_DEBUG_OBJECT (encoder, "Calling finish");
783     g_mutex_lock (&av1enc->encoder_lock);
784     if (aom_codec_encode (&av1enc->encoder, NULL, 0, 1, 0)
785         != AOM_CODEC_OK) {
786       gst_av1_codec_error (&av1enc->encoder, "Failed to encode frame");
787       ret = GST_FLOW_ERROR;
788     }
789     g_mutex_unlock (&av1enc->encoder_lock);
790 
791     ret = gst_av1_enc_process (av1enc);
792   }
793 
794 
795   if (ret == GST_FLOW_CUSTOM_SUCCESS)
796     ret = GST_FLOW_OK;
797 
798   return ret;
799 }
800 
801 static void
gst_av1_enc_destroy_encoder(GstAV1Enc * av1enc)802 gst_av1_enc_destroy_encoder (GstAV1Enc * av1enc)
803 {
804   g_mutex_lock (&av1enc->encoder_lock);
805   if (av1enc->encoder_inited) {
806     aom_codec_destroy (&av1enc->encoder);
807     av1enc->encoder_inited = FALSE;
808   }
809   g_mutex_unlock (&av1enc->encoder_lock);
810 }
811 
812 static gboolean
gst_av1_enc_propose_allocation(GstVideoEncoder * encoder,GstQuery * query)813 gst_av1_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
814 {
815   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
816 
817   return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
818       query);
819 }
820 
821 static void
gst_av1_enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)822 gst_av1_enc_set_property (GObject * object, guint prop_id,
823     const GValue * value, GParamSpec * pspec)
824 {
825   GstAV1Enc *av1enc = GST_AV1_ENC_CAST (object);
826   gboolean global = FALSE;
827   aom_codec_err_t status;
828 
829   GST_OBJECT_LOCK (av1enc);
830 
831   g_mutex_lock (&av1enc->encoder_lock);
832   switch (prop_id) {
833     case PROP_CPU_USED:
834       av1enc->cpu_used = g_value_get_int (value);
835       GST_AV1_ENC_APPLY_CODEC_CONTROL (av1enc, AOME_SET_CPUUSED,
836           av1enc->cpu_used);
837       break;
838     case PROP_DROP_FRAME:
839       av1enc->aom_cfg.rc_dropframe_thresh = g_value_get_uint (value);
840       global = TRUE;
841       break;
842     case PROP_RESIZE_MODE:
843       av1enc->aom_cfg.rc_resize_mode = g_value_get_enum (value);
844       global = TRUE;
845       break;
846     case PROP_RESIZE_DENOMINATOR:
847       av1enc->aom_cfg.rc_resize_denominator = g_value_get_uint (value);
848       global = TRUE;
849       break;
850     case PROP_RESIZE_KF_DENOMINATOR:
851       av1enc->aom_cfg.rc_resize_kf_denominator = g_value_get_uint (value);
852       global = TRUE;
853       break;
854     case PROP_SUPERRES_MODE:
855       av1enc->aom_cfg.rc_superres_mode = g_value_get_enum (value);
856       global = TRUE;
857       break;
858     case PROP_SUPERRES_DENOMINATOR:
859       av1enc->aom_cfg.rc_superres_denominator = g_value_get_uint (value);
860       global = TRUE;
861       break;
862     case PROP_SUPERRES_KF_DENOMINATOR:
863       av1enc->aom_cfg.rc_superres_kf_denominator = g_value_get_uint (value);
864       global = TRUE;
865       break;
866     case PROP_SUPERRES_QTHRESH:
867       av1enc->aom_cfg.rc_superres_qthresh = g_value_get_uint (value);
868       global = TRUE;
869       break;
870     case PROP_SUPERRES_KF_QTHRESH:
871       av1enc->aom_cfg.rc_superres_kf_qthresh = g_value_get_uint (value);
872       global = TRUE;
873       break;
874     case PROP_END_USAGE:
875       av1enc->aom_cfg.rc_end_usage = g_value_get_enum (value);
876       global = TRUE;
877       break;
878     case PROP_TARGET_BITRATE:
879       av1enc->aom_cfg.rc_target_bitrate = g_value_get_uint (value);
880       av1enc->target_bitrate_set = TRUE;
881       global = TRUE;
882       break;
883     case PROP_MIN_QUANTIZER:
884       av1enc->aom_cfg.rc_min_quantizer = g_value_get_uint (value);
885       global = TRUE;
886       break;
887     case PROP_MAX_QUANTIZER:
888       av1enc->aom_cfg.rc_max_quantizer = g_value_get_uint (value);
889       global = TRUE;
890       break;
891     case PROP_UNDERSHOOT_PCT:
892       av1enc->aom_cfg.rc_undershoot_pct = g_value_get_uint (value);
893       global = TRUE;
894       break;
895     case PROP_OVERSHOOT_PCT:
896       av1enc->aom_cfg.rc_overshoot_pct = g_value_get_uint (value);
897       global = TRUE;
898       break;
899     case PROP_BUF_SZ:
900       av1enc->aom_cfg.rc_buf_sz = g_value_get_uint (value);
901       global = TRUE;
902       break;
903     case PROP_BUF_INITIAL_SZ:
904       av1enc->aom_cfg.rc_buf_initial_sz = g_value_get_uint (value);
905       global = TRUE;
906       break;
907     case PROP_BUF_OPTIMAL_SZ:
908       av1enc->aom_cfg.rc_buf_optimal_sz = g_value_get_uint (value);
909       global = TRUE;
910       break;
911     default:
912       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
913       break;
914   }
915 
916   if (global &&av1enc->encoder_inited) {
917     status = aom_codec_enc_config_set (&av1enc->encoder, &av1enc->aom_cfg);
918     GST_DEBUG_OBJECT (av1enc, "Set %s encoder configuration, ret = %s",
919         pspec->name, gst_av1_get_error_name (status));
920   }
921 
922   g_mutex_unlock (&av1enc->encoder_lock);
923   GST_OBJECT_UNLOCK (av1enc);
924 }
925 
926 static void
gst_av1_enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)927 gst_av1_enc_get_property (GObject * object, guint prop_id, GValue * value,
928     GParamSpec * pspec)
929 {
930   GstAV1Enc *av1enc = GST_AV1_ENC_CAST (object);
931 
932   GST_OBJECT_LOCK (av1enc);
933 
934   switch (prop_id) {
935     case PROP_CPU_USED:
936       g_value_set_int (value, av1enc->cpu_used);
937       break;
938     case PROP_DROP_FRAME:
939       g_value_set_uint (value, av1enc->aom_cfg.rc_dropframe_thresh);
940       break;
941     case PROP_RESIZE_MODE:
942       g_value_set_enum (value, av1enc->aom_cfg.rc_resize_mode);
943       break;
944     case PROP_RESIZE_DENOMINATOR:
945       g_value_set_uint (value, av1enc->aom_cfg.rc_resize_denominator);
946       break;
947     case PROP_RESIZE_KF_DENOMINATOR:
948       g_value_set_uint (value, av1enc->aom_cfg.rc_resize_kf_denominator);
949       break;
950     case PROP_SUPERRES_MODE:
951       g_value_set_enum (value, av1enc->aom_cfg.rc_superres_mode);
952       break;
953     case PROP_SUPERRES_DENOMINATOR:
954       g_value_set_uint (value, av1enc->aom_cfg.rc_superres_denominator);
955       break;
956     case PROP_SUPERRES_KF_DENOMINATOR:
957       g_value_set_uint (value, av1enc->aom_cfg.rc_superres_kf_denominator);
958       break;
959     case PROP_SUPERRES_QTHRESH:
960       g_value_set_uint (value, av1enc->aom_cfg.rc_superres_qthresh);
961       break;
962     case PROP_SUPERRES_KF_QTHRESH:
963       g_value_set_uint (value, av1enc->aom_cfg.rc_superres_kf_qthresh);
964       break;
965     case PROP_END_USAGE:
966       g_value_set_enum (value, av1enc->aom_cfg.rc_end_usage);
967       break;
968     case PROP_TARGET_BITRATE:
969       g_value_set_uint (value, av1enc->aom_cfg.rc_target_bitrate);
970       break;
971     case PROP_MIN_QUANTIZER:
972       g_value_set_uint (value, av1enc->aom_cfg.rc_min_quantizer);
973       break;
974     case PROP_MAX_QUANTIZER:
975       g_value_set_uint (value, av1enc->aom_cfg.rc_max_quantizer);
976       break;
977     case PROP_UNDERSHOOT_PCT:
978       g_value_set_uint (value, av1enc->aom_cfg.rc_undershoot_pct);
979       break;
980     case PROP_OVERSHOOT_PCT:
981       g_value_set_uint (value, av1enc->aom_cfg.rc_overshoot_pct);
982       break;
983     case PROP_BUF_SZ:
984       g_value_set_uint (value, av1enc->aom_cfg.rc_buf_sz);
985       break;
986     case PROP_BUF_INITIAL_SZ:
987       g_value_set_uint (value, av1enc->aom_cfg.rc_buf_initial_sz);
988       break;
989     case PROP_BUF_OPTIMAL_SZ:
990       g_value_set_uint (value, av1enc->aom_cfg.rc_buf_optimal_sz);
991       break;
992     default:
993       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
994       break;
995   }
996 
997   GST_OBJECT_UNLOCK (av1enc);
998 }
999 
1000 static gboolean
gst_av1_enc_start(GstVideoEncoder * encoder)1001 gst_av1_enc_start (GstVideoEncoder * encoder)
1002 {
1003   return TRUE;
1004 }
1005 
1006 static gboolean
gst_av1_enc_stop(GstVideoEncoder * encoder)1007 gst_av1_enc_stop (GstVideoEncoder * encoder)
1008 {
1009   GstAV1Enc *av1enc = GST_AV1_ENC_CAST (encoder);
1010 
1011   if (av1enc->input_state) {
1012     gst_video_codec_state_unref (av1enc->input_state);
1013   }
1014   av1enc->input_state = NULL;
1015 
1016   gst_av1_enc_destroy_encoder (av1enc);
1017 
1018   return TRUE;
1019 }
1020