69b9989bfc0a6ad43b8be87242e6a3ce9a0f426b
[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 static gboolean  gst_h264encode_set_src_caps(GstVaapiEncode* encode, GstCaps *caps);
46
47
48 /* h264 encode */
49 GST_BOILERPLATE(
50     GstH264Encode,
51     gst_h264encode,
52     GstVaapiEncode,
53     GST_TYPE_VAAPI_ENCODE);
54
55 enum {
56     H264_PROP_0,
57     H264_PROP_PROFILE,
58     H264_PROP_LEVEL,
59     H264_PROP_BITRATE,
60     H264_PROP_INTRA_PERIOD,
61     H264_PROP_INIT_QP,
62     H264_PROP_MIN_QP,
63     H264_PROP_SLICE_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
158 }
159
160 static void
161 gst_h264encode_init(GstH264Encode *h264_encode, GstH264EncodeClass *klass)
162 {
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 guint 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 guint 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
328 static gboolean
329 gst_h264encode_set_src_caps(GstVaapiEncode* encode, GstCaps *caps)
330 {
331   g_return_val_if_fail(caps,FALSE);
332   gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "avc",
333                             "alignment", G_TYPE_STRING, "au",
334                             NULL);
335   return TRUE;
336 }
337
338