From: Roopang Patel <roopangkumar.pa...@ti.com>

Changes:
1) Given support of v4l2 extra controls such as
bitrate,gopsize and iperiod for H264 encoding and
also added as v4l2 H264 plugin properties to set and
get for dynamic value change.

2) We need to set these extra controls before the gstreamer
pipeline set format API invoke.so, we are setting extra
controls when the pipeline change the state
GST_STATE_CHANGE_READY_TO_PAUSED.
---
 sys/v4l2/gstv4l2h264enc.c | 135 +++++++++++++++++++++++++++++++++++++-
 sys/v4l2/gstv4l2h264enc.h |   9 +++
 2 files changed, 142 insertions(+), 2 deletions(-)

diff --git a/sys/v4l2/gstv4l2h264enc.c b/sys/v4l2/gstv4l2h264enc.c
index ee160b3a0..169e6ae69 100644
--- a/sys/v4l2/gstv4l2h264enc.c
+++ b/sys/v4l2/gstv4l2h264enc.c
@@ -47,6 +47,9 @@ enum
 {
   PROP_0,
   V4L2_STD_OBJECT_PROPS,
+  PROP_BITRATE,
+  PROP_GOPSIZE,
+  PROP_I_PERIOD,
 /* TODO add H264 controls
  * PROP_I_FRAME_QP,
  * PROP_P_FRAME_QP,
@@ -78,14 +81,46 @@ static void
 gst_v4l2_h264_enc_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec)
 {
-  /* TODO */
+  GstV4l2H264Enc *self = GST_V4L2_H264_ENC (object);
+
+  switch(prop_id)
+  {
+    case PROP_BITRATE:{
+     self->bitrate = g_value_get_uint (value);
+    }break;
+    case PROP_GOPSIZE:{
+     self->gopsize = g_value_get_uint (value);
+    }break;
+    case PROP_I_PERIOD:{
+     self->iperiod = g_value_get_uint (value);
+    }break;
+    default:{
+     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }break;
+  }
 }
 
 static void
 gst_v4l2_h264_enc_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec)
 {
-  /* TODO */
+  GstV4l2H264Enc *self = GST_V4L2_H264_ENC (object);
+
+  switch(prop_id)
+  {
+    case PROP_BITRATE:{
+     g_value_set_uint (value, self->bitrate);
+    }break;
+    case PROP_GOPSIZE:{
+     g_value_set_uint (value, self->gopsize);
+    }break;
+    case PROP_I_PERIOD:{
+     g_value_set_uint (value, self->iperiod);
+    }break;
+    default:{
+     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }break;
+  }
 }
 
 static gint
@@ -270,6 +305,82 @@ v4l2_level_to_string (gint v4l2_level)
 static void
 gst_v4l2_h264_enc_init (GstV4l2H264Enc * self)
 {
+  /* Initializing H264 encoder control parameter with
+  * default values */
+  self->bitrate = DEFAULT_PROP_BITRATE;
+  self->gopsize = DEFAULT_PROP_GOPSIZE;
+  self->iperiod = DEFAULT_PROP_I_PERIOD;
+}
+
+static void
+gst_v4l2_h264_enc_get_ctrls(GstV4l2Object * v4l2object)
+{
+  struct v4l2_ext_controls ctrls;
+  struct v4l2_ext_control controls[3];
+  guint i;
+
+  memset(&ctrls, 0, sizeof(ctrls));
+  memset(controls, 0, sizeof(controls));
+
+  ctrls.which = V4L2_CTRL_WHICH_CUR_VAL;
+  ctrls.count = 3;
+  ctrls.controls = controls;
+
+  controls[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
+  controls[1].id = V4L2_CID_MPEG_VIDEO_BITRATE;
+  controls[2].id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
+
+  if (v4l2object->ioctl(v4l2object->video_fd, VIDIOC_G_EXT_CTRLS, &ctrls)) {
+    GST_DEBUG_OBJECT(v4l2object,"Failed to get extra "
+    "controls for H264 encoder");
+    return;
+  }
+}
+
+static void
+gst_v4l2_h264_enc_set_ctrls(GstV4l2Object * v4l2object, guint bitrate,
+                                                       guint gop_size, guint 
i_period)
+{
+  struct v4l2_ext_controls ctrls;
+  struct v4l2_ext_control controls[3];
+  guint i;
+
+  memset(&ctrls, 0, sizeof(ctrls));
+  memset(controls, 0, sizeof(controls));
+
+  ctrls.which = V4L2_CTRL_WHICH_CUR_VAL;
+  ctrls.count = 3;
+  ctrls.controls = controls;
+
+  controls[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
+  controls[0].value = gop_size;
+  controls[1].id = V4L2_CID_MPEG_VIDEO_BITRATE;
+  controls[1].value = bitrate;
+  controls[2].id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
+  controls[2].value = i_period;
+
+  if (v4l2object->ioctl(v4l2object->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls)) {
+    GST_DEBUG_OBJECT(v4l2object,"Failed to set extra "
+    "controls for encoder");
+    return;
+  }
+}
+
+static GstStateChangeReturn
+gst_v4l2_h264_enc_change_state (GstElement * element,
+    GstStateChange transition)
+{
+  GstV4l2VideoEnc *parent = GST_V4L2_VIDEO_ENC (element);
+  GstV4l2H264Enc *self = GST_V4L2_H264_ENC (element);
+
+  if(transition == GST_STATE_CHANGE_READY_TO_PAUSED)
+  {
+    gst_v4l2_h264_enc_set_ctrls(parent->v4l2output, self->bitrate,
+                                self->gopsize, self->iperiod);
+    gst_v4l2_h264_enc_get_ctrls(parent->v4l2output);
+  }
+
+  return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 }
 
 static void
@@ -278,12 +389,14 @@ gst_v4l2_h264_enc_class_init (GstV4l2H264EncClass * klass)
   GstElementClass *element_class;
   GObjectClass *gobject_class;
   GstV4l2VideoEncClass *baseclass;
+  GstVideoEncoderClass *video_encoder_class;
 
   parent_class = g_type_class_peek_parent (klass);
 
   element_class = (GstElementClass *) klass;
   gobject_class = (GObjectClass *) klass;
   baseclass = (GstV4l2VideoEncClass *) (klass);
+  video_encoder_class = (GstVideoEncoderClass *) klass;
 
   GST_DEBUG_CATEGORY_INIT (gst_v4l2_h264_enc_debug, "v4l2h264enc", 0,
       "V4L2 H.264 Encoder");
@@ -298,6 +411,9 @@ gst_v4l2_h264_enc_class_init (GstV4l2H264EncClass * klass)
   gobject_class->get_property =
       GST_DEBUG_FUNCPTR (gst_v4l2_h264_enc_get_property);
 
+  element_class->change_state =
+        GST_DEBUG_FUNCPTR (gst_v4l2_h264_enc_change_state);
+
   baseclass->codec_name = "H264";
   baseclass->profile_cid = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
   baseclass->profile_to_string = v4l2_profile_to_string;
@@ -305,6 +421,21 @@ gst_v4l2_h264_enc_class_init (GstV4l2H264EncClass * klass)
   baseclass->level_cid = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
   baseclass->level_to_string = v4l2_level_to_string;
   baseclass->level_from_string = v4l2_level_from_string;
+
+  g_object_class_install_property (gobject_class, PROP_BITRATE,
+    g_param_spec_uint ("bitrate", "Bitrate", "Bitrate in kbit/sec",
+    24000, 100 * 1000 * 1000, DEFAULT_PROP_BITRATE,
+    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
+
+  g_object_class_install_property (gobject_class, PROP_GOPSIZE,
+    g_param_spec_uint ("gopsize", "Gopsize", "IDR frame interval",
+    1,7200, DEFAULT_PROP_GOPSIZE,
+    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
+
+  g_object_class_install_property (gobject_class, PROP_I_PERIOD,
+    g_param_spec_uint ("iperiod", "Iperiod", "I Frame Period",
+    1,600, DEFAULT_PROP_I_PERIOD,
+    G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS ));
 }
 
 /* Probing functions */
diff --git a/sys/v4l2/gstv4l2h264enc.h b/sys/v4l2/gstv4l2h264enc.h
index 3bfa34346..370bcf535 100644
--- a/sys/v4l2/gstv4l2h264enc.h
+++ b/sys/v4l2/gstv4l2h264enc.h
@@ -39,9 +39,18 @@ G_BEGIN_DECLS
 typedef struct _GstV4l2H264Enc GstV4l2H264Enc;
 typedef struct _GstV4l2H264EncClass GstV4l2H264EncClass;
 
+#define DEFAULT_PROP_BITRATE   (500 * 1000)
+#define DEFAULT_PROP_GOPSIZE   (1800)
+#define DEFAULT_PROP_I_PERIOD  (30)
+
 struct _GstV4l2H264Enc
 {
   GstV4l2VideoEnc parent;
+
+  /*H264 Extra Controls*/
+  guint bitrate;
+  guint gopsize;
+  guint iperiod;
 };
 
 struct _GstV4l2H264EncClass
-- 
2.17.1

_______________________________________________
meta-arago mailing list
meta-arago@arago-project.org
http://arago-project.org/cgi-bin/mailman/listinfo/meta-arago

Reply via email to