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