2 * Copyright (C) 2007-2009 Nokia Corporation.
4 * Author: Felipe Contreras <felipe.contreras@nokia.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation
9 * version 2.1 of the License.
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.
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 Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "gstomx_base_videoenc.h"
25 #include <string.h> /* for strcmp */
34 #define DEFAULT_BITRATE 0
36 GSTOMX_BOILERPLATE (GstOmxBaseVideoEnc, gst_omx_base_videoenc, GstOmxBaseFilter,
37 GST_OMX_BASE_FILTER_TYPE);
40 /* modification: user force I frame */
42 add_force_key_frame(GstOmxBaseVideoEnc *enc)
44 GstOmxBaseFilter *omx_base;
46 OMX_CONFIG_INTRAREFRESHVOPTYPE config;
48 omx_base = GST_OMX_BASE_FILTER (enc);
49 gomx = (GOmxCore *) omx_base->gomx;
52 GST_INFO_OBJECT (enc, "request forced key frame now.");
54 if (!omx_base->out_port || !gomx->omx_handle) {
55 GST_WARNING_OBJECT (enc, "failed to set force-i-frame...");
59 G_OMX_INIT_PARAM (config);
60 config.nPortIndex = omx_base->out_port->port_index;
62 OMX_GetConfig (gomx->omx_handle, OMX_IndexConfigVideoIntraVOPRefresh, &config);
63 config.IntraRefreshVOP = OMX_TRUE;
65 OMX_SetConfig (gomx->omx_handle, OMX_IndexConfigVideoIntraVOPRefresh, &config);
70 process_input_buf (GstOmxBaseFilter * omx_base_filter, GstBuffer **buf)
72 GstOmxBaseVideoEnc *self;
74 self = GST_OMX_BASE_VIDEOENC (omx_base_filter);
76 GST_LOG_OBJECT (self, "base videoenc process_input_buf enter");
79 return GSTOMX_RETURN_OK;
82 /* modification: postprocess for outputbuf. in this videoenc case, set sync frame */
84 process_output_buf(GstOmxBaseFilter * omx_base, GstBuffer **buf, OMX_BUFFERHEADERTYPE *omx_buffer)
86 GstOmxBaseVideoEnc *self;
88 self = GST_OMX_BASE_VIDEOENC (omx_base);
90 GST_LOG_OBJECT (self, "base videoenc process_output_buf enter");
92 /* modification: set sync frame info while encoding */
93 if (omx_buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
94 GST_BUFFER_FLAG_UNSET(*buf, GST_BUFFER_FLAG_DELTA_UNIT);
96 GST_BUFFER_FLAG_SET(*buf, GST_BUFFER_FLAG_DELTA_UNIT);
99 return GSTOMX_RETURN_OK;
102 /* modification: get codec_data from omx component and set it caps */
104 process_output_caps(GstOmxBaseFilter * self, OMX_BUFFERHEADERTYPE *omx_buffer)
107 GstCaps *caps = NULL;
108 GstStructure *structure;
109 GValue value = { 0, {{0}
113 caps = gst_pad_get_negotiated_caps (self->srcpad);
114 caps = gst_caps_make_writable (caps);
115 structure = gst_caps_get_structure (caps, 0);
117 g_value_init (&value, GST_TYPE_BUFFER);
118 buf = gst_buffer_new_and_alloc (omx_buffer->nFilledLen);
119 memcpy (GST_BUFFER_DATA (buf),
120 omx_buffer->pBuffer + omx_buffer->nOffset, omx_buffer->nFilledLen);
121 gst_value_set_buffer (&value, buf);
122 gst_buffer_unref (buf);
123 gst_structure_set_value (structure, "codec_data", &value);
124 g_value_unset (&value);
126 gst_pad_set_caps (self->srcpad, caps);
127 gst_caps_unref (caps);
131 type_base_init (gpointer g_class)
136 set_property (GObject * obj,
137 guint prop_id, const GValue * value, GParamSpec * pspec)
139 GstOmxBaseVideoEnc *self;
141 self = GST_OMX_BASE_VIDEOENC (obj);
145 self->bitrate = g_value_get_uint (value);
147 /* modification: request to component to make key frame */
148 case ARG_FORCE_KEY_FRAME:
149 self->use_force_key_frame = g_value_get_boolean (value);
150 if (self->use_force_key_frame) {
151 add_force_key_frame (self);
152 self->use_force_key_frame = FALSE;
156 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
162 get_property (GObject * obj, guint prop_id, GValue * value, GParamSpec * pspec)
164 GstOmxBaseVideoEnc *self;
166 self = GST_OMX_BASE_VIDEOENC (obj);
170 /** @todo propagate this to OpenMAX when processing. */
171 g_value_set_uint (value, self->bitrate);
174 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
180 type_class_init (gpointer g_class, gpointer class_data)
182 GObjectClass *gobject_class;
183 GstOmxBaseFilterClass *basefilter_class;
184 // GstOmxBaseVideoEncClass *videoenc_class;
186 gobject_class = G_OBJECT_CLASS (g_class);
187 basefilter_class = GST_OMX_BASE_FILTER_CLASS (g_class);
188 // videoenc_class = GST_OMX_BASE_VIDEOENC_CLASS (g_class);
190 /* Properties stuff */
192 gobject_class->set_property = set_property;
193 gobject_class->get_property = get_property;
195 g_object_class_install_property (gobject_class, ARG_BITRATE,
196 g_param_spec_uint ("bitrate", "Bit-rate",
198 0, G_MAXUINT, DEFAULT_BITRATE,
199 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
201 g_object_class_install_property (gobject_class, ARG_FORCE_KEY_FRAME,
202 g_param_spec_boolean ("force-i-frame", "force the encoder to produce I frame",
203 "force the encoder to produce I frame",
205 G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
207 basefilter_class->process_input_buf = process_input_buf;
208 basefilter_class->process_output_buf = process_output_buf;
209 basefilter_class->process_output_caps = process_output_caps;
213 sink_setcaps (GstPad * pad, GstCaps * caps)
215 GstStructure *structure;
216 GstOmxBaseVideoEnc *self;
217 GstOmxBaseFilter *omx_base;
219 OMX_COLOR_FORMATTYPE color_format = OMX_COLOR_FormatUnused;
222 const GValue *framerate = NULL;
224 self = GST_OMX_BASE_VIDEOENC (GST_PAD_PARENT (pad));
225 omx_base = GST_OMX_BASE_FILTER (self);
226 gomx = (GOmxCore *) omx_base->gomx;
228 GST_INFO_OBJECT (self, "setcaps (sink): %" GST_PTR_FORMAT, caps);
230 g_return_val_if_fail (gst_caps_get_size (caps) == 1, FALSE);
232 structure = gst_caps_get_structure (caps, 0);
234 gst_structure_get_int (structure, "width", &width);
235 gst_structure_get_int (structure, "height", &height);
237 if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0) {
240 framerate = gst_structure_get_value (structure, "framerate");
242 self->framerate_num = gst_value_get_fraction_numerator (framerate);
243 self->framerate_denom = gst_value_get_fraction_denominator (framerate);
246 if (gst_structure_get_fourcc (structure, "format", &fourcc)) {
248 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
249 case GST_MAKE_FOURCC ('S', '4', '2', '0'):
250 color_format = OMX_COLOR_FormatYUV420PackedPlanar;
252 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
253 color_format = OMX_COLOR_FormatYCbYCr;
255 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
256 color_format = OMX_COLOR_FormatCbYCrY;
258 /* MODIFICATION: Add extended_color_format */
259 case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
260 color_format = OMX_EXT_COLOR_FormatNV12TPhysicalAddress;
262 case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
263 color_format = OMX_EXT_COLOR_FormatNV12LPhysicalAddress;
270 OMX_PARAM_PORTDEFINITIONTYPE param;
272 G_OMX_INIT_PARAM (param);
274 /* Input port configuration. */
276 param.nPortIndex = omx_base->in_port->port_index;
277 OMX_GetParameter (gomx->omx_handle, OMX_IndexParamPortDefinition, ¶m);
279 param.format.video.nFrameWidth = width;
280 param.format.video.nFrameHeight = height;
281 param.format.video.eColorFormat = color_format;
283 /* convert to Q.16 */
284 param.format.video.xFramerate =
285 (gst_value_get_fraction_numerator (framerate) << 16) /
286 gst_value_get_fraction_denominator (framerate);
289 OMX_SetParameter (gomx->omx_handle, OMX_IndexParamPortDefinition, ¶m);
292 /* modification: set nBufferSize */
293 G_OMX_INIT_PARAM (param);
295 param.nPortIndex = omx_base->out_port->port_index;
296 OMX_GetParameter (gomx->omx_handle, OMX_IndexParamPortDefinition, ¶m);
298 param.nBufferSize = width * height * 3 / 2;
299 OMX_SetParameter (gomx->omx_handle, OMX_IndexParamPortDefinition, ¶m);
302 return gst_pad_set_caps (pad, caps);
306 omx_setup (GstOmxBaseFilter * omx_base)
308 GstOmxBaseVideoEnc *self;
311 self = GST_OMX_BASE_VIDEOENC (omx_base);
312 gomx = (GOmxCore *) omx_base->gomx;
314 GST_INFO_OBJECT (omx_base, "begin");
317 OMX_PARAM_PORTDEFINITIONTYPE param;
319 G_OMX_INIT_PARAM (param);
321 /* Output port configuration. */
323 param.nPortIndex = omx_base->out_port->port_index;
324 OMX_GetParameter (gomx->omx_handle, OMX_IndexParamPortDefinition, ¶m);
326 param.format.video.eCompressionFormat = self->compression_format;
328 if (self->bitrate > 0)
329 param.format.video.nBitrate = self->bitrate;
331 OMX_SetParameter (gomx->omx_handle, OMX_IndexParamPortDefinition, ¶m);
335 /* modification: set bitrate by using OMX_IndexParamVideoBitrate macro*/
336 if (self->bitrate > 0) {
337 OMX_VIDEO_PARAM_BITRATETYPE param;
338 G_OMX_INIT_PARAM (param);
340 param.nPortIndex = omx_base->out_port->port_index;
341 OMX_GetParameter (gomx->omx_handle, OMX_IndexParamVideoBitrate, ¶m);
343 param.nTargetBitrate = self->bitrate;
344 param.eControlRate = OMX_Video_ControlRateConstant;
345 GST_INFO_OBJECT (self, "set bitrate (OMX_Video_ControlRateConstant): %d", param.nTargetBitrate);
347 OMX_SetParameter (gomx->omx_handle, OMX_IndexParamVideoBitrate, ¶m);
350 GST_INFO_OBJECT (omx_base, "end");
354 type_instance_init (GTypeInstance * instance, gpointer g_class)
356 GstOmxBaseFilter *omx_base;
357 GstOmxBaseVideoEnc *self;
359 omx_base = GST_OMX_BASE_FILTER (instance);
360 self = GST_OMX_BASE_VIDEOENC (instance);
362 omx_base->omx_setup = omx_setup;
364 gst_pad_set_setcaps_function (omx_base->sinkpad, sink_setcaps);
366 self->bitrate = DEFAULT_BITRATE;
367 self->use_force_key_frame = FALSE;