1 /* GStreamer
2 * Copyright (c) 2011, Texas Instruments Incorporated
3 * Copyright (c) 2011, Collabora Ltd.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Author: Alessandro Decina <alessandro.decina@collabora.com>
21 */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include "gstducati.h"
28 #include "gstducatih264enc.h"
30 #include <string.h>
32 #include <math.h>
34 #define GST_CAT_DEFAULT gst_ducati_debug
36 #define DEFAULT_PROFILE GST_DUCATI_H264ENC_PROFILE_HIGH
37 #define DEFAULT_LEVEL GST_DUCATI_H264ENC_LEVEL_40
39 #define GST_TYPE_DUCATI_H264ENC_PROFILE (gst_ducati_h264enc_profile_get_type ())
40 #define GST_TYPE_DUCATI_H264ENC_LEVEL (gst_ducati_h264enc_level_get_type ())
43 enum
44 {
45 LAST_SIGNAL
46 };
48 enum
49 {
50 PROP_0,
51 PROP_PROFILE,
52 PROP_LEVEL,
53 };
55 static void gst_ducati_h264enc_set_property (GObject * object, guint prop_id,
56 const GValue * value, GParamSpec * pspec);
57 static void gst_ducati_h264enc_get_property (GObject * object, guint prop_id,
58 GValue * value, GParamSpec * pspec);
60 static gboolean gst_ducati_h264enc_allocate_params (GstDucatiVidEnc *
61 self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
62 gint outargs_sz);
63 static gboolean gst_ducati_h264enc_configure (GstDucatiVidEnc * self);
66 static GstStaticPadTemplate gst_ducati_h264enc_sink_template =
67 GST_STATIC_PAD_TEMPLATE ("sink",
68 GST_PAD_SINK,
69 GST_PAD_ALWAYS,
70 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("NV12"))
71 );
73 static GstStaticPadTemplate gst_ducati_h264enc_src_template =
74 GST_STATIC_PAD_TEMPLATE ("src",
75 GST_PAD_SRC,
76 GST_PAD_ALWAYS,
77 GST_STATIC_CAPS ("video/x-h264")
78 );
80 GST_BOILERPLATE (GstDucatiH264Enc, gst_ducati_h264enc, GstDucatiVidEnc,
81 GST_TYPE_DUCATIVIDENC);
84 /* the values for the following enums are taken from the codec */
86 enum
87 {
88 GST_DUCATI_H264ENC_PROFILE_BASELINE = 66, /**< BaseLine Profile */
89 GST_DUCATI_H264ENC_PROFILE_MAIN = 77, /**< Main Profile */
90 GST_DUCATI_H264ENC_PROFILE_EXTENDED = 88, /**< Extended Profile */
91 GST_DUCATI_H264ENC_PROFILE_HIGH = 100, /**< High Profile */
92 GST_DUCATI_H264ENC_PROFILE_HIGH_10 = 110, /**< High 10 Profile */
93 GST_DUCATI_H264ENC_PROFILE_HIGH_422 = 122 /**< High 4:2:2 Profile */
94 };
96 enum
97 {
98 GST_DUCATI_H264ENC_LEVEL_10 = 10, /**< Level 1.0 */
99 GST_DUCATI_H264ENC_LEVEL_1b = 9, /**< Level 1.b */
100 GST_DUCATI_H264ENC_LEVEL_11 = 11, /**< Level 1.1 */
101 GST_DUCATI_H264ENC_LEVEL_12 = 12, /**< Level 1.2 */
102 GST_DUCATI_H264ENC_LEVEL_13 = 13, /**< Level 1.3 */
103 GST_DUCATI_H264ENC_LEVEL_20 = 20, /**< Level 2.0 */
104 GST_DUCATI_H264ENC_LEVEL_21 = 21, /**< Level 2.1 */
105 GST_DUCATI_H264ENC_LEVEL_22 = 22, /**< Level 2.2 */
106 GST_DUCATI_H264ENC_LEVEL_30 = 30, /**< Level 3.0 */
107 GST_DUCATI_H264ENC_LEVEL_31 = 31, /**< Level 3.1 */
108 GST_DUCATI_H264ENC_LEVEL_32 = 32, /**< Level 3.2 */
109 GST_DUCATI_H264ENC_LEVEL_40 = 40, /**< Level 4.0 */
110 GST_DUCATI_H264ENC_LEVEL_41 = 41, /**< Level 4.1 */
111 GST_DUCATI_H264ENC_LEVEL_42 = 42, /**< Level 4.2 */
112 GST_DUCATI_H264ENC_LEVEL_50 = 50, /**< Level 5.0 */
113 GST_DUCATI_H264ENC_LEVEL_51 = 51 /**< Level 5.1 */
114 };
116 static GType
117 gst_ducati_h264enc_profile_get_type (void)
118 {
119 static GType type = 0;
121 if (!type) {
122 static const GEnumValue vals[] = {
123 {GST_DUCATI_H264ENC_PROFILE_BASELINE, "Base Profile", "baseline"},
124 {GST_DUCATI_H264ENC_PROFILE_MAIN, "Main Profile", "main"},
125 {GST_DUCATI_H264ENC_PROFILE_EXTENDED, "Extended Profile", "extended"},
126 {GST_DUCATI_H264ENC_PROFILE_HIGH, "High Profile", "high"},
127 {GST_DUCATI_H264ENC_PROFILE_HIGH_10, "High 10 Profile", "high-10"},
128 {GST_DUCATI_H264ENC_PROFILE_HIGH_422, "High 4:2:2 Profile", "high-422"},
129 {0, NULL, NULL},
130 };
132 type = g_enum_register_static ("GstDucatiH264EncProfile", vals);
133 }
135 return type;
136 }
138 static GType
139 gst_ducati_h264enc_level_get_type (void)
140 {
141 static GType type = 0;
143 if (!type) {
144 static const GEnumValue vals[] = {
145 {GST_DUCATI_H264ENC_LEVEL_10, "Level 1", "level-1"},
146 {GST_DUCATI_H264ENC_LEVEL_1b, "Level 1b", "level-1b"},
147 {GST_DUCATI_H264ENC_LEVEL_11, "Level 11", "level-11"},
148 {GST_DUCATI_H264ENC_LEVEL_12, "Level 12", "level-12"},
149 {GST_DUCATI_H264ENC_LEVEL_13, "Level 13", "level-13"},
150 {GST_DUCATI_H264ENC_LEVEL_20, "Level 2", "level-2"},
151 {GST_DUCATI_H264ENC_LEVEL_21, "Level 21", "level-21"},
152 {GST_DUCATI_H264ENC_LEVEL_22, "Level 22", "level-22"},
153 {GST_DUCATI_H264ENC_LEVEL_30, "Level 3", "level-3"},
154 {GST_DUCATI_H264ENC_LEVEL_31, "Level 31", "level-31"},
155 {GST_DUCATI_H264ENC_LEVEL_32, "Level 32", "level-32"},
156 {GST_DUCATI_H264ENC_LEVEL_40, "Level 4", "level-4"},
157 {GST_DUCATI_H264ENC_LEVEL_41, "Level 41", "level-41"},
158 {GST_DUCATI_H264ENC_LEVEL_42, "Level 42", "level-42"},
159 {GST_DUCATI_H264ENC_LEVEL_50, "Level 5", "level-5"},
160 {GST_DUCATI_H264ENC_LEVEL_51, "Level 51", "level-51"},
161 {0, NULL, NULL},
162 };
164 type = g_enum_register_static ("GstDucatiH264EncLevel", vals);
165 }
167 return type;
168 }
170 static void
171 gst_ducati_h264enc_base_init (gpointer g_class)
172 {
174 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
176 gst_element_class_add_pad_template (element_class,
177 gst_static_pad_template_get (&gst_ducati_h264enc_src_template));
178 gst_element_class_add_pad_template (element_class,
179 gst_static_pad_template_get (&gst_ducati_h264enc_sink_template));
181 gst_element_class_set_details_simple (element_class, "H264 Encoder",
182 "Codec/Encoder/Video",
183 "Encode raw video into H264 stream",
184 "Alessandro Decina <alessandro.decina@collabora.com>");
186 GST_DUCATIVIDENC_CLASS (element_class)->codec_name = "ivahd_h264enc";
187 }
189 static void
190 gst_ducati_h264enc_class_init (GstDucatiH264EncClass * klass)
191 {
192 GObjectClass *gobject_class;
193 GstDucatiVidEncClass *videnc_class;
195 gobject_class = G_OBJECT_CLASS (klass);
196 videnc_class = GST_DUCATIVIDENC_CLASS (klass);
198 gobject_class->set_property = gst_ducati_h264enc_set_property;
199 gobject_class->get_property = gst_ducati_h264enc_get_property;
201 videnc_class->allocate_params = gst_ducati_h264enc_allocate_params;
202 videnc_class->configure = gst_ducati_h264enc_configure;
204 g_object_class_install_property (gobject_class, PROP_PROFILE,
205 g_param_spec_enum ("profile", "H.264 Profile", "H.264 Profile",
206 GST_TYPE_DUCATI_H264ENC_PROFILE, DEFAULT_PROFILE, G_PARAM_READWRITE));
208 g_object_class_install_property (gobject_class, PROP_LEVEL,
209 g_param_spec_enum ("level", "H.264 Level", "H.264 Level",
210 GST_TYPE_DUCATI_H264ENC_LEVEL, DEFAULT_LEVEL, G_PARAM_READWRITE));
211 }
213 static void
214 gst_ducati_h264enc_init (GstDucatiH264Enc * self, GstDucatiH264EncClass * klass)
215 {
216 GST_DEBUG ("gst_ducati_h264enc_init");
218 self->profile = DEFAULT_PROFILE;
219 self->level = DEFAULT_LEVEL;
220 }
222 static void
223 gst_ducati_h264enc_set_property (GObject * object, guint prop_id,
224 const GValue * value, GParamSpec * pspec)
225 {
226 GstDucatiH264Enc *self = GST_DUCATIH264ENC (object);
228 g_return_if_fail (GST_IS_DUCATIH264ENC (object));
229 self = GST_DUCATIH264ENC (object);
231 switch (prop_id) {
232 case PROP_PROFILE:
233 self->profile = g_value_get_enum (value);
234 break;
235 case PROP_LEVEL:
236 self->level = g_value_get_enum (value);
237 break;
238 default:
239 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
240 }
241 }
243 static void
244 gst_ducati_h264enc_get_property (GObject * object, guint prop_id,
245 GValue * value, GParamSpec * pspec)
246 {
247 GstDucatiH264Enc *self = GST_DUCATIH264ENC (object);
249 g_return_if_fail (GST_IS_DUCATIH264ENC (object));
250 self = GST_DUCATIH264ENC (object);
252 switch (prop_id) {
253 case PROP_PROFILE:
254 g_value_set_enum (value, self->profile);
255 break;
256 case PROP_LEVEL:
257 g_value_set_enum (value, self->level);
258 break;
259 default:
260 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
261 }
262 }
264 static gboolean
265 gst_ducati_h264enc_configure (GstDucatiVidEnc * videnc)
266 {
267 GstDucatiH264Enc *self = GST_DUCATIH264ENC (videnc);
268 IH264ENC_Params *params;
269 gboolean ret;
271 videnc->params->profile = self->profile;
272 videnc->params->level = self->level;
274 params = (IH264ENC_Params *) videnc->params;
275 /* this is the only non-base field strictly required */
276 params->maxIntraFrameInterval = 0x7fffffff;
277 params->IDRFrameInterval = 1;
278 params->numTemporalLayer = 1;
280 ret = GST_DUCATIVIDENC_CLASS (parent_class)->configure (videnc);
281 if (ret) {
282 const GstVideoState *state =
283 gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (videnc));
284 GstCaps *caps = gst_caps_new_simple ("video/x-h264",
285 "width", G_TYPE_INT, videnc->rect.w,
286 "height", G_TYPE_INT, videnc->rect.h,
287 "framerate", GST_TYPE_FRACTION, state->fps_n, state->fps_d,
288 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, state->par_d,
289 "stream-format", G_TYPE_STRING, "byte-stream",
290 "align", G_TYPE_STRING, "au",
291 NULL);
292 ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (self), caps);
293 }
295 return ret;
296 }
298 static gboolean
299 gst_ducati_h264enc_allocate_params (GstDucatiVidEnc *
300 videnc, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
301 gint outargs_sz)
302 {
303 return GST_DUCATIVIDENC_CLASS (parent_class)->allocate_params (videnc,
304 sizeof (IH264ENC_Params), sizeof (IVIDENC2_DynamicParams),
305 sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
306 sizeof (IVIDENC2_OutArgs));
307 }