add Intel Copyright
[profile/ivi/gstreamer-vaapi.git] / gst / vaapiencode / gstvaapih264encode.c
1 /*
2  *  gstvaapih264encode.c - VA-API H.264 encoder
3  *
4  *  Copyright (C) 2011 Intel Corporation
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public License
8  *  as published by the Free Software Foundation; either version 2.1
9  *  of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301 USA
20  */
21
22 #include "gstvaapih264encode.h"
23 #include "gstvaapih264encoder.h"
24
25 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h264_encode_debug);
26 #define GST_CAT_DEFAULT gst_vaapi_h264_encode_debug
27
28 static const char gst_h264encode_sink_caps_str[] =
29     GST_CAPS_CODEC("video/x-raw-yuv, " "format = (fourcc) { I420 } ")
30     GST_CAPS_CODEC("video/x-raw-yuv, " "format = (fourcc) { NV12 } ")
31     GST_VAAPI_SURFACE_CAPS;
32
33 static const GstElementDetails gst_h264encode_details =
34     GST_ELEMENT_DETAILS(
35         "VA-API h264 encoder",
36         "Codec/Encoder/Video",
37         "A VA-API based h264 encoder",
38         "Feng Yuan<feng.yuan@intel.com>");
39
40
41 static const char gst_h264encode_src_caps_str[] =
42     GST_CAPS_CODEC("video/x-h264");
43
44 static GstStaticPadTemplate gst_h264encode_sink_factory =
45     GST_STATIC_PAD_TEMPLATE(
46         "sink",
47         GST_PAD_SINK,
48         GST_PAD_ALWAYS,
49         GST_STATIC_CAPS(gst_h264encode_sink_caps_str));
50
51 static GstStaticPadTemplate gst_h264encode_src_factory =
52     GST_STATIC_PAD_TEMPLATE(
53         "src",
54         GST_PAD_SRC,
55         GST_PAD_ALWAYS,
56         GST_STATIC_CAPS(gst_h264encode_src_caps_str));
57
58 static void gst_h264encode_finalize(GObject *object);
59 static void gst_h264encode_set_property(GObject *object, guint prop_id,
60     const GValue *value, GParamSpec *pspec);
61 static void gst_h264encode_get_property (GObject * object, guint prop_id,
62     GValue * value, GParamSpec * pspec);
63 static gboolean _h264_check_valid_profile(guint profile);
64 static gboolean _h264_check_valid_level(guint level);
65 static gboolean  gst_h264encode_set_src_caps(GstVaapiEncode* encode, GstCaps *caps);
66
67
68 /* h264 encode */
69 GST_BOILERPLATE(
70     GstH264Encode,
71     gst_h264encode,
72     GstVaapiEncode,
73     GST_TYPE_VAAPI_ENCODE);
74
75 enum {
76     H264_PROP_0,
77     H264_PROP_PROFILE,
78     H264_PROP_LEVEL,
79     H264_PROP_BITRATE,
80     H264_PROP_INTRA_PERIOD,
81     H264_PROP_INIT_QP,
82     H264_PROP_MIN_QP,
83     H264_PROP_SLICE_NUM,
84     H264_PROP_B_FRAME_NUM,
85 };
86
87
88 static void
89 gst_h264encode_base_init(gpointer klass)
90 {
91   GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
92
93   gst_element_class_set_details(element_class, &gst_h264encode_details);
94
95   /* sink pad */
96   gst_element_class_add_pad_template(
97       element_class,
98       gst_static_pad_template_get(&gst_h264encode_sink_factory)
99   );
100
101   /* src pad */
102   gst_element_class_add_pad_template(
103       element_class,
104       gst_static_pad_template_get(&gst_h264encode_src_factory)
105   );
106 }
107
108 static void
109 gst_h264encode_class_init(GstH264EncodeClass *klass)
110 {
111   GObjectClass * const object_class = G_OBJECT_CLASS(klass);
112   GstVaapiEncodeClass *const encode_class = GST_VAAPI_ENCODE_CLASS(klass);
113   GST_DEBUG_CATEGORY_INIT (gst_vaapi_h264_encode_debug, "vaapih264encode", 0,
114       "vaapih264encode element");
115
116   object_class->finalize      = gst_h264encode_finalize;
117   object_class->set_property  = gst_h264encode_set_property;
118   object_class->get_property  = gst_h264encode_get_property;
119
120   encode_class->set_encoder_src_caps = gst_h264encode_set_src_caps;
121
122   g_object_class_install_property (object_class, H264_PROP_PROFILE,
123           g_param_spec_uint ("profile",
124               "H264 Profile",
125               "Profile supports: 66(Baseline), 77(Main), 100(High)",
126               H264_PROFILE_BASELINE,
127               H264_PROFILE_HIGH10,
128               H264_DEFAULT_PROFILE,
129               G_PARAM_READWRITE));
130     g_object_class_install_property (object_class, H264_PROP_LEVEL,
131           g_param_spec_uint ("level",
132               "H264 level idc",
133               "Level idc supports: 10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41",
134               H264_LEVEL_10,
135               H264_LEVEL_41,
136               H264_DEFAULT_LEVEL,
137               G_PARAM_READWRITE));
138     g_object_class_install_property (object_class, H264_PROP_BITRATE,
139           g_param_spec_uint ("bitrate",
140               "H264 encoding bitrate",
141               "H264 encoding bitrate, 10k~100M, (0, auto-calculate)",
142               0,
143               100*1000*1000,
144               0,
145               G_PARAM_READWRITE));
146     g_object_class_install_property (object_class, H264_PROP_INTRA_PERIOD,
147           g_param_spec_uint ("intra-period",
148               "H264 encoding intra-period",
149               "H264 encoding intra-period",
150               1,
151               300,
152               H264_DEFAULT_INTRA_PERIOD,
153               G_PARAM_READWRITE));
154     g_object_class_install_property (object_class, H264_PROP_INIT_QP,
155           g_param_spec_uint ("init-qp",
156               "H264 init-qp",
157               "H264 init-qp",
158               1,
159               51,
160               H264_DEFAULT_INIT_QP,
161               G_PARAM_READWRITE));
162     g_object_class_install_property (object_class, H264_PROP_MIN_QP,
163           g_param_spec_uint ("min-qp",
164               "H264 min-qp",
165               "H264 min-qp",
166               1,
167               51,
168               H264_DEFAULT_MIN_QP,
169               G_PARAM_READWRITE));
170     g_object_class_install_property (object_class, H264_PROP_SLICE_NUM,
171           g_param_spec_uint ("slice-num",
172               "H264 slice num",
173               "H264 slice num",
174               1,
175               200,
176               1,
177               G_PARAM_READWRITE));
178     g_object_class_install_property (object_class, H264_PROP_B_FRAME_NUM,
179           g_param_spec_uint ("b-frame-num",
180               "B frams num",
181               "B frams num",
182               0,
183               10,
184               0,
185               G_PARAM_READWRITE));
186
187 }
188
189 static void
190 gst_h264encode_init(GstH264Encode *h264_encode, GstH264EncodeClass *klass)
191 {
192   GstVaapiEncode *encode = GST_VAAPI_ENCODE(h264_encode);
193   encode->encoder = GST_VAAPI_ENCODER(gst_h264_encoder_new());
194   ENCODER_ASSERT(encode->encoder);
195 }
196
197 static void
198 gst_h264encode_finalize(GObject *object)
199 {
200   //GstH264Encode * const h264_encode = GST_H264ENCODE(object);
201   G_OBJECT_CLASS(parent_class)->finalize(object);
202 }
203
204 static void
205 gst_h264encode_set_property(GObject *object, guint prop_id,
206     const GValue *value, GParamSpec *pspec)
207 {
208   GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
209   GstH264Encoder *h264encoder = GST_H264_ENCODER(encode->encoder);
210
211   ENCODER_ASSERT(h264encoder);
212
213   switch (prop_id) {
214     case H264_PROP_PROFILE: {
215       guint profile = g_value_get_uint(value);
216       if (_h264_check_valid_profile(profile)) {
217         h264encoder->profile = profile;
218       } else {
219         ENCODER_LOG_ERROR("h264encode set property <profile> failed.");
220       }
221     }
222       break;
223
224     case H264_PROP_LEVEL: {
225       guint level = g_value_get_uint(value);
226       if (_h264_check_valid_level(level)) {
227         h264encoder->level= level;
228       } else {
229         ENCODER_LOG_ERROR("h264encode set property <level> failed.");
230       }
231     }
232       break;
233
234     case H264_PROP_BITRATE: {
235       h264encoder->bitrate = g_value_get_uint(value);
236     }
237       break;
238
239     case H264_PROP_INTRA_PERIOD: {
240       h264encoder->intra_period = g_value_get_uint(value);
241     }
242       break;
243
244     case H264_PROP_INIT_QP: {
245       h264encoder->init_qp = g_value_get_uint(value);
246     }
247       break;
248
249     case H264_PROP_MIN_QP: {
250       h264encoder->min_qp = g_value_get_uint(value);
251     }
252       break;
253
254     case H264_PROP_SLICE_NUM: {
255       h264encoder->slice_num= g_value_get_uint(value);
256     }
257       break;
258
259     case H264_PROP_B_FRAME_NUM: {
260       h264encoder->b_frame_num= g_value_get_uint(value);
261     }
262       break;
263
264     default:
265       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
266       break;
267   }
268 }
269
270 static void
271 gst_h264encode_get_property (GObject * object, guint prop_id,
272     GValue * value, GParamSpec * pspec)
273 {
274   GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
275   GstH264Encoder *h264encoder = GST_H264_ENCODER(encode->encoder);
276   ENCODER_ASSERT(h264encoder);
277
278   switch (prop_id) {
279     case H264_PROP_PROFILE:
280       g_value_set_uint (value, h264encoder->profile);
281       break;
282
283     case H264_PROP_LEVEL:
284       g_value_set_uint (value, h264encoder->level);
285       break;
286
287     case H264_PROP_BITRATE:
288       g_value_set_uint (value, h264encoder->bitrate);
289       break;
290
291     case H264_PROP_INTRA_PERIOD:
292       g_value_set_uint (value, h264encoder->intra_period);
293       break;
294
295     case H264_PROP_INIT_QP:
296       g_value_set_uint (value, h264encoder->init_qp);
297       break;
298
299     case H264_PROP_MIN_QP:
300       g_value_set_uint (value, h264encoder->min_qp);
301       break;
302
303     case H264_PROP_SLICE_NUM:
304       g_value_set_uint (value, h264encoder->slice_num);
305       break;
306
307     case H264_PROP_B_FRAME_NUM:
308       g_value_set_uint (value, h264encoder->b_frame_num);
309       break;
310
311     default:
312       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
313       break;
314   }
315 }
316
317
318 static gboolean
319 _h264_check_valid_profile(guint profile)
320 {
321    static const guint limit_profiles[] = {
322          H264_PROFILE_BASELINE,
323          H264_PROFILE_MAIN,
324          H264_PROFILE_HIGH
325         };
326    guint n_profiles = sizeof(limit_profiles)/sizeof(limit_profiles[0]);
327    guint i;
328    for (i = 0; i < n_profiles; ++i) {
329      if (limit_profiles[i] == profile)
330        return TRUE;
331    }
332    return FALSE;
333 }
334
335 static gboolean
336 _h264_check_valid_level(guint level)
337 {
338   static const guint limit_levels[] = {
339         H264_LEVEL_10,
340         H264_LEVEL_11,
341         H264_LEVEL_12,
342         H264_LEVEL_13,
343         H264_LEVEL_20,
344         H264_LEVEL_21,
345         H264_LEVEL_22,
346         H264_LEVEL_30,
347         H264_LEVEL_31,
348         H264_LEVEL_32,
349         H264_LEVEL_40,
350         H264_LEVEL_41,
351         H264_LEVEL_42,
352         H264_LEVEL_50,
353         H264_LEVEL_51
354        };
355   guint n_levels = sizeof(limit_levels)/sizeof(limit_levels[0]);
356   guint i;
357   for (i = 0; i < n_levels; ++i) {
358     if (limit_levels[i] == level)
359       return TRUE;
360   }
361   return FALSE;
362
363 }
364
365
366 static gboolean
367 gst_h264encode_set_src_caps(GstVaapiEncode* encode, GstCaps *caps)
368 {
369   g_return_val_if_fail(caps,FALSE);
370   gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "avc",
371                             "alignment", G_TYPE_STRING, "au",
372                             NULL);
373   return TRUE;
374 }
375
376