2 * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
3 * Copyright (C) 2017 Xilinx, Inc.
4 * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
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
28 #include "gstomxh265enc.h"
29 #include "gstomxh265utils.h"
30 #include "gstomxvideo.h"
32 GST_DEBUG_CATEGORY_STATIC (gst_omx_h265_enc_debug_category);
33 #define GST_CAT_DEFAULT gst_omx_h265_enc_debug_category
36 static gboolean gst_omx_h265_enc_set_format (GstOMXVideoEnc * enc,
37 GstOMXPort * port, GstVideoCodecState * state);
38 static GstCaps *gst_omx_h265_enc_get_caps (GstOMXVideoEnc * enc,
39 GstOMXPort * port, GstVideoCodecState * state);
40 static void gst_omx_h265_enc_set_property (GObject * object, guint prop_id,
41 const GValue * value, GParamSpec * pspec);
42 static void gst_omx_h265_enc_get_property (GObject * object, guint prop_id,
43 GValue * value, GParamSpec * pspec);
44 static GstFlowReturn gst_omx_h265_enc_handle_output_frame (GstOMXVideoEnc *
45 self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
50 PROP_PERIODICITYOFIDRFRAMES,
51 PROP_INTERVALOFCODINGINTRAFRAMES,
53 PROP_CONSTRAINED_INTRA_PREDICTION,
54 PROP_LOOP_FILTER_MODE,
57 #define GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT (0xffffffff)
58 #define GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
59 #define GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT (0xffffffff)
60 #define GST_OMX_H265_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT (FALSE)
61 #define GST_OMX_H265_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT (0xffffffff)
63 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
64 /* zynqultrascaleplus's OMX uses a param struct different of Android's one */
65 #define INDEX_PARAM_VIDEO_HEVC OMX_ALG_IndexParamVideoHevc
66 #define ALIGNMENT "{ au, nal }"
68 #define INDEX_PARAM_VIDEO_HEVC OMX_IndexParamVideoHevc
69 #define ALIGNMENT "au"
72 /* class initialization */
75 GST_DEBUG_CATEGORY_INIT (gst_omx_h265_enc_debug_category, "omxh265enc", 0, \
76 "debug category for gst-omx H265 video encoder");
78 #define parent_class gst_omx_h265_enc_parent_class
79 G_DEFINE_TYPE_WITH_CODE (GstOMXH265Enc, gst_omx_h265_enc,
80 GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
82 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
83 #define GST_TYPE_OMX_H265_ENC_LOOP_FILTER_MODE (gst_omx_h265_enc_loop_filter_mode_get_type ())
85 gst_omx_h265_enc_loop_filter_mode_get_type (void)
87 static GType qtype = 0;
90 static const GEnumValue values[] = {
91 {OMX_ALG_VIDEO_HEVCLoopFilterEnable, "Enable deblocking filter",
93 {OMX_ALG_VIDEO_HEVCLoopFilterDisable, "Disable deblocking filter",
95 {OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossSlice,
96 "Disable deblocking filter on slice boundary", "disable-cross-slice"},
97 {OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossTile,
98 "Disable deblocking filter on tile boundary", "disable-cross-tile"},
99 {OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossSliceAndTile,
100 "Disable deblocking filter on slice and tile boundary",
101 "disable-slice-and-tile"},
102 {0xffffffff, "Component Default", "default"},
106 qtype = g_enum_register_static ("GstOMXH265EncLoopFilter", values);
113 gst_omx_h265_enc_flush (GstVideoEncoder * enc)
115 GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
117 g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
118 self->headers = NULL;
120 return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (enc);
124 gst_omx_h265_enc_stop (GstVideoEncoder * enc)
126 GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
128 g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
129 self->headers = NULL;
131 return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc);
135 gst_omx_h265_enc_class_init (GstOMXH265EncClass * klass)
137 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
138 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
139 GstVideoEncoderClass *basevideoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
140 GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
142 videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h265_enc_set_format);
143 videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h265_enc_get_caps);
144 videoenc_class->handle_output_frame =
145 GST_DEBUG_FUNCPTR (gst_omx_h265_enc_handle_output_frame);
147 basevideoenc_class->flush = gst_omx_h265_enc_flush;
148 basevideoenc_class->stop = gst_omx_h265_enc_stop;
150 gobject_class->set_property = gst_omx_h265_enc_set_property;
151 gobject_class->get_property = gst_omx_h265_enc_get_property;
153 g_object_class_install_property (gobject_class,
154 PROP_INTERVALOFCODINGINTRAFRAMES,
155 g_param_spec_uint ("interval-intraframes",
156 "Interval of coding Intra frames",
157 "Interval of coding Intra frames (0xffffffff=component default)", 0,
159 GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT,
160 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
161 GST_PARAM_MUTABLE_READY));
163 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
164 g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
165 g_param_spec_uint ("periodicity-idr", "IDR periodicity",
166 "Periodicity of IDR frames (0xffffffff=component default)",
168 GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
169 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
170 GST_PARAM_MUTABLE_READY));
172 g_object_class_install_property (gobject_class, PROP_B_FRAMES,
173 g_param_spec_uint ("b-frames", "Number of B-frames",
174 "Number of B-frames between two consecutive I-frames (0xffffffff=component default)",
175 0, G_MAXUINT, GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT,
176 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
177 GST_PARAM_MUTABLE_READY));
179 g_object_class_install_property (gobject_class,
180 PROP_CONSTRAINED_INTRA_PREDICTION,
181 g_param_spec_boolean ("constrained-intra-prediction",
182 "Constrained Intra Prediction",
183 "If enabled, prediction only uses residual data and decoded samples "
184 "from neighbouring coding blocks coded using intra prediction modes",
185 GST_OMX_H265_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT,
186 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
187 GST_PARAM_MUTABLE_READY));
189 g_object_class_install_property (gobject_class, PROP_LOOP_FILTER_MODE,
190 g_param_spec_enum ("loop-filter-mode", "Loop Filter mode",
191 "Enable or disable the deblocking filter (0xffffffff=component default)",
192 GST_TYPE_OMX_H265_ENC_LOOP_FILTER_MODE,
193 GST_OMX_H265_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT,
194 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
195 GST_PARAM_MUTABLE_READY));
198 videoenc_class->cdata.default_sink_template_caps =
199 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
200 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_FORMAT_INTERLACED,
201 GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS)
202 ", interlace-mode = (string) alternate ; "
204 GST_VIDEO_CAPS_MAKE (GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS);
206 videoenc_class->cdata.default_src_template_caps = "video/x-h265, "
207 "width=(int) [ 1, MAX ], " "height=(int) [ 1, MAX ], "
208 "framerate = (fraction) [0, MAX], stream-format=(string) byte-stream, "
209 "aligmment = (string) " ALIGNMENT;
211 gst_element_class_set_static_metadata (element_class,
212 "OpenMAX H.265 Video Encoder",
213 "Codec/Encoder/Video/Hardware",
214 "Encode H.265 video streams",
215 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
217 gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.hevc");
221 gst_omx_h265_enc_set_property (GObject * object, guint prop_id,
222 const GValue * value, GParamSpec * pspec)
224 GstOMXH265Enc *self = GST_OMX_H265_ENC (object);
227 case PROP_INTERVALOFCODINGINTRAFRAMES:
228 self->interval_intraframes = g_value_get_uint (value);
230 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
231 case PROP_PERIODICITYOFIDRFRAMES:
232 self->periodicity_idr = g_value_get_uint (value);
235 self->b_frames = g_value_get_uint (value);
237 case PROP_CONSTRAINED_INTRA_PREDICTION:
238 self->constrained_intra_prediction = g_value_get_boolean (value);
240 case PROP_LOOP_FILTER_MODE:
241 self->loop_filter_mode = g_value_get_enum (value);
245 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
251 gst_omx_h265_enc_get_property (GObject * object, guint prop_id, GValue * value,
254 GstOMXH265Enc *self = GST_OMX_H265_ENC (object);
257 case PROP_INTERVALOFCODINGINTRAFRAMES:
258 g_value_set_uint (value, self->interval_intraframes);
260 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
261 case PROP_PERIODICITYOFIDRFRAMES:
262 g_value_set_uint (value, self->periodicity_idr);
265 g_value_set_uint (value, self->b_frames);
267 case PROP_CONSTRAINED_INTRA_PREDICTION:
268 g_value_set_boolean (value, self->constrained_intra_prediction);
270 case PROP_LOOP_FILTER_MODE:
271 g_value_set_enum (value, self->loop_filter_mode);
275 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
281 gst_omx_h265_enc_init (GstOMXH265Enc * self)
283 self->interval_intraframes =
284 GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT;
285 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
286 self->periodicity_idr =
287 GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
288 self->b_frames = GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT;
289 self->constrained_intra_prediction =
290 GST_OMX_H265_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT;
291 self->loop_filter_mode = GST_OMX_H265_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT;
295 /* Update OMX_VIDEO_PARAM_PROFILELEVELTYPE.{eProfile,eLevel}
297 * Returns TRUE if succeeded or if not supported, FALSE if failed */
299 update_param_profile_level (GstOMXH265Enc * self,
300 OMX_VIDEO_HEVCPROFILETYPE profile, OMX_VIDEO_HEVCLEVELTYPE level)
302 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
305 GST_OMX_INIT_STRUCT (¶m);
306 param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
309 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
310 OMX_IndexParamVideoProfileLevelCurrent, ¶m);
311 if (err != OMX_ErrorNone) {
312 GST_WARNING_OBJECT (self,
313 "Getting OMX_IndexParamVideoProfileLevelCurrent not supported by component");
317 if (profile != OMX_VIDEO_HEVCProfileUnknown)
318 param.eProfile = profile;
319 if (level != OMX_VIDEO_HEVCLevelUnknown)
320 param.eLevel = level;
323 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
324 OMX_IndexParamVideoProfileLevelCurrent, ¶m);
325 if (err == OMX_ErrorUnsupportedIndex) {
326 GST_WARNING_OBJECT (self,
327 "Setting OMX_IndexParamVideoProfileLevelCurrent not supported by component");
329 } else if (err != OMX_ErrorNone) {
330 GST_ERROR_OBJECT (self,
331 "Error setting profile %u and level %u: %s (0x%08x)",
332 (guint) param.eProfile, (guint) param.eLevel,
333 gst_omx_error_to_string (err), err);
340 /* Update OMX_ALG_VIDEO_PARAM_HEVCTYPE
342 * Returns TRUE if succeeded or if not supported, FALSE if failed */
344 update_param_hevc (GstOMXH265Enc * self,
345 OMX_VIDEO_HEVCPROFILETYPE profile, OMX_VIDEO_HEVCLEVELTYPE level)
347 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
348 OMX_ALG_VIDEO_PARAM_HEVCTYPE param;
350 OMX_VIDEO_PARAM_HEVCTYPE param;
354 GST_OMX_INIT_STRUCT (¶m);
355 param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
357 /* On Android the param struct is initialized manually with default
358 * settings rather than using GetParameter() to retrieve them.
359 * We should probably do the same when we'll add Android as target.
360 * See bgo#783862 for details. */
362 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
363 param.bConstIpred = self->constrained_intra_prediction;
365 if (self->loop_filter_mode != GST_OMX_H265_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT)
366 param.eLoopFilterMode = self->loop_filter_mode;
369 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
370 (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoHevc, ¶m);
373 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
374 (OMX_INDEXTYPE) OMX_IndexParamVideoHevc, ¶m);
377 if (err != OMX_ErrorNone) {
378 GST_WARNING_OBJECT (self,
379 "Getting OMX_ALG_IndexParamVideoHevc not supported by component");
383 if (profile != OMX_VIDEO_HEVCProfileUnknown)
384 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
385 param.eProfile = (OMX_ALG_VIDEO_HEVCPROFILETYPE) profile;
387 param.eProfile = profile;
390 if (level != OMX_VIDEO_HEVCLevelUnknown)
391 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
392 param.eLevel = (OMX_ALG_VIDEO_HEVCLEVELTYPE) level;
394 param.eLevel = level;
398 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
399 /* The zynqultrascaleplus uses another PARAM_HEVCTYPE API allowing users to
400 * define the number of P and B frames while Android's API only expose the
402 if (self->interval_intraframes !=
403 GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
404 param.nPFrames = self->interval_intraframes;
406 /* If user specified a specific number of B-frames, reduce the number of
407 * P-frames by this amount. If not ensure there is no B-frame to have the
408 * requested GOP length. */
409 if (self->b_frames != GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT) {
410 if (self->b_frames > self->interval_intraframes) {
411 GST_ERROR_OBJECT (self,
412 "The interval_intraframes perdiod (%u) needs to be higher than the number of B-frames (%u)",
413 self->interval_intraframes, self->b_frames);
416 param.nPFrames -= self->b_frames;
422 if (self->b_frames != GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT)
423 param.nBFrames = self->b_frames;
425 if (self->interval_intraframes !=
426 GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT)
427 param.nKeyFrameInterval = self->interval_intraframes;
431 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
432 (OMX_INDEXTYPE) INDEX_PARAM_VIDEO_HEVC, ¶m);
434 if (err == OMX_ErrorUnsupportedIndex) {
435 GST_WARNING_OBJECT (self,
436 "Setting IndexParamVideoHevc not supported by component");
438 } else if (err != OMX_ErrorNone) {
439 GST_ERROR_OBJECT (self,
440 "Error setting HEVC settings (profile %u and level %u): %s (0x%08x)",
441 (guint) param.eProfile, (guint) param.eLevel,
442 gst_omx_error_to_string (err), err);
449 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
451 set_intra_period (GstOMXH265Enc * self)
453 OMX_ALG_VIDEO_PARAM_INSTANTANEOUS_DECODING_REFRESH config_idr;
456 GST_OMX_INIT_STRUCT (&config_idr);
457 config_idr.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
459 GST_DEBUG_OBJECT (self, "nIDRPeriod:%u",
460 (guint) config_idr.nInstantaneousDecodingRefreshFrequency);
462 config_idr.nInstantaneousDecodingRefreshFrequency = self->periodicity_idr;
465 gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
466 (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh,
468 if (err != OMX_ErrorNone) {
469 GST_ERROR_OBJECT (self,
470 "can't set OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
471 gst_omx_error_to_string (err), err);
480 gst_omx_h265_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
481 GstVideoCodecState * state)
483 GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
485 OMX_PARAM_PORTDEFINITIONTYPE port_def;
487 const gchar *profile_string, *level_string, *tier_string;
488 OMX_VIDEO_HEVCPROFILETYPE profile = OMX_VIDEO_HEVCProfileUnknown;
489 OMX_VIDEO_HEVCLEVELTYPE level = OMX_VIDEO_HEVCLevelUnknown;
490 gboolean enable_subframe = FALSE;
492 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
493 if (self->periodicity_idr !=
494 GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT)
495 set_intra_period (self);
498 gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
500 port_def.format.video.eCompressionFormat =
501 (OMX_VIDEO_CODINGTYPE) OMX_VIDEO_CodingHEVC;
503 gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
504 (self)->enc_out_port, &port_def);
505 if (err != OMX_ErrorNone)
508 /* Set profile and level */
509 peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
510 gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
513 const gchar *alignment_string;
515 if (gst_caps_is_empty (peercaps)) {
516 gst_caps_unref (peercaps);
517 GST_ERROR_OBJECT (self, "Empty caps");
521 s = gst_caps_get_structure (peercaps, 0);
522 profile_string = gst_structure_get_string (s, "profile");
523 if (profile_string) {
524 profile = gst_omx_h265_utils_get_profile_from_str (profile_string);
525 if (profile == OMX_VIDEO_HEVCProfileUnknown)
526 goto unsupported_profile;
529 level_string = gst_structure_get_string (s, "level");
530 tier_string = gst_structure_get_string (s, "tier");
531 if (level_string && tier_string) {
532 level = gst_omx_h265_utils_get_level_from_str (level_string, tier_string);
533 if (level == OMX_VIDEO_HEVCLevelUnknown)
534 goto unsupported_level;
537 alignment_string = gst_structure_get_string (s, "alignment");
538 if (alignment_string && g_str_equal (alignment_string, "nal"))
539 enable_subframe = TRUE;
541 gst_caps_unref (peercaps);
544 if (profile != OMX_VIDEO_HEVCProfileUnknown
545 || level != OMX_VIDEO_HEVCLevelUnknown) {
546 /* OMX provides 2 API to set the profile and level. We try using the
547 * generic one here and the H265 specific when calling
548 * update_param_hevc() */
549 if (!update_param_profile_level (self, profile, level))
553 if (!update_param_hevc (self, profile, level))
556 gst_omx_port_set_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port,
562 GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
563 gst_caps_unref (peercaps);
567 GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
568 gst_caps_unref (peercaps);
573 gst_omx_h265_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
574 GstVideoCodecState * state)
576 GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
579 OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
580 const gchar *profile, *level, *tier, *alignment;
582 GST_OMX_INIT_STRUCT (¶m);
583 param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
586 gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
587 OMX_IndexParamVideoProfileLevelCurrent, ¶m);
588 if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex)
591 if (gst_omx_port_get_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port))
596 caps = gst_caps_new_simple ("video/x-h265",
597 "stream-format", G_TYPE_STRING, "byte-stream",
598 "alignment", G_TYPE_STRING, alignment, NULL);
600 if (err == OMX_ErrorNone) {
601 profile = gst_omx_h265_utils_get_profile_from_enum (param.eProfile);
603 g_assert_not_reached ();
604 gst_caps_unref (caps);
608 switch (param.eLevel) {
609 case OMX_VIDEO_HEVCMainTierLevel1:
613 case OMX_VIDEO_HEVCMainTierLevel2:
617 case OMX_VIDEO_HEVCMainTierLevel21:
621 case OMX_VIDEO_HEVCMainTierLevel3:
625 case OMX_VIDEO_HEVCMainTierLevel31:
629 case OMX_VIDEO_HEVCMainTierLevel4:
633 case OMX_VIDEO_HEVCMainTierLevel41:
637 case OMX_VIDEO_HEVCMainTierLevel5:
641 case OMX_VIDEO_HEVCMainTierLevel51:
645 case OMX_VIDEO_HEVCMainTierLevel52:
649 case OMX_VIDEO_HEVCMainTierLevel6:
653 case OMX_VIDEO_HEVCMainTierLevel61:
657 case OMX_VIDEO_HEVCMainTierLevel62:
661 case OMX_VIDEO_HEVCHighTierLevel4:
665 case OMX_VIDEO_HEVCHighTierLevel41:
669 case OMX_VIDEO_HEVCHighTierLevel5:
673 case OMX_VIDEO_HEVCHighTierLevel51:
677 case OMX_VIDEO_HEVCHighTierLevel52:
681 case OMX_VIDEO_HEVCHighTierLevel6:
685 case OMX_VIDEO_HEVCHighTierLevel61:
689 case OMX_VIDEO_HEVCHighTierLevel62:
694 g_assert_not_reached ();
695 gst_caps_unref (caps);
699 gst_caps_set_simple (caps,
700 "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level,
701 "tier", G_TYPE_STRING, tier, NULL);
708 gst_omx_h265_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port,
709 GstOMXBuffer * buf, GstVideoCodecFrame * frame)
711 GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
713 if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
714 /* The codec data is SPS/PPS but our output is stream-format=byte-stream.
715 * For bytestream stream format the SPS/PPS is only in-stream and not
719 GstMapInfo map = GST_MAP_INFO_INIT;
720 GstFlowReturn flow_ret;
722 GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format");
724 hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
725 GST_BUFFER_FLAG_SET (hdrs, GST_BUFFER_FLAG_HEADER);
727 gst_buffer_map (hdrs, &map, GST_MAP_WRITE);
729 buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
730 buf->omx_buf->nFilledLen);
731 gst_buffer_unmap (hdrs, &map);
732 self->headers = g_list_append (self->headers, gst_buffer_ref (hdrs));
733 frame->output_buffer = hdrs;
735 gst_video_encoder_finish_subframe (GST_VIDEO_ENCODER (self), frame);
736 gst_video_codec_frame_unref (frame);
739 } else if (self->headers) {
740 gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers);
741 self->headers = NULL;
745 GST_OMX_VIDEO_ENC_CLASS
746 (gst_omx_h265_enc_parent_class)->handle_output_frame (enc, port, buf,