msdkenc: set ROI region for msdk{h264, h265}enc
authorHaihao Xiang <haihao.xiang@intel.com>
Wed, 27 Nov 2019 08:00:59 +0000 (16:00 +0800)
committerHaihao Xiang <haihao.xiang@intel.com>
Wed, 15 Jan 2020 00:47:12 +0000 (00:47 +0000)
A reconfig is needed when ROI is changed, otherwise the ROI parameters won't
take effect

sys/msdk/gstmsdkenc.c
sys/msdk/gstmsdkenc.h
sys/msdk/gstmsdkh264enc.c
sys/msdk/gstmsdkh264enc.h
sys/msdk/gstmsdkh265enc.c
sys/msdk/gstmsdkh265enc.h

index 9e9fc54..8570285 100644 (file)
@@ -237,6 +237,115 @@ gst_msdkenc_ensure_extended_coding_options (GstMsdkEnc * thiz)
   }
 }
 
+/* Return TRUE if ROI is changed and update ROI parameters in encoder_roi */
+gboolean
+gst_msdkenc_get_roi_params (GstMsdkEnc * thiz,
+    GstVideoCodecFrame * frame, mfxExtEncoderROI * encoder_roi)
+{
+  GstBuffer *input;
+  guint num_roi, i, num_valid_roi = 0;
+  gushort roi_mode = G_MAXUINT16;
+  gpointer state = NULL;
+  mfxExtEncoderROI *curr_roi = encoder_roi;
+  mfxExtEncoderROI *prev_roi = encoder_roi + 1;
+
+  if (!frame || !frame->input_buffer)
+    return FALSE;
+
+  memset (curr_roi, 0, sizeof (mfxExtEncoderROI));
+  input = frame->input_buffer;
+
+  num_roi =
+      gst_buffer_get_n_meta (input, GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE);
+
+  if (num_roi == 0)
+    goto end;
+
+  curr_roi->Header.BufferId = MFX_EXTBUFF_ENCODER_ROI;
+  curr_roi->Header.BufferSz = sizeof (mfxExtEncoderROI);
+
+  for (i = 0; i < num_roi && num_valid_roi < 256; i++) {
+    GstVideoRegionOfInterestMeta *roi;
+    GstStructure *s;
+
+    roi = (GstVideoRegionOfInterestMeta *)
+        gst_buffer_iterate_meta_filtered (input, &state,
+        GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE);
+
+    if (!roi)
+      continue;
+
+    /* ignore roi if overflow */
+    if ((roi->x > G_MAXINT16) || (roi->y > G_MAXINT16)
+        || (roi->w > G_MAXUINT16) || (roi->h > G_MAXUINT16)) {
+      GST_DEBUG_OBJECT (thiz, "Ignoring ROI... ROI overflow");
+      continue;
+    }
+
+    GST_LOG ("Input buffer ROI: type=%s id=%d (%d, %d) %dx%d",
+        g_quark_to_string (roi->roi_type), roi->id, roi->x, roi->y, roi->w,
+        roi->h);
+
+    curr_roi->ROI[num_valid_roi].Left = roi->x;
+    curr_roi->ROI[num_valid_roi].Top = roi->y;
+    curr_roi->ROI[num_valid_roi].Right = roi->x + roi->w;
+    curr_roi->ROI[num_valid_roi].Bottom = roi->y + roi->h;
+
+    s = gst_video_region_of_interest_meta_get_param (roi, "roi/msdk");
+
+    if (s) {
+      int value = 0;
+
+      if (roi_mode == G_MAXUINT16) {
+        if (gst_structure_get_int (s, "delta-qp", &value)) {
+#if (MFX_VERSION >= 1022)
+          roi_mode = MFX_ROI_MODE_QP_DELTA;
+          curr_roi->ROI[num_valid_roi].DeltaQP = CLAMP (value, -51, 51);
+          GST_LOG ("Use delta-qp %d", value);
+#else
+          GST_WARNING
+              ("Ignore delta QP because the MFX doesn't support delta QP mode");
+#endif
+        } else if (gst_structure_get_int (s, "priority", &value)) {
+          roi_mode = MFX_ROI_MODE_PRIORITY;
+          curr_roi->ROI[num_valid_roi].Priority = CLAMP (value, -3, 3);
+          GST_LOG ("Use priority %d", value);
+        } else
+          continue;
+#if (MFX_VERSION >= 1022)
+      } else if (roi_mode == MFX_ROI_MODE_QP_DELTA &&
+          gst_structure_get_int (s, "delta-qp", &value)) {
+        curr_roi->ROI[num_valid_roi].DeltaQP = CLAMP (value, -51, 51);
+#endif
+      } else if (roi_mode == MFX_ROI_MODE_PRIORITY &&
+          gst_structure_get_int (s, "priority", &value)) {
+        curr_roi->ROI[num_valid_roi].Priority = CLAMP (value, -3, 3);
+      } else
+        continue;
+
+      num_valid_roi++;
+    }
+  }
+
+#if (MFX_VERSION >= 1022)
+  curr_roi->ROIMode = roi_mode;
+#endif
+
+  curr_roi->NumROI = num_valid_roi;
+
+end:
+  if (curr_roi->NumROI == 0 && prev_roi->NumROI == 0)
+    return FALSE;
+
+  if (curr_roi->NumROI != prev_roi->NumROI ||
+      memcmp (curr_roi, prev_roi, sizeof (mfxExtEncoderROI)) != 0) {
+    *prev_roi = *curr_roi;
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
 static gboolean
 gst_msdkenc_init_encoder (GstMsdkEnc * thiz)
 {
index bce8139..9895874 100644 (file)
@@ -204,6 +204,9 @@ gst_msdkenc_get_common_property (GObject * object, guint prop_id,
 void
 gst_msdkenc_ensure_extended_coding_options (GstMsdkEnc * thiz);
 
+gboolean
+gst_msdkenc_get_roi_params (GstMsdkEnc * thiz,
+    GstVideoCodecFrame * frame, mfxExtEncoderROI * encoder_roi);
 G_END_DECLS
 
 #endif /* __GST_MSDKENC_H__ */
index b77d15c..62e0265 100644 (file)
@@ -480,6 +480,24 @@ gst_msdkh264enc_get_property (GObject * object, guint prop_id, GValue * value,
   GST_OBJECT_UNLOCK (thiz);
 }
 
+static gboolean
+gst_msdkh264enc_need_reconfig (GstMsdkEnc * encoder, GstVideoCodecFrame * frame)
+{
+  GstMsdkH264Enc *h264enc = GST_MSDKH264ENC (encoder);
+
+  return gst_msdkenc_get_roi_params (encoder, frame, h264enc->roi);
+}
+
+static void
+gst_msdkh264enc_set_extra_params (GstMsdkEnc * encoder,
+    GstVideoCodecFrame * frame)
+{
+  GstMsdkH264Enc *h264enc = GST_MSDKH264ENC (encoder);
+
+  if (h264enc->roi[0].NumROI)
+    gst_msdkenc_add_extra_param (encoder, (mfxExtBuffer *) & h264enc->roi[0]);
+}
+
 static void
 gst_msdkh264enc_class_init (GstMsdkH264EncClass * klass)
 {
@@ -501,6 +519,8 @@ gst_msdkh264enc_class_init (GstMsdkH264EncClass * klass)
   encoder_class->set_format = gst_msdkh264enc_set_format;
   encoder_class->configure = gst_msdkh264enc_configure;
   encoder_class->set_src_caps = gst_msdkh264enc_set_src_caps;
+  encoder_class->need_reconfig = gst_msdkh264enc_need_reconfig;
+  encoder_class->set_extra_params = gst_msdkh264enc_set_extra_params;
 
   gst_msdkenc_install_common_properties (encoder_class);
 
index e8b0b1b..700dd4f 100644 (file)
@@ -55,6 +55,8 @@ struct _GstMsdkH264Enc
   GstMsdkEnc base;
 
   mfxExtCodingOption option;
+  /* roi[0] for current ROI and roi[1] for previous ROI */
+  mfxExtEncoderROI roi[2];
 
   gint profile;
   gint level;
index 0d15be7..5ce07b0 100644 (file)
@@ -286,6 +286,24 @@ gst_msdkh265enc_get_property (GObject * object, guint prop_id, GValue * value,
   GST_OBJECT_UNLOCK (thiz);
 }
 
+static gboolean
+gst_msdkh265enc_need_reconfig (GstMsdkEnc * encoder, GstVideoCodecFrame * frame)
+{
+  GstMsdkH265Enc *h265enc = GST_MSDKH265ENC (encoder);
+
+  return gst_msdkenc_get_roi_params (encoder, frame, h265enc->roi);
+}
+
+static void
+gst_msdkh265enc_set_extra_params (GstMsdkEnc * encoder,
+    GstVideoCodecFrame * frame)
+{
+  GstMsdkH265Enc *h265enc = GST_MSDKH265ENC (encoder);
+
+  if (h265enc->roi[0].NumROI)
+    gst_msdkenc_add_extra_param (encoder, (mfxExtBuffer *) & h265enc->roi[0]);
+}
+
 static void
 gst_msdkh265enc_class_init (GstMsdkH265EncClass * klass)
 {
@@ -303,6 +321,8 @@ gst_msdkh265enc_class_init (GstMsdkH265EncClass * klass)
   encoder_class->set_format = gst_msdkh265enc_set_format;
   encoder_class->configure = gst_msdkh265enc_configure;
   encoder_class->set_src_caps = gst_msdkh265enc_set_src_caps;
+  encoder_class->need_reconfig = gst_msdkh265enc_need_reconfig;
+  encoder_class->set_extra_params = gst_msdkh265enc_set_extra_params;
 
   gst_msdkenc_install_common_properties (encoder_class);
 
index 68892bd..e6b75a6 100644 (file)
@@ -59,6 +59,8 @@ struct _GstMsdkH265Enc
   gushort num_tile_cols;
 
   mfxExtHEVCTiles ext_tiles;
+  /* roi[0] for current ROI and roi[1] for previous ROI */
+  mfxExtEncoderROI roi[2];
 };
 
 struct _GstMsdkH265EncClass