aom: Implement cpu-used in av1enc
authorSean DuBois <sean@siobud.com>
Mon, 5 Feb 2018 08:52:55 +0000 (08:52 +0000)
committerSebastian Dröge <sebastian@centricular.com>
Wed, 14 Feb 2018 08:19:40 +0000 (10:19 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=791674

ext/aom/gstav1enc.c
ext/aom/gstav1enc.h

index 748b3eeeba771ae242e7126f917aaccac811cd97..84b4b93ee1d9191609b1af84f582f95952d490b6 100644 (file)
 #include <gst/video/gstvideometa.h>
 #include <gst/base/base.h>
 
+#define GST_AV1_ENC_APPLY_CODEC_CONTROL(av1enc, flag, value)             \
+  if (av1enc->encoder_inited) {                                        \
+    if (aom_codec_control (&av1enc->encoder, flag,                     \
+            value) != AOM_CODEC_OK) {                                  \
+      gst_av1_codec_error (&av1enc->encoder, "Failed to set " #flag);  \
+    }                                                                  \
+  }
+
 GST_DEBUG_CATEGORY_STATIC (av1_enc_debug);
 #define GST_CAT_DEFAULT av1_enc_debug
 
@@ -48,9 +56,12 @@ enum
 
 enum
 {
-  PROP_0
+  PROP_0,
+  PROP_CPU_USED
 };
 
+#define PROP_CPU_USED_DEFAULT 0
+
 static void gst_av1_enc_finalize (GObject * object);
 static void gst_av1_enc_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -124,6 +135,12 @@ gst_av1_enc_class_init (GstAV1EncClass * klass)
 
   klass->codec_algo = &aom_codec_av1_cx_algo;
   GST_DEBUG_CATEGORY_INIT (av1_enc_debug, "av1enc", 0, "AV1 encoding element");
+
+  g_object_class_install_property (gobject_class, PROP_CPU_USED,
+      g_param_spec_int ("cpu-used", "CPU Used",
+          "CPU Used. A Value greater than 0 will increase encoder speed at the expense of quality.",
+          0, 8, PROP_CPU_USED_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -139,8 +156,12 @@ gst_av1_enc_init (GstAV1Enc * av1enc)
 {
   GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (av1enc));
 
-  av1enc->keyframe_dist = 30;
   av1enc->encoder_inited = FALSE;
+
+  av1enc->keyframe_dist = 30;
+  av1enc->cpu_used = PROP_CPU_USED_DEFAULT;
+
+  g_mutex_init (&av1enc->encoder_lock);
 }
 
 static void
@@ -154,6 +175,7 @@ gst_av1_enc_finalize (GObject * object)
   av1enc->input_state = NULL;
 
   gst_av1_enc_destroy_encoder (av1enc);
+  g_mutex_clear (&av1enc->encoder_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -253,6 +275,7 @@ gst_av1_enc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state)
 
   gst_av1_enc_set_latency (av1enc);
 
+  g_mutex_lock (&av1enc->encoder_lock);
   if (aom_codec_enc_config_default (av1enc_class->codec_algo, &av1enc->aom_cfg,
           0)) {
     gst_av1_codec_error (&av1enc->encoder,
@@ -281,6 +304,9 @@ gst_av1_enc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state)
   }
   av1enc->encoder_inited = TRUE;
 
+  GST_AV1_ENC_APPLY_CODEC_CONTROL (av1enc, AOME_SET_CPUUSED, av1enc->cpu_used);
+  g_mutex_unlock (&av1enc->encoder_lock);
+
   return TRUE;
 }
 
@@ -359,11 +385,13 @@ gst_av1_enc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
   }
   av1enc->keyframe_dist++;
 
+  g_mutex_lock (&av1enc->encoder_lock);
   if (aom_codec_encode (&av1enc->encoder, &raw, frame->pts, 1, flags)
       != AOM_CODEC_OK) {
     gst_av1_codec_error (&av1enc->encoder, "Failed to encode frame");
     ret = GST_FLOW_ERROR;
   }
+  g_mutex_unlock (&av1enc->encoder_lock);
 
   aom_img_free (&raw);
   gst_video_codec_frame_unref (frame);
@@ -377,10 +405,12 @@ gst_av1_enc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
 static void
 gst_av1_enc_destroy_encoder (GstAV1Enc * av1enc)
 {
+  g_mutex_lock (&av1enc->encoder_lock);
   if (av1enc->encoder_inited) {
     aom_codec_destroy (&av1enc->encoder);
     av1enc->encoder_inited = FALSE;
   }
+  g_mutex_unlock (&av1enc->encoder_lock);
 }
 
 static gboolean
@@ -400,11 +430,18 @@ gst_av1_enc_set_property (GObject * object, guint prop_id,
 
   GST_OBJECT_LOCK (av1enc);
 
+  g_mutex_lock (&av1enc->encoder_lock);
   switch (prop_id) {
+    case PROP_CPU_USED:
+      av1enc->cpu_used = g_value_get_int (value);
+      GST_AV1_ENC_APPLY_CODEC_CONTROL (av1enc, AOME_SET_CPUUSED,
+          av1enc->cpu_used);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
+  g_mutex_unlock (&av1enc->encoder_lock);
 
   GST_OBJECT_UNLOCK (av1enc);
 }
@@ -418,6 +455,8 @@ gst_av1_enc_get_property (GObject * object, guint prop_id, GValue * value,
   GST_OBJECT_LOCK (av1enc);
 
   switch (prop_id) {
+    case PROP_CPU_USED:
+      g_value_set_int (value, av1enc->cpu_used);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
index 60fb79435af9e970db2e5d4414e416a4de4a1c13..dcb7590f6b5802a053b716fede20cd168271894e 100644 (file)
@@ -53,14 +53,16 @@ struct _GstAV1Enc
 {
   GstVideoEncoder base_video_encoder;
 
-  gboolean encoder_inited;
-
+  /* properties */
   guint keyframe_dist;
+  gint cpu_used;
 
+  /* state */
+  gboolean encoder_inited;
+  GstVideoCodecState *input_state;
   aom_codec_enc_cfg_t aom_cfg;
   aom_codec_ctx_t encoder;
-
-  GstVideoCodecState *input_state;
+  GMutex encoder_lock;
 };
 
 struct _GstAV1EncClass