enum {
PROP_0,
+ PROP_PROFILE,
+ PROP_LEVEL,
+ PROP_BITRATE,
+ PROP_INTRA_PERIOD,
+ PROP_INIT_QP,
};
GstCaps * caps, GstBuffer ** buf);
static char* _h264_dump_caps(GstCaps *cpas);
+static gboolean _h264_check_valid_profile(guint profile);
+static gboolean _h264_check_valid_level(guint level);
+
/*gst fix functions*/
object_class->set_property = gst_h264encode_set_property;
object_class->get_property = gst_h264encode_get_property;
+ g_object_class_install_property (object_class, PROP_PROFILE,
+ g_param_spec_uint ("profile",
+ "H264 Profile",
+ "Profile supports: 66(Baseline), 77(Main), 100(High)",
+ H264_PROFILE_BASELINE,
+ H264_PROFILE_HIGH10,
+ H264_DEFAULT_PROFILE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_LEVEL,
+ g_param_spec_uint ("level",
+ "H264 level idc",
+ "Level idc supports: 10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51",
+ H264_LEVEL_10,
+ H264_LEVEL_51,
+ H264_DEFAULT_LEVEL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_BITRATE,
+ g_param_spec_uint ("bitrate",
+ "H264 encoding bitrate",
+ "H264 encoding bitrate, 10k~100M",
+ 10*1000,
+ 100*1000*1000,
+ H264_DEFAULT_BITRATE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_INTRA_PERIOD,
+ g_param_spec_uint ("intra-period",
+ "H264 encoding intra-period",
+ "H264 encoding intra-period",
+ 1,
+ 300,
+ H264_DEFAULT_INTRA_PERIOD,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_INIT_QP,
+ g_param_spec_uint ("init-qp",
+ "H264 init-qp",
+ "H264 init-qp",
+ 1,
+ 51,
+ H264_DEFAULT_INIT_QP,
+ G_PARAM_READWRITE));
+
element_class->change_state = gst_h264encode_change_state;
}
gst_h264encode_set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
+ GstH264Encode *encode = GST_H264ENCODE(object);
+ H264_ASSERT(encode->encoder);
+
+ switch (prop_id) {
+ case PROP_PROFILE: {
+ guint profile = g_value_get_uint(value);
+ if (_h264_check_valid_profile(profile)) {
+ encode->encoder->profile = profile;
+ } else {
+ H264_LOG_ERROR("h264encode set property <profile> failed.\n");
+ }
+ }
+ break;
+
+ case PROP_LEVEL: {
+ guint level = g_value_get_uint(value);
+ if (_h264_check_valid_level(level)) {
+ encode->encoder->level= level;
+ } else {
+ H264_LOG_ERROR("h264encode set property <level> failed.\n");
+ }
+ }
+ break;
+
+ case PROP_BITRATE: {
+ encode->encoder->bitrate = g_value_get_uint(value);
+ }
+ break;
+
+ case PROP_INTRA_PERIOD: {
+ encode->encoder->intra_period = g_value_get_uint(value);
+ }
+ break;
+
+ case PROP_INIT_QP: {
+ encode->encoder->init_qp = g_value_get_uint(value);
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
static void
gst_h264encode_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
+ GstH264Encode *encode = GST_H264ENCODE(object);
+ H264_ASSERT(encode->encoder);
+
+ switch (prop_id) {
+ case PROP_PROFILE:
+ g_value_set_uint (value, encode->encoder->profile);
+ break;
+
+ case PROP_LEVEL:
+ g_value_set_uint (value, encode->encoder->level);
+ break;
+
+ case PROP_BITRATE:
+ g_value_set_uint (value, encode->encoder->bitrate);
+ break;
+
+ case PROP_INTRA_PERIOD:
+ g_value_set_uint (value, encode->encoder->intra_period);
+ break;
+
+ case PROP_INIT_QP:
+ g_value_set_uint (value, encode->encoder->init_qp);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
static gboolean
gst_h264encode_set_caps(GstPad *sink_pad, GstCaps *caps)
{
GstH264Encode *encode = GST_H264ENCODE(GST_OBJECT_PARENT(sink_pad));
+ GstStructure *structure;
+ gint width = 0, height = 0;
+ gint fps_n = 0, fps_d = 0;
+ const GValue *fps_value = NULL;
encode->sinkpad_caps = caps;
- H264_LOG_INFO("gst_h264encode_set_caps,\n%s", _h264_dump_caps(caps));
gst_caps_ref(caps);
+ H264_LOG_INFO("gst_h264encode_set_caps,\n%s", _h264_dump_caps(caps));
+
+ structure = gst_caps_get_structure (caps, 0);
+ if (gst_structure_get_int (structure, "width", &width)) {
+ encode->encoder->width = width;
+ }
+ if (gst_structure_get_int (structure, "height", &height)) {
+ encode->encoder->height = height;
+ }
+ fps_value = gst_structure_get_value (structure, "framerate");
+ if (fps_value) {
+ fps_n = gst_value_get_fraction_numerator (fps_value);
+ fps_d = gst_value_get_fraction_denominator (fps_value);
+ encode->encoder->frame_rate = fps_n/fps_d;
+ }
return TRUE;
}
recv_struct = gst_caps_get_structure (recv_caps, 0);
GST_H264_ENCODE_CHECK_STATUS(NULL != recv_caps, GST_FLOW_ERROR, "gst_h264encode_chain, 1st buffer didn't have detailed caps.\n");
- gst_structure_get_int (recv_struct, "width", &width);
- gst_structure_get_int (recv_struct, "height", &height);
+ if (gst_structure_get_int (recv_struct, "width", &width)) {
+ encode->encoder->width = width;
+ }
+ if (gst_structure_get_int (recv_struct, "height", &height)) {
+ encode->encoder->height = height;
+ }
framerate = gst_structure_get_value (recv_struct, "framerate");
- fps_n = gst_value_get_fraction_numerator (framerate);
- fps_d = gst_value_get_fraction_denominator (framerate);
+ if (framerate) {
+ fps_n = gst_value_get_fraction_numerator (framerate);
+ fps_d = gst_value_get_fraction_denominator (framerate);
+ encode->encoder->frame_rate = fps_n/fps_d;
+ }
format_value = gst_structure_get_value (recv_struct, "format");
if (format_value) {
GST_H264_ENCODE_CHECK_STATUS(format_value && GST_TYPE_FOURCC == G_VALUE_TYPE(format_value),
GST_FLOW_ERROR, "1st buffer caps' format type is not fourcc.\n");
format = gst_value_get_fourcc (format_value);
+ if (format) {
+ gst_h264_encoder_set_input_format(encode->encoder, format);
+ }
}
- encode->encoder->profile = 66;
- encode->encoder->level = 30;
- encode->encoder->width = width;
- encode->encoder->height = height;
- encode->encoder->frame_rate = fps_n/fps_d;
- encode->encoder->bitrate = 3*1000*1000; // 3M
- encode->encoder->intra_period = 30;
-
/*set src pad caps*/
if (encode->srcpad_caps) {
gst_caps_unref(encode->srcpad_caps);
"framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
/*set display and initialize encoder*/
- if (format) {
- gst_h264_encoder_set_input_format(encode->encoder, format);
- }
if (GST_VAAPI_IS_VIDEO_BUFFER(buf)) {
GstVaapiDisplay *display = NULL;
GstVaapiVideoBuffer *video_buffer = GST_VAAPI_VIDEO_BUFFER(buf);
//need to get surface_pool and set to h264encoder->vaapi_context
//(video_buffer->priv->surface_pool);
#ifdef _MRST_
- surface_pool = gst_vaapi_video_buffer_get_surface_pool(video_buffer);
+ surface_pool = GST_VAAPI_SURFACE_POOL(gst_vaapi_video_buffer_get_surface_pool(video_buffer));
#endif
if (display) {
GST_H264_ENCODE_CHECK_STATUS(gst_h264_encoder_set_display(encode->encoder,display)
return ret_num;
}
+static gboolean _h264_check_valid_profile(guint profile)
+{
+ static const limit_profiles[] = {
+ H264_PROFILE_BASELINE,
+ H264_PROFILE_MAIN,
+ H264_PROFILE_HIGH
+ };
+ guint n_profiles = sizeof(limit_profiles)/sizeof(limit_profiles[0]);
+ guint i;
+ for (i = 0; i < n_profiles; ++i) {
+ if (limit_profiles[i] == profile)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean _h264_check_valid_level(guint level)
+{
+ static const limit_levels[] = {
+ H264_LEVEL_10,
+ H264_LEVEL_11,
+ H264_LEVEL_12,
+ H264_LEVEL_13,
+ H264_LEVEL_20,
+ H264_LEVEL_21,
+ H264_LEVEL_22,
+ H264_LEVEL_30,
+ H264_LEVEL_31,
+ H264_LEVEL_32,
+ H264_LEVEL_40,
+ H264_LEVEL_41,
+ H264_LEVEL_42,
+ H264_LEVEL_50,
+ H264_LEVEL_51
+ };
+ guint n_levels = sizeof(limit_levels)/sizeof(limit_levels[0]);
+ guint i;
+ for (i = 0; i < n_levels; ++i) {
+ if (limit_levels[i] == level)
+ return TRUE;
+ }
+ return FALSE;
+}
static char*
_h264_dump_caps(GstCaps *cpas)
#define H264_QUERY_STATUS_ERR -8
#define H264_DATA_NOT_READY -9
#define H264_DATA_ERR -10
-
+#define H264_PROFILE_ERR -11
+#define H264_PARAMETER_ERR -12
#define H264_LOG_ERROR(...) fprintf(stdout, ## __VA_ARGS__)
typedef int H264Status;
-typedef void* VADisplay;
typedef struct _GstH264Encoder GstH264Encoder;
typedef struct _GstH264EncoderPrivate GstH264EncoderPrivate;
typedef struct _GstH264EncoderClass GstH264EncoderClass;
H264_PROFILE_HIGH444_PREDICTIVE = 244,
} H264_Profile;
-#define H264_DEFAULT_INIT_QP 26
+typedef enum {
+ H264_LEVEL_10 = 10, /* QCIF format, < 380160 samples/sec */
+ H264_LEVEL_11 = 11, /* CIF format, < 768000 samples/sec */
+ H264_LEVEL_12 = 12, /* CIF format, < 1536000 samples/sec */
+ H264_LEVEL_13 = 13, /* CIF format, < 3041280 samples/sec */
+ H264_LEVEL_20 = 20, /* CIF format, < 3041280 samples/sec */
+ H264_LEVEL_21 = 21, /* HHR format, < 5068800 samples/sec */
+ H264_LEVEL_22 = 22, /* SD/4CIF format, < 5184000 samples/sec */
+ H264_LEVEL_30 = 30, /* SD/4CIF format, < 10368000 samples/sec */
+ H264_LEVEL_31 = 31, /* 720pHD format, < 27648000 samples/sec */
+ H264_LEVEL_32 = 32, /* SXGA format, < 55296000 samples/sec */
+ H264_LEVEL_40 = 40, /* 2Kx1K format, < 62914560 samples/sec */
+ H264_LEVEL_41 = 41, /* 2Kx1K format, < 62914560 samples/sec */
+ H264_LEVEL_42 = 42, /* 2Kx1K format, < 125829120 samples/sec */
+ H264_LEVEL_50 = 50, /* 3672x1536 format, < 150994944 samples/sec */
+ H264_LEVEL_51 = 51, /* 4096x2304 format, < 251658240 samples/sec */
+} H264_Level;
+
+#define H264_DEFAULT_PROFILE H264_PROFILE_BASELINE
+#define H264_DEFAULT_LEVEL H264_LEVEL_30
+#define H264_DEFAULT_INIT_QP 24
+#define H264_DEFAULT_BITRATE 800*1000 /*800k*/
+#define H264_DEFAULT_INTRA_PERIOD 30
+#define H264_DEFAULT_FPS 30
+
struct _GstH264Encoder {
GObject parent; /*based on gobject*/