2 * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
3 * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation
8 * version 2.1 of the License.
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 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "gstomxh264enc.h"
28 #include "gstomxh264utils.h"
30 #ifdef USE_OMX_TARGET_RPI
31 #include <OMX_Broadcom.h>
32 #include <OMX_Index.h>
35 GST_DEBUG_CATEGORY_STATIC (gst_omx_h264_enc_debug_category);
36 #define GST_CAT_DEFAULT gst_omx_h264_enc_debug_category
39 static gboolean gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc,
40 GstOMXPort * port, GstVideoCodecState * state);
41 static GstCaps *gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc,
42 GstOMXPort * port, GstVideoCodecState * state);
43 static GstFlowReturn gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc *
44 self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
45 static gboolean gst_omx_h264_enc_flush (GstVideoEncoder * enc);
46 static gboolean gst_omx_h264_enc_stop (GstVideoEncoder * enc);
47 static void gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
48 const GValue * value, GParamSpec * pspec);
49 static void gst_omx_h264_enc_get_property (GObject * object, guint prop_id,
50 GValue * value, GParamSpec * pspec);
55 #ifdef USE_OMX_TARGET_RPI
56 PROP_INLINESPSPPSHEADERS,
58 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
62 PROP_PERIODICITYOFIDRFRAMES,
63 PROP_PERIODICITYOFIDRFRAMES_COMPAT,
64 PROP_INTERVALOFCODINGINTRAFRAMES,
67 PROP_CONSTRAINED_INTRA_PREDICTION,
68 PROP_LOOP_FILTER_MODE,
72 #ifdef USE_OMX_TARGET_RPI
73 #define GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT TRUE
75 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
76 #define GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT (0x00000001)
77 #define GST_OMX_VIDEO_ENC_NUM_REF_FRAME_MAX (0x00000002)
78 #define GST_OMX_VIDEO_ENC_NUM_B_FRAME_DEFAULT (0x00000001)
79 #define GST_OMX_VIDEO_ENC_NUM_B_FRAME_MAX (0x00000002)
81 #define GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT (0xffffffff)
82 #define GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
83 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
84 #define GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT (0)
85 #define ALIGNMENT "{ au, nal }"
87 #define GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT (0xffffffff)
88 #define ALIGNMENT "au"
90 #define GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT (0xffffffff)
91 #define GST_OMX_H264_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT (FALSE)
92 #define GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT (0xffffffff)
93 #define GST_OMX_H264_VIDEO_ENC_REF_FRAMES_DEFAULT 0
94 #define GST_OMX_H264_VIDEO_ENC_REF_FRAMES_MIN 0
95 #define GST_OMX_H264_VIDEO_ENC_REF_FRAMES_MAX 16
97 /* class initialization */
100 GST_DEBUG_CATEGORY_INIT (gst_omx_h264_enc_debug_category, "omxh264enc", 0, \
101 "debug category for gst-omx video encoder base class");
103 #define parent_class gst_omx_h264_enc_parent_class
104 G_DEFINE_TYPE_WITH_CODE (GstOMXH264Enc, gst_omx_h264_enc,
105 GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
107 #define GST_TYPE_OMX_H264_ENC_ENTROPY_MODE (gst_omx_h264_enc_entropy_mode_get_type ())
109 gst_omx_h264_enc_entropy_mode_get_type (void)
111 static GType qtype = 0;
114 static const GEnumValue values[] = {
115 {FALSE, "CAVLC entropy mode", "CAVLC"},
116 {TRUE, "CABAC entropy mode", "CABAC"},
117 {0xffffffff, "Component Default", "default"},
121 qtype = g_enum_register_static ("GstOMXH264EncEntropyMode", values);
126 #define GST_TYPE_OMX_H264_ENC_LOOP_FILTER_MODE (gst_omx_h264_enc_loop_filter_mode_get_type ())
128 gst_omx_h264_enc_loop_filter_mode_get_type (void)
130 static GType qtype = 0;
133 static const GEnumValue values[] = {
134 {OMX_VIDEO_AVCLoopFilterEnable, "Enable deblocking filter", "enable"},
135 {OMX_VIDEO_AVCLoopFilterDisable, "Disable deblocking filter", "disable"},
136 {OMX_VIDEO_AVCLoopFilterDisableSliceBoundary,
137 "Disables deblocking filter on slice boundary",
138 "disable-slice-boundary"},
139 {0xffffffff, "Component Default", "default"},
143 qtype = g_enum_register_static ("GstOMXH264EncLoopFilter", values);
149 gst_omx_h264_enc_class_init (GstOMXH264EncClass * klass)
151 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
152 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
153 GstVideoEncoderClass *basevideoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
154 GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
156 videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h264_enc_set_format);
157 videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h264_enc_get_caps);
159 gobject_class->set_property = gst_omx_h264_enc_set_property;
160 gobject_class->get_property = gst_omx_h264_enc_get_property;
162 #ifdef USE_OMX_TARGET_RPI
163 g_object_class_install_property (gobject_class, PROP_INLINESPSPPSHEADERS,
164 g_param_spec_boolean ("inline-header",
165 "Inline SPS/PPS headers before IDR",
166 "Inline SPS/PPS header before IDR",
167 GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT,
168 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
169 GST_PARAM_MUTABLE_READY));
171 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
172 g_object_class_install_property (gobject_class, PROP_NUM_REF_FRAME,
173 g_param_spec_uint ("reference-frame", "set number of reference frame",
174 "The number of reference frame (0x00000001=component default)",
175 GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT, GST_OMX_VIDEO_ENC_NUM_REF_FRAME_MAX,
176 GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT,
177 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
178 GST_PARAM_MUTABLE_READY));
180 g_object_class_install_property (gobject_class, PROP_NUM_B_FRAME,
181 g_param_spec_uint ("b-frame", "set number of b frame",
182 "The number of reference frame (0x00000001=component default)",
183 GST_OMX_VIDEO_ENC_NUM_B_FRAME_DEFAULT, GST_OMX_VIDEO_ENC_NUM_B_FRAME_MAX,
184 GST_OMX_VIDEO_ENC_NUM_B_FRAME_DEFAULT,
185 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
186 GST_PARAM_MUTABLE_READY));
188 g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
189 g_param_spec_uint ("periodicity-idr", "IDR periodicity",
190 "Periodicity of IDR frames (0xffffffff=component default)",
192 GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
193 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
194 GST_PARAM_MUTABLE_READY));
196 g_object_class_install_property (gobject_class,
197 PROP_PERIODICITYOFIDRFRAMES_COMPAT, g_param_spec_uint ("periodicty-idr",
199 "Periodicity of IDR frames (0xffffffff=component default) DEPRECATED - only for backwards compat",
201 GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
202 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
203 GST_PARAM_MUTABLE_READY));
205 g_object_class_install_property (gobject_class,
206 PROP_INTERVALOFCODINGINTRAFRAMES,
207 g_param_spec_uint ("interval-intraframes",
208 "Interval of coding Intra frames",
209 "Interval of coding Intra frames (0xffffffff=component default)", 0,
211 GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT,
212 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
213 GST_PARAM_MUTABLE_READY));
215 g_object_class_install_property (gobject_class, PROP_B_FRAMES,
216 g_param_spec_uint ("b-frames", "Number of B-frames",
217 "Number of B-frames between two consecutive I-frames (0xffffffff=component default)",
218 0, G_MAXUINT, GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT,
219 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
220 GST_PARAM_MUTABLE_READY));
222 g_object_class_install_property (gobject_class, PROP_ENTROPY_MODE,
223 g_param_spec_enum ("entropy-mode", "Entropy Mode",
224 "Entropy mode for encoding process",
225 GST_TYPE_OMX_H264_ENC_ENTROPY_MODE,
226 GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT,
227 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
228 GST_PARAM_MUTABLE_READY));
230 g_object_class_install_property (gobject_class,
231 PROP_CONSTRAINED_INTRA_PREDICTION,
232 g_param_spec_boolean ("constrained-intra-prediction",
233 "Constrained Intra Prediction",
234 "If enabled, prediction only uses residual data and decoded samples "
235 "from neighbouring coding blocks coded using intra prediction modes",
236 GST_OMX_H264_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT,
237 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
238 GST_PARAM_MUTABLE_READY));
240 g_object_class_install_property (gobject_class, PROP_LOOP_FILTER_MODE,
241 g_param_spec_enum ("loop-filter-mode", "Loop Filter mode",
242 "Enable or disable the deblocking filter (0xffffffff=component default)",
243 GST_TYPE_OMX_H264_ENC_LOOP_FILTER_MODE,
244 GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT,
245 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
246 GST_PARAM_MUTABLE_READY));
248 g_object_class_install_property (gobject_class, PROP_REF_FRAMES,
249 g_param_spec_uchar ("ref-frames", "Reference frames",
250 "Number of reference frames used for inter-motion search (0=component default)",
251 GST_OMX_H264_VIDEO_ENC_REF_FRAMES_MIN,
252 GST_OMX_H264_VIDEO_ENC_REF_FRAMES_MAX,
253 GST_OMX_H264_VIDEO_ENC_REF_FRAMES_DEFAULT,
254 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
255 GST_PARAM_MUTABLE_READY));
257 basevideoenc_class->flush = gst_omx_h264_enc_flush;
258 basevideoenc_class->stop = gst_omx_h264_enc_stop;
260 videoenc_class->cdata.default_src_template_caps = "video/x-h264, "
261 "width = (int) [ 16, 4096 ], height = (int) [ 16, 4096 ], "
262 "framerate = (fraction) [0, MAX], stream-format=(string) byte-stream, "
263 "alignment = (string) " ALIGNMENT;
264 videoenc_class->handle_output_frame =
265 GST_DEBUG_FUNCPTR (gst_omx_h264_enc_handle_output_frame);
267 gst_element_class_set_static_metadata (element_class,
268 "OpenMAX H.264 Video Encoder",
269 "Codec/Encoder/Video/Hardware",
270 "Encode H.264 video streams",
271 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
273 gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.avc");
277 gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
278 const GValue * value, GParamSpec * pspec)
280 GstOMXH264Enc *self = GST_OMX_H264_ENC (object);
283 #ifdef USE_OMX_TARGET_RPI
284 case PROP_INLINESPSPPSHEADERS:
285 self->inline_sps_pps_headers = g_value_get_boolean (value);
288 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
289 case PROP_NUM_REF_FRAME:
290 self->reference_frame = g_value_get_int (value);
292 case PROP_NUM_B_FRAME:
293 self->b_frame = g_value_get_int (value);
296 case PROP_PERIODICITYOFIDRFRAMES:
297 case PROP_PERIODICITYOFIDRFRAMES_COMPAT:
298 self->periodicty_idr = g_value_get_uint (value);
300 case PROP_INTERVALOFCODINGINTRAFRAMES:
301 self->interval_intraframes = g_value_get_uint (value);
304 self->b_frames = g_value_get_uint (value);
306 case PROP_ENTROPY_MODE:
307 self->entropy_mode = g_value_get_enum (value);
309 case PROP_CONSTRAINED_INTRA_PREDICTION:
310 self->constrained_intra_prediction = g_value_get_boolean (value);
312 case PROP_LOOP_FILTER_MODE:
313 self->loop_filter_mode = g_value_get_enum (value);
315 case PROP_REF_FRAMES:
316 self->ref_frames = g_value_get_uchar (value);
319 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
325 gst_omx_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
328 GstOMXH264Enc *self = GST_OMX_H264_ENC (object);
331 #ifdef USE_OMX_TARGET_RPI
332 case PROP_INLINESPSPPSHEADERS:
333 g_value_set_boolean (value, self->inline_sps_pps_headers);
336 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
337 case PROP_NUM_REF_FRAME:
338 g_value_set_uint (value, self->reference_frame);
340 case PROP_NUM_B_FRAME:
341 g_value_set_uint (value, self->b_frame);
344 case PROP_PERIODICITYOFIDRFRAMES:
345 case PROP_PERIODICITYOFIDRFRAMES_COMPAT:
346 g_value_set_uint (value, self->periodicty_idr);
348 case PROP_INTERVALOFCODINGINTRAFRAMES:
349 g_value_set_uint (value, self->interval_intraframes);
352 g_value_set_uint (value, self->b_frames);
354 case PROP_ENTROPY_MODE:
355 g_value_set_enum (value, self->entropy_mode);
357 case PROP_CONSTRAINED_INTRA_PREDICTION:
358 g_value_set_boolean (value, self->constrained_intra_prediction);
360 case PROP_LOOP_FILTER_MODE:
361 g_value_set_enum (value, self->loop_filter_mode);
363 case PROP_REF_FRAMES:
364 g_value_set_uchar (value, self->ref_frames);
367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
373 gst_omx_h264_enc_init (GstOMXH264Enc * self)
375 #ifdef USE_OMX_TARGET_RPI
376 self->inline_sps_pps_headers =
377 GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT;
379 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
380 self->reference_frame = GST_OMX_VIDEO_ENC_NUM_REF_FRAME_DEFAULT;
382 self->periodicty_idr =
383 GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
384 self->interval_intraframes =
385 GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT;
386 self->b_frames = GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT;
387 self->entropy_mode = GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT;
388 self->constrained_intra_prediction =
389 GST_OMX_H264_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT;
390 self->loop_filter_mode = GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT;
391 self->ref_frames = GST_OMX_H264_VIDEO_ENC_REF_FRAMES_DEFAULT;
395 gst_omx_h264_enc_flush (GstVideoEncoder * enc)
397 GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
399 g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
400 self->headers = NULL;
402 return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (enc);
406 gst_omx_h264_enc_stop (GstVideoEncoder * enc)
408 GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
410 g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
411 self->headers = NULL;
413 return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc);
416 /* Update OMX_VIDEO_PARAM_PROFILELEVELTYPE.{eProfile,eLevel}
418 * Returns TRUE if succeeded or if not supported, FALSE if failed */
420 update_param_profile_level (GstOMXH264Enc * self,
421 OMX_VIDEO_AVCPROFILETYPE profile, OMX_VIDEO_AVCLEVELTYPE level)
423 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
426 GST_OMX_INIT_STRUCT (¶m);
427 param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
430 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
431 OMX_IndexParamVideoProfileLevelCurrent, ¶m);
432 if (err != OMX_ErrorNone) {
433 GST_WARNING_OBJECT (self,
434 "Getting OMX_IndexParamVideoProfileLevelCurrent not supported by component");
438 if (profile != OMX_VIDEO_AVCProfileMax)
439 param.eProfile = profile;
440 if (level != OMX_VIDEO_AVCLevelMax)
441 param.eLevel = level;
444 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
445 OMX_IndexParamVideoProfileLevelCurrent, ¶m);
446 if (err == OMX_ErrorUnsupportedIndex) {
447 GST_WARNING_OBJECT (self,
448 "Setting OMX_IndexParamVideoProfileLevelCurrent not supported by component");
450 } else if (err != OMX_ErrorNone) {
451 GST_ERROR_OBJECT (self,
452 "Error setting profile %u and level %u: %s (0x%08x)",
453 (guint) param.eProfile, (guint) param.eLevel,
454 gst_omx_error_to_string (err), err);
461 /* Update OMX_VIDEO_PARAM_AVCTYPE
463 * Returns TRUE if succeeded or if not supported, FALSE if failed */
465 update_param_avc (GstOMXH264Enc * self,
466 OMX_VIDEO_AVCPROFILETYPE profile, OMX_VIDEO_AVCLEVELTYPE level)
468 OMX_VIDEO_PARAM_AVCTYPE param;
471 GST_OMX_INIT_STRUCT (¶m);
472 param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
474 /* On Android the param struct is initialized manually with default
475 * settings rather than using GetParameter() to retrieve them.
476 * We should probably do the same when we'll add Android as target.
477 * See bgo#783862 for details. */
480 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
481 OMX_IndexParamVideoAvc, ¶m);
482 if (err != OMX_ErrorNone) {
483 GST_WARNING_OBJECT (self,
484 "Getting OMX_IndexParamVideoAvc not supported by component");
488 if (profile != OMX_VIDEO_AVCProfileMax)
489 param.eProfile = profile;
490 if (level != OMX_VIDEO_AVCLevelMax)
491 param.eLevel = level;
494 if (self->interval_intraframes !=
495 GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
496 param.nPFrames = self->interval_intraframes;
498 /* If user specified a specific number of B-frames, reduce the number of
499 * P-frames by this amount. If not ensure there is no B-frame to have the
500 * requested GOP length. */
501 if (self->b_frames != GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT) {
502 if (self->b_frames > self->interval_intraframes) {
503 GST_ERROR_OBJECT (self,
504 "The interval_intraframes perdiod (%u) needs to be higher than the number of B-frames (%u)",
505 self->interval_intraframes, self->b_frames);
508 param.nPFrames -= self->b_frames;
514 if (self->b_frames != GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT) {
515 if (profile == OMX_VIDEO_AVCProfileBaseline && self->b_frames > 0) {
516 GST_ERROR_OBJECT (self,
517 "Baseline profile doesn't support B-frames (%u requested)",
521 param.nBFrames = self->b_frames;
524 if (self->ref_frames != GST_OMX_H264_VIDEO_ENC_REF_FRAMES_DEFAULT)
525 param.nRefFrames = self->ref_frames;
527 if (self->entropy_mode != GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT) {
528 param.bEntropyCodingCABAC = self->entropy_mode;
531 param.bconstIpred = self->constrained_intra_prediction;
533 if (self->loop_filter_mode != GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT) {
534 param.eLoopFilterMode = self->loop_filter_mode;
538 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
539 OMX_IndexParamVideoAvc, ¶m);
540 if (err == OMX_ErrorUnsupportedIndex) {
541 GST_WARNING_OBJECT (self,
542 "Setting OMX_IndexParamVideoAvc not supported by component");
544 } else if (err != OMX_ErrorNone) {
545 GST_ERROR_OBJECT (self,
546 "Error setting AVC settings (profile %u and level %u): %s (0x%08x)",
547 (guint) param.eProfile, (guint) param.eLevel,
548 gst_omx_error_to_string (err), err);
556 set_avc_intra_period (GstOMXH264Enc * self)
558 OMX_VIDEO_CONFIG_AVCINTRAPERIOD config_avcintraperiod;
561 GST_OMX_INIT_STRUCT (&config_avcintraperiod);
562 config_avcintraperiod.nPortIndex =
563 GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
565 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
566 OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
567 if (err == OMX_ErrorUnsupportedIndex) {
568 GST_WARNING_OBJECT (self,
569 "OMX_IndexConfigVideoAVCIntraPeriod not supported by component");
571 } else if (err != OMX_ErrorNone) {
572 GST_ERROR_OBJECT (self,
573 "can't get OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
574 gst_omx_error_to_string (err), err);
578 GST_DEBUG_OBJECT (self, "default nPFrames:%u, nIDRPeriod:%u",
579 (guint) config_avcintraperiod.nPFrames,
580 (guint) config_avcintraperiod.nIDRPeriod);
582 if (self->periodicty_idr !=
583 GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT) {
584 config_avcintraperiod.nIDRPeriod = self->periodicty_idr;
587 if (self->interval_intraframes !=
588 GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
589 /* This OMX API doesn't allow us to specify the number of B-frames.
590 * So if user requested one we have to rely on update_param_avc()
591 * to configure the intraframes interval so it can take the
592 * B-frames into account. */
593 if (self->b_frames == GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT)
594 config_avcintraperiod.nPFrames = self->interval_intraframes;
598 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
599 OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
600 if (err != OMX_ErrorNone) {
601 GST_ERROR_OBJECT (self,
602 "can't set OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
603 gst_omx_error_to_string (err), err);
610 #ifdef USE_OMX_TARGET_RPI
612 set_brcm_video_intra_period (GstOMXH264Enc * self)
614 OMX_PARAM_U32TYPE intra_period;
617 GST_OMX_INIT_STRUCT (&intra_period);
619 intra_period.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
621 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
622 OMX_IndexConfigBrcmVideoIntraPeriod, &intra_period);
623 if (err != OMX_ErrorNone) {
624 GST_ERROR_OBJECT (self,
625 "can't get OMX_IndexConfigBrcmVideoIntraPeriod %s (0x%08x)",
626 gst_omx_error_to_string (err), err);
630 GST_DEBUG_OBJECT (self, "default OMX_IndexConfigBrcmVideoIntraPeriod: %u",
631 (guint) intra_period.nU32);
633 if (self->interval_intraframes ==
634 GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT)
637 intra_period.nU32 = self->interval_intraframes;
640 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
641 OMX_IndexConfigBrcmVideoIntraPeriod, &intra_period);
642 if (err != OMX_ErrorNone) {
643 GST_ERROR_OBJECT (self,
644 "can't set OMX_IndexConfigBrcmVideoIntraPeriod %s (0x%08x)",
645 gst_omx_error_to_string (err), err);
649 GST_DEBUG_OBJECT (self, "OMX_IndexConfigBrcmVideoIntraPeriod set to %u",
650 (guint) intra_period.nU32);
657 gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
658 GstVideoCodecState * state)
660 GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
662 OMX_PARAM_PORTDEFINITIONTYPE port_def;
663 #ifdef USE_OMX_TARGET_RPI
664 OMX_CONFIG_PORTBOOLEANTYPE config_inline_header;
666 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
667 OMX_VIDEO_PARAM_AVCTYPE avc_param;
670 const gchar *profile_string, *level_string;
671 OMX_VIDEO_AVCPROFILETYPE profile = OMX_VIDEO_AVCProfileMax;
672 OMX_VIDEO_AVCLEVELTYPE level = OMX_VIDEO_AVCLevelMax;
673 gboolean enable_subframe = FALSE;
675 #ifdef USE_OMX_TARGET_RPI
676 GST_OMX_INIT_STRUCT (&config_inline_header);
677 config_inline_header.nPortIndex =
678 GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
680 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
681 OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
682 if (err != OMX_ErrorNone) {
683 GST_ERROR_OBJECT (self,
684 "can't get OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
685 gst_omx_error_to_string (err), err);
689 if (self->inline_sps_pps_headers) {
690 config_inline_header.bEnabled = OMX_TRUE;
692 config_inline_header.bEnabled = OMX_FALSE;
696 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
697 OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
698 if (err != OMX_ErrorNone) {
699 GST_ERROR_OBJECT (self,
700 "can't set OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
701 gst_omx_error_to_string (err), err);
705 #if defined(USE_OMX_TARGET_EXYNOS) || defined(USE_OMX_TARGET_EXYNOS64)
706 GST_OMX_INIT_STRUCT (&avc_param);
709 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
710 OMX_IndexParamVideoAvc, &avc_param);
711 if (err != OMX_ErrorNone) {
712 GST_ERROR_OBJECT (self,
713 "can't get OMX_IndexParamVideoAvc %s (0x%08x)",
714 gst_omx_error_to_string (err), err);
718 GST_DEBUG_OBJECT (self, "default nRefFrames:%u, nBFrames:%u",
719 (guint) avc_param.nRefFrames,
720 (guint) avc_param.nBFrames);
722 avc_param.nRefFrames = self->reference_frame;
723 avc_param.nBFrames = self->b_frame;
725 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
726 OMX_IndexParamVideoAvc, &avc_param);
727 if (err != OMX_ErrorNone) {
728 GST_ERROR_OBJECT (self,
729 "can't set OMX_IndexParamVideoAvc %s (0x%08x)",
730 gst_omx_error_to_string (err), err);
736 /* Configure GOP pattern */
737 if (self->periodicty_idr !=
738 GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT
739 || self->interval_intraframes !=
740 GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
741 set_avc_intra_period (self);
743 #ifdef USE_OMX_TARGET_RPI
744 /* The Pi uses a specific OMX setting to configure the intra period */
746 if (self->interval_intraframes)
747 set_brcm_video_intra_period (self);
750 gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
752 port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
754 gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
755 (self)->enc_out_port, &port_def);
756 if (err != OMX_ErrorNone)
759 /* Set profile and level */
760 peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
761 gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
764 const gchar *alignment_string;
766 if (gst_caps_is_empty (peercaps)) {
767 gst_caps_unref (peercaps);
768 GST_ERROR_OBJECT (self, "Empty caps");
772 s = gst_caps_get_structure (peercaps, 0);
773 profile_string = gst_structure_get_string (s, "profile");
774 if (profile_string) {
775 profile = gst_omx_h264_utils_get_profile_from_str (profile_string);
776 if (profile == OMX_VIDEO_AVCProfileMax)
777 goto unsupported_profile;
779 level_string = gst_structure_get_string (s, "level");
781 level = gst_omx_h264_utils_get_level_from_str (level_string);
782 if (level == OMX_VIDEO_AVCLevelMax)
783 goto unsupported_level;
786 alignment_string = gst_structure_get_string (s, "alignment");
787 if (alignment_string && g_str_equal (alignment_string, "nal"))
788 enable_subframe = TRUE;
790 gst_caps_unref (peercaps);
793 if (profile != OMX_VIDEO_AVCProfileMax || level != OMX_VIDEO_AVCLevelMax) {
794 /* OMX provides 2 API to set the profile and level. We try using the
795 * generic one here and the H264 specific when calling
796 * update_param_avc() */
797 if (!update_param_profile_level (self, profile, level))
801 gst_omx_port_set_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port,
804 if (!update_param_avc (self, profile, level))
810 GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
811 gst_caps_unref (peercaps);
815 GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
816 gst_caps_unref (peercaps);
821 gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
822 GstVideoCodecState * state)
824 GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
827 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
828 const gchar *profile, *level, *alignment;
830 GST_OMX_INIT_STRUCT (¶m);
831 param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
834 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
835 OMX_IndexParamVideoProfileLevelCurrent, ¶m);
836 if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex)
839 if (gst_omx_port_get_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port))
844 caps = gst_caps_new_simple ("video/x-h264",
845 "stream-format", G_TYPE_STRING, "byte-stream",
846 "alignment", G_TYPE_STRING, alignment, NULL);
848 if (err == OMX_ErrorNone) {
849 profile = gst_omx_h264_utils_get_profile_from_enum (param.eProfile);
851 g_assert_not_reached ();
852 gst_caps_unref (caps);
856 switch (param.eLevel) {
857 case OMX_VIDEO_AVCLevel1:
860 case OMX_VIDEO_AVCLevel1b:
863 case OMX_VIDEO_AVCLevel11:
866 case OMX_VIDEO_AVCLevel12:
869 case OMX_VIDEO_AVCLevel13:
872 case OMX_VIDEO_AVCLevel2:
875 case OMX_VIDEO_AVCLevel21:
878 case OMX_VIDEO_AVCLevel22:
881 case OMX_VIDEO_AVCLevel3:
884 case OMX_VIDEO_AVCLevel31:
887 case OMX_VIDEO_AVCLevel32:
890 case OMX_VIDEO_AVCLevel4:
893 case OMX_VIDEO_AVCLevel41:
896 case OMX_VIDEO_AVCLevel42:
899 case OMX_VIDEO_AVCLevel5:
902 case OMX_VIDEO_AVCLevel51:
905 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
906 case OMX_ALG_VIDEO_AVCLevel52:
909 case OMX_ALG_VIDEO_AVCLevel60:
912 case OMX_ALG_VIDEO_AVCLevel61:
915 case OMX_ALG_VIDEO_AVCLevel62:
920 g_assert_not_reached ();
921 gst_caps_unref (caps);
924 gst_caps_set_simple (caps,
925 "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level, NULL);
932 gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port,
933 GstOMXBuffer * buf, GstVideoCodecFrame * frame)
935 GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
937 if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
938 /* The codec data is SPS/PPS but our output is stream-format=byte-stream.
939 * For bytestream stream format the SPS/PPS is only in-stream and not
943 GstMapInfo map = GST_MAP_INFO_INIT;
944 GstFlowReturn flow_ret;
946 GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format");
948 hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
949 GST_BUFFER_FLAG_SET (hdrs, GST_BUFFER_FLAG_HEADER);
951 gst_buffer_map (hdrs, &map, GST_MAP_WRITE);
953 buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
954 buf->omx_buf->nFilledLen);
955 gst_buffer_unmap (hdrs, &map);
956 self->headers = g_list_append (self->headers, gst_buffer_ref (hdrs));
957 frame->output_buffer = hdrs;
959 gst_video_encoder_finish_subframe (GST_VIDEO_ENCODER (self), frame);
960 gst_video_codec_frame_unref (frame);
963 } else if (self->headers) {
964 gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers);
965 self->headers = NULL;
969 GST_OMX_VIDEO_ENC_CLASS
970 (gst_omx_h264_enc_parent_class)->handle_output_frame (enc, port, buf,