add h264encoder
[profile/ivi/gstreamer-vaapi.git] / gst / vaapiencode / gstvaapih264encode.c
1 #include "gstvaapih264encode.h"
2 #include "gstvaapih264encoder.h"
3
4 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h264_encode_debug);
5 #define GST_CAT_DEFAULT gst_vaapi_h264_encode_debug
6
7 static const char gst_h264encode_sink_caps_str[] =
8     GST_CAPS_CODEC("video/x-raw-yuv, " "format = (fourcc) { I420 } ")
9     GST_CAPS_CODEC("video/x-raw-yuv, " "format = (fourcc) { NV12 } ")
10     GST_CAPS_CODEC("video/x-vaapi-surface ")
11     ;
12
13 static const GstElementDetails gst_h264encode_details =
14     GST_ELEMENT_DETAILS(
15         "VA-API h264 encoder",
16         "Codec/Encoder/Video",
17         "A VA-API based h264 encoder",
18         "Feng Yuan<feng.yuan@intel.com>");
19
20
21 static const char gst_h264encode_src_caps_str[] =
22     GST_CAPS_CODEC("video/x-h264");
23
24 static GstStaticPadTemplate gst_h264encode_sink_factory =
25     GST_STATIC_PAD_TEMPLATE(
26         "sink",
27         GST_PAD_SINK,
28         GST_PAD_ALWAYS,
29         GST_STATIC_CAPS(gst_h264encode_sink_caps_str));
30
31 static GstStaticPadTemplate gst_h264encode_src_factory =
32     GST_STATIC_PAD_TEMPLATE(
33         "src",
34         GST_PAD_SRC,
35         GST_PAD_ALWAYS,
36         GST_STATIC_CAPS(gst_h264encode_src_caps_str));
37
38 static void gst_h264encode_finalize(GObject *object);
39 static void gst_h264encode_set_property(GObject *object, guint prop_id,
40     const GValue *value, GParamSpec *pspec);
41 static void gst_h264encode_get_property (GObject * object, guint prop_id,
42     GValue * value, GParamSpec * pspec);
43 static gboolean _h264_check_valid_profile(guint profile);
44 static gboolean _h264_check_valid_level(guint level);
45
46
47 /* h264 encode */
48 GST_BOILERPLATE(
49     GstH264Encode,
50     gst_h264encode,
51     GstVaapiEncode,
52     GST_TYPE_VAAPI_ENCODE);
53
54 enum {
55     H264_PROP_0,
56     H264_PROP_PROFILE,
57     H264_PROP_LEVEL,
58     H264_PROP_BITRATE,
59     H264_PROP_INTRA_PERIOD,
60     H264_PROP_INIT_QP,
61     H264_PROP_MIN_QP,
62     H264_PROP_SLICE_NUM,
63 };
64
65
66 static void
67 gst_h264encode_base_init(gpointer klass)
68 {
69   GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
70
71   gst_element_class_set_details(element_class, &gst_h264encode_details);
72
73   /* sink pad */
74   gst_element_class_add_pad_template(
75       element_class,
76       gst_static_pad_template_get(&gst_h264encode_sink_factory)
77   );
78
79   /* src pad */
80   gst_element_class_add_pad_template(
81       element_class,
82       gst_static_pad_template_get(&gst_h264encode_src_factory)
83   );
84 }
85
86 static void
87 gst_h264encode_class_init(GstH264EncodeClass *klass)
88 {
89   GObjectClass * const object_class = G_OBJECT_CLASS(klass);
90   GstVaapiEncodeClass * const encode_class = GST_VAAPI_ENCODE_CLASS(klass);
91
92   GST_DEBUG_CATEGORY_INIT (gst_vaapi_h264_encode_debug, "vaapih264encode", 0,
93       "vaapih264encode element");
94
95   object_class->finalize      = gst_h264encode_finalize;
96   object_class->set_property  = gst_h264encode_set_property;
97   object_class->get_property  = gst_h264encode_get_property;
98
99
100   g_object_class_install_property (object_class, H264_PROP_PROFILE,
101           g_param_spec_uint ("profile",
102               "H264 Profile",
103               "Profile supports: 66(Baseline), 77(Main), 100(High)",
104               H264_PROFILE_BASELINE,
105               H264_PROFILE_HIGH10,
106               H264_DEFAULT_PROFILE,
107               G_PARAM_READWRITE));
108     g_object_class_install_property (object_class, H264_PROP_LEVEL,
109           g_param_spec_uint ("level",
110               "H264 level idc",
111               "Level idc supports: 10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41",
112               H264_LEVEL_10,
113               H264_LEVEL_41,
114               H264_DEFAULT_LEVEL,
115               G_PARAM_READWRITE));
116     g_object_class_install_property (object_class, H264_PROP_BITRATE,
117           g_param_spec_uint ("bitrate",
118               "H264 encoding bitrate",
119               "H264 encoding bitrate, 10k~100M, (0, auto-calculate)",
120               0,
121               100*1000*1000,
122               0,
123               G_PARAM_READWRITE));
124     g_object_class_install_property (object_class, H264_PROP_INTRA_PERIOD,
125           g_param_spec_uint ("intra-period",
126               "H264 encoding intra-period",
127               "H264 encoding intra-period",
128               1,
129               300,
130               H264_DEFAULT_INTRA_PERIOD,
131               G_PARAM_READWRITE));
132     g_object_class_install_property (object_class, H264_PROP_INIT_QP,
133           g_param_spec_uint ("init-qp",
134               "H264 init-qp",
135               "H264 init-qp",
136               1,
137               51,
138               H264_DEFAULT_INIT_QP,
139               G_PARAM_READWRITE));
140     g_object_class_install_property (object_class, H264_PROP_MIN_QP,
141           g_param_spec_uint ("min-qp",
142               "H264 min-qp",
143               "H264 min-qp",
144               1,
145               51,
146               H264_DEFAULT_MIN_QP,
147               G_PARAM_READWRITE));
148     g_object_class_install_property (object_class, H264_PROP_SLICE_NUM,
149           g_param_spec_uint ("slice-num",
150               "H264 slice num",
151               "H264 slice num",
152               1,
153               200,
154               1,
155               G_PARAM_READWRITE));
156
157 }
158
159 static void
160 gst_h264encode_init(GstH264Encode *h264_encode, GstH264EncodeClass *klass)
161 {
162   GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
163   GstVaapiEncode *encode = GST_VAAPI_ENCODE(h264_encode);
164   encode->encoder = GST_VAAPI_ENCODER(gst_h264_encoder_new());
165   ENCODER_ASSERT(encode->encoder);
166 }
167
168 static void
169 gst_h264encode_finalize(GObject *object)
170 {
171   //GstH264Encode * const h264_encode = GST_H264ENCODE(object);
172   G_OBJECT_CLASS(parent_class)->finalize(object);
173 }
174
175 static void
176 gst_h264encode_set_property(GObject *object, guint prop_id,
177     const GValue *value, GParamSpec *pspec)
178 {
179   GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
180   GstH264Encoder *h264encoder = GST_H264_ENCODER(encode->encoder);
181
182   ENCODER_ASSERT(h264encoder);
183
184   switch (prop_id) {
185     case H264_PROP_PROFILE: {
186       guint profile = g_value_get_uint(value);
187       if (_h264_check_valid_profile(profile)) {
188         h264encoder->profile = profile;
189       } else {
190         ENCODER_LOG_ERROR("h264encode set property <profile> failed.\n");
191       }
192     }
193       break;
194
195     case H264_PROP_LEVEL: {
196       guint level = g_value_get_uint(value);
197       if (_h264_check_valid_level(level)) {
198         h264encoder->level= level;
199       } else {
200         ENCODER_LOG_ERROR("h264encode set property <level> failed.\n");
201       }
202     }
203       break;
204
205     case H264_PROP_BITRATE: {
206       h264encoder->bitrate = g_value_get_uint(value);
207     }
208       break;
209
210     case H264_PROP_INTRA_PERIOD: {
211       h264encoder->intra_period = g_value_get_uint(value);
212     }
213       break;
214
215     case H264_PROP_INIT_QP: {
216       h264encoder->init_qp = g_value_get_uint(value);
217     }
218       break;
219
220     case H264_PROP_MIN_QP: {
221       h264encoder->min_qp = g_value_get_uint(value);
222     }
223       break;
224
225     case H264_PROP_SLICE_NUM: {
226       h264encoder->slice_num= g_value_get_uint(value);
227     }
228       break;
229
230     default:
231       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
232       break;
233   }
234 }
235
236 static void
237 gst_h264encode_get_property (GObject * object, guint prop_id,
238     GValue * value, GParamSpec * pspec)
239 {
240   GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
241   GstH264Encoder *h264encoder = GST_H264_ENCODER(encode->encoder);
242   ENCODER_ASSERT(h264encoder);
243
244   switch (prop_id) {
245     case H264_PROP_PROFILE:
246       g_value_set_uint (value, h264encoder->profile);
247       break;
248
249     case H264_PROP_LEVEL:
250       g_value_set_uint (value, h264encoder->level);
251       break;
252
253     case H264_PROP_BITRATE:
254       g_value_set_uint (value, h264encoder->bitrate);
255       break;
256
257     case H264_PROP_INTRA_PERIOD:
258       g_value_set_uint (value, h264encoder->intra_period);
259       break;
260
261     case H264_PROP_INIT_QP:
262       g_value_set_uint (value, h264encoder->init_qp);
263       break;
264
265     case H264_PROP_MIN_QP:
266       g_value_set_uint (value, h264encoder->min_qp);
267       break;
268
269     case H264_PROP_SLICE_NUM:
270       g_value_set_uint (value, h264encoder->slice_num);
271       break;
272
273     default:
274       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
275       break;
276   }
277 }
278
279
280 static gboolean
281 _h264_check_valid_profile(guint profile)
282 {
283    static const limit_profiles[] = {
284          H264_PROFILE_BASELINE,
285          H264_PROFILE_MAIN,
286          H264_PROFILE_HIGH
287         };
288    guint n_profiles = sizeof(limit_profiles)/sizeof(limit_profiles[0]);
289    guint i;
290    for (i = 0; i < n_profiles; ++i) {
291      if (limit_profiles[i] == profile)
292        return TRUE;
293    }
294    return FALSE;
295 }
296
297 static gboolean
298 _h264_check_valid_level(guint level)
299 {
300   static const limit_levels[] = {
301         H264_LEVEL_10,
302         H264_LEVEL_11,
303         H264_LEVEL_12,
304         H264_LEVEL_13,
305         H264_LEVEL_20,
306         H264_LEVEL_21,
307         H264_LEVEL_22,
308         H264_LEVEL_30,
309         H264_LEVEL_31,
310         H264_LEVEL_32,
311         H264_LEVEL_40,
312         H264_LEVEL_41,
313         H264_LEVEL_42,
314         H264_LEVEL_50,
315         H264_LEVEL_51
316        };
317   guint n_levels = sizeof(limit_levels)/sizeof(limit_levels[0]);
318   guint i;
319   for (i = 0; i < n_levels; ++i) {
320     if (limit_levels[i] == level)
321       return TRUE;
322   }
323   return FALSE;
324
325 }
326
327