summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/openh264/gstopenh264enc.cpp174
1 files changed, 167 insertions, 7 deletions
diff --git a/ext/openh264/gstopenh264enc.cpp b/ext/openh264/gstopenh264enc.cpp
index 178c22ee6..31eb0fdaa 100644
--- a/ext/openh264/gstopenh264enc.cpp
+++ b/ext/openh264/gstopenh264enc.cpp
@@ -85,6 +85,53 @@ gst_openh264enc_rc_modes_get_type (void)
return rc_modes_type;
}
+typedef enum _GstOpenh264encDeblockingMode
+{
+ GST_OPENH264_DEBLOCKING_ON = 0,
+ GST_OPENH264_DEBLOCKING_OFF = 1,
+ GST_OPENH264_DEBLOCKING_NOT_SLICE_BOUNDARIES = 2
+} GstOpenh264encDeblockingMode;
+
+#define GST_TYPE_OPENH264ENC_DEBLOCKING_MODE (gst_openh264enc_deblocking_mode_get_type ())
+static GType
+gst_openh264enc_deblocking_mode_get_type (void)
+{
+ static const GEnumValue types[] = {
+ {GST_OPENH264_DEBLOCKING_ON, "Deblocking on", "on"},
+ {GST_OPENH264_DEBLOCKING_OFF, "Deblocking off", "off"},
+ {GST_OPENH264_DEBLOCKING_NOT_SLICE_BOUNDARIES,
+ "Deblocking on, except for slice boundaries", "not-slice-boundaries"},
+ {0, NULL, NULL},
+ };
+ static volatile GType id = 0;
+
+ if (g_once_init_enter ((gsize *) & id)) {
+ GType _id = g_enum_register_static ("GstOpenh264encDeblockingModes", types);
+ g_once_init_leave ((gsize *) & id, _id);
+ }
+
+ return id;
+}
+
+#define GST_TYPE_OPENH264ENC_SLICE_MODE (gst_openh264enc_slice_mode_get_type ())
+static GType
+gst_openh264enc_slice_mode_get_type (void)
+{
+ static const GEnumValue types[] = {
+ {SM_FIXEDSLCNUM_SLICE, "num-slices slices", "n-slices"},
+ {SM_AUTO_SLICE, "Number of slices equal to number of threads", "auto"},
+ {0, NULL, NULL},
+ };
+ static volatile GType id = 0;
+
+ if (g_once_init_enter ((gsize *) & id)) {
+ GType _id = g_enum_register_static ("GstOpenh264encSliceModes", types);
+ g_once_init_leave ((gsize *) & id, _id);
+ }
+
+ return id;
+}
+
/* prototypes */
static void gst_openh264enc_set_property (GObject * object,
@@ -117,6 +164,12 @@ static void gst_openh264enc_set_rate_control (GstOpenh264Enc * openh264enc,
#define DEFAULT_MULTI_THREAD 0
#define DEFAULT_ENABLE_DENOISE FALSE
#define DEFAULT_ENABLE_FRAME_SKIP FALSE
+#define DEFAULT_DEBLOCKING_MODE GST_OPENH264_DEBLOCKING_ON
+#define DEFAULT_BACKGROUND_DETECTION TRUE
+#define DEFAULT_ADAPTIVE_QUANTIZATION TRUE
+#define DEFAULT_SCENE_CHANGE_DETECTION TRUE
+#define DEFAULT_SLICE_MODE SM_AUTO_SLICE
+#define DEFAULT_NUM_SLICES 1
enum
{
@@ -129,6 +182,12 @@ enum
PROP_MULTI_THREAD,
PROP_ENABLE_DENOISE,
PROP_ENABLE_FRAME_SKIP,
+ PROP_DEBLOCKING_MODE,
+ PROP_BACKGROUND_DETECTION,
+ PROP_ADAPTIVE_QUANTIZATION,
+ PROP_SCENE_CHANGE_DETECTION,
+ PROP_SLICE_MODE,
+ PROP_NUM_SLICES,
N_PROPERTIES
};
@@ -149,6 +208,12 @@ struct _GstOpenh264EncPrivate
guint64 time_per_frame;
guint64 frame_count;
guint64 previous_timestamp;
+ GstOpenh264encDeblockingMode deblocking_mode;
+ gboolean background_detection;
+ gboolean adaptive_quantization;
+ gboolean scene_change_detection;
+ SliceModeEnum slice_mode;
+ guint num_slices;
};
/* pad templates */
@@ -253,6 +318,39 @@ gst_openh264enc_class_init (GstOpenh264EncClass * klass)
"The maximum size of one slice (in bytes).",
0, G_MAXUINT, DEFAULT_MAX_SLICE_SIZE,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass),
+ PROP_DEBLOCKING_MODE, g_param_spec_enum ("deblocking",
+ "Deblocking mode", "Deblocking mode",
+ GST_TYPE_OPENH264ENC_DEBLOCKING_MODE, DEFAULT_DEBLOCKING_MODE,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (gobject_class, PROP_BACKGROUND_DETECTION,
+ g_param_spec_boolean ("background-detection", "Background detection",
+ "Background detection", DEFAULT_BACKGROUND_DETECTION,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (gobject_class, PROP_ADAPTIVE_QUANTIZATION,
+ g_param_spec_boolean ("adaptive-quantization", "Adaptive quantization",
+ "Adaptive quantization", DEFAULT_ADAPTIVE_QUANTIZATION,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (gobject_class, PROP_SCENE_CHANGE_DETECTION,
+ g_param_spec_boolean ("scene-change-detection",
+ "Scene change detection", "Scene change detection",
+ DEFAULT_SCENE_CHANGE_DETECTION,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SLICE_MODE,
+ g_param_spec_enum ("slice-mode", "Slice mode", "Slice mode",
+ GST_TYPE_OPENH264ENC_SLICE_MODE, DEFAULT_SLICE_MODE,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (gobject_class, PROP_NUM_SLICES,
+ g_param_spec_uint ("num-slices", "Number of slices",
+ "The number of slices (needs slice-mode=n-slices)",
+ 0, G_MAXUINT, DEFAULT_NUM_SLICES,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
}
static void
@@ -273,6 +371,12 @@ gst_openh264enc_init (GstOpenh264Enc * openh264enc)
openh264enc->priv->drop_bitrate = DROP_BITRATE;
openh264enc->priv->enable_denoise = DEFAULT_ENABLE_DENOISE;
openh264enc->priv->enable_frame_skip = DEFAULT_ENABLE_FRAME_SKIP;
+ openh264enc->priv->deblocking_mode = DEFAULT_DEBLOCKING_MODE;
+ openh264enc->priv->background_detection = DEFAULT_BACKGROUND_DETECTION;
+ openh264enc->priv->adaptive_quantization = DEFAULT_ADAPTIVE_QUANTIZATION;
+ openh264enc->priv->scene_change_detection = DEFAULT_SCENE_CHANGE_DETECTION;
+ openh264enc->priv->slice_mode = DEFAULT_SLICE_MODE;
+ openh264enc->priv->num_slices = DEFAULT_NUM_SLICES;
openh264enc->priv->encoder = NULL;
gst_openh264enc_set_usage_type (openh264enc, CAMERA_VIDEO_REAL_TIME);
gst_openh264enc_set_rate_control (openh264enc, RC_QUALITY_MODE);
@@ -355,6 +459,31 @@ gst_openh264enc_set_property (GObject * object, guint property_id,
openh264enc->priv->max_slice_size = g_value_get_uint (value);
break;
+ case PROP_DEBLOCKING_MODE:
+ openh264enc->priv->deblocking_mode =
+ (GstOpenh264encDeblockingMode) g_value_get_enum (value);
+ break;
+
+ case PROP_BACKGROUND_DETECTION:
+ openh264enc->priv->background_detection = g_value_get_boolean (value);
+ break;
+
+ case PROP_ADAPTIVE_QUANTIZATION:
+ openh264enc->priv->adaptive_quantization = g_value_get_boolean (value);
+ break;
+
+ case PROP_SCENE_CHANGE_DETECTION:
+ openh264enc->priv->scene_change_detection = g_value_get_boolean (value);
+ break;
+
+ case PROP_SLICE_MODE:
+ openh264enc->priv->slice_mode = (SliceModeEnum) g_value_get_enum (value);
+ break;
+
+ case PROP_NUM_SLICES:
+ openh264enc->priv->num_slices = g_value_get_uint (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -402,6 +531,30 @@ gst_openh264enc_get_property (GObject * object, guint property_id,
g_value_set_uint (value, openh264enc->priv->max_slice_size);
break;
+ case PROP_DEBLOCKING_MODE:
+ g_value_set_enum (value, openh264enc->priv->deblocking_mode);
+ break;
+
+ case PROP_BACKGROUND_DETECTION:
+ g_value_set_boolean (value, openh264enc->priv->background_detection);
+ break;
+
+ case PROP_ADAPTIVE_QUANTIZATION:
+ g_value_set_boolean (value, openh264enc->priv->adaptive_quantization);
+ break;
+
+ case PROP_SCENE_CHANGE_DETECTION:
+ g_value_set_boolean (value, openh264enc->priv->scene_change_detection);
+ break;
+
+ case PROP_SLICE_MODE:
+ g_value_set_enum (value, openh264enc->priv->slice_mode);
+ break;
+
+ case PROP_NUM_SLICES:
+ g_value_set_uint (value, openh264enc->priv->num_slices);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -518,19 +671,26 @@ gst_openh264enc_set_format (GstVideoEncoder * encoder,
enc_params.iMultipleThreadIdc = openh264enc->priv->multi_thread;
enc_params.bEnableDenoise = openh264enc->priv->enable_denoise;
enc_params.uiIntraPeriod = priv->gop_size;
- enc_params.bEnableBackgroundDetection = 1;
- enc_params.bEnableAdaptiveQuant = 1;
+ enc_params.bEnableBackgroundDetection =
+ openh264enc->priv->background_detection;
+ enc_params.bEnableAdaptiveQuant = openh264enc->priv->adaptive_quantization;
+ enc_params.bEnableSceneChangeDetect =
+ openh264enc->priv->scene_change_detection;
enc_params.bEnableFrameSkip = openh264enc->priv->enable_frame_skip;
enc_params.bEnableLongTermReference = 0;
enc_params.bEnableSpsPpsIdAddition = 1;
enc_params.bPrefixNalAddingCtrl = 0;
enc_params.fMaxFrameRate = fps_n * 1.0 / fps_d;
+ enc_params.iLoopFilterDisableIdc = openh264enc->priv->deblocking_mode;
enc_params.sSpatialLayers[0].uiProfileIdc = PRO_BASELINE;
enc_params.sSpatialLayers[0].iVideoWidth = width;
enc_params.sSpatialLayers[0].iVideoHeight = height;
enc_params.sSpatialLayers[0].fFrameRate = fps_n * 1.0 / fps_d;
enc_params.sSpatialLayers[0].iSpatialBitrate = openh264enc->priv->bitrate;
- enc_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
+ enc_params.sSpatialLayers[0].sSliceCfg.uiSliceMode =
+ openh264enc->priv->slice_mode;
+ enc_params.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum =
+ openh264enc->priv->num_slices;
priv->framerate = (1 + fps_n / fps_d);
@@ -604,8 +764,8 @@ gst_openh264enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
return
- GST_VIDEO_ENCODER_CLASS (gst_openh264enc_parent_class)->propose_allocation
- (encoder, query);
+ GST_VIDEO_ENCODER_CLASS
+ (gst_openh264enc_parent_class)->propose_allocation (encoder, query);
}
static GstFlowReturn
@@ -719,8 +879,8 @@ gst_openh264enc_handle_frame (GstVideoEncoder * encoder,
* guess based on the input */
frame = gst_video_encoder_get_oldest_frame (base_encoder);
if (!frame) {
- GST_ELEMENT_ERROR (openh264enc, STREAM, ENCODE, ("Could not encode frame"),
- ("openh264enc returned %d", ret));
+ GST_ELEMENT_ERROR (openh264enc, STREAM, ENCODE,
+ ("Could not encode frame"), ("openh264enc returned %d", ret));
gst_video_codec_frame_unref (frame);
return GST_FLOW_ERROR;
}