1 /* GStreamer Intel MSDK plugin
2 * Copyright (c) 2016, Oblong Industries, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * SECTION:element-msdkh265enc
35 * @short_description: Intel MSDK H265 encoder
37 * H265 video encoder based on Intel MFX
39 * ## Example launch line
41 * gst-launch-1.0 videotestsrc num-buffers=90 ! msdkh265enc ! h265parse ! filesink location=output.h265
52 #include <gst/allocators/gstdmabuf.h>
54 #include "gstmsdkh265enc.h"
56 GST_DEBUG_CATEGORY_EXTERN (gst_msdkh265enc_debug);
57 #define GST_CAT_DEFAULT gst_msdkh265enc_debug
61 #ifndef GST_REMOVE_DEPRECATED
62 PROP_LOW_POWER = GST_MSDKENC_PROP_MAX,
65 PROP_TILE_ROW = GST_MSDKENC_PROP_MAX,
75 PROP_INTRA_REFRESH_TYPE,
76 PROP_INTRA_REFRESH_CYCLE_SIZE,
77 PROP_INTRA_REFRESH_QP_DELTA,
78 PROP_INTRA_REFRESH_CYCLE_DIST,
84 GST_MSDK_FLAG_LOW_POWER = 1 << 0,
85 GST_MSDK_FLAG_TUNE_MODE = 1 << 1,
88 #define PROP_LOWPOWER_DEFAULT FALSE
89 #define PROP_TILE_ROW_DEFAULT 1
90 #define PROP_TILE_COL_DEFAULT 1
91 #define PROP_MAX_SLICE_SIZE_DEFAULT 0
92 #define PROP_TUNE_MODE_DEFAULT MFX_CODINGOPTION_UNKNOWN
93 #define PROP_TRANSFORM_SKIP_DEFAULT MFX_CODINGOPTION_UNKNOWN
94 #define PROP_B_PYRAMID_DEFAULT FALSE
95 #define PROP_P_PYRAMID_DEFAULT FALSE
96 #define PROP_MIN_QP_DEFAULT 0
97 #define PROP_MAX_QP_DEFAULT 0
98 #define PROP_INTRA_REFRESH_TYPE_DEFAULT MFX_REFRESH_NO
99 #define PROP_INTRA_REFRESH_CYCLE_SIZE_DEFAULT 0
100 #define PROP_INTRA_REFRESH_QP_DELTA_DEFAULT 0
101 #define PROP_INTRA_REFRESH_CYCLE_DIST_DEFAULT 0
102 #define PROP_DBLK_IDC_DEFAULT 0
104 #define RAW_FORMATS "NV12, I420, YV12, YUY2, UYVY, BGRA, BGR10A2_LE, P010_10LE, VUYA"
105 #define PROFILES "main, main-10, main-444, main-still-picture, main-10-still-picture"
106 #define COMMON_FORMAT "{ " RAW_FORMATS " }"
107 #define PRFOLIE_STR "{ " PROFILES " }"
110 #if (MFX_VERSION >= 1027)
113 #define FORMATS_1027 RAW_FORMATS ", Y410, Y210"
114 #define PROFILES_1027 PROFILES ", main-444-10, main-422-10"
115 #define COMMON_FORMAT "{ " FORMATS_1027 " }"
116 #define PRFOLIE_STR "{ " PROFILES_1027 " }"
119 #if (MFX_VERSION >= 1031)
122 #define FORMATS_1031 FORMATS_1027 ", P012_LE"
123 #define PROFILES_1031 PROFILES_1027 ", main-12"
124 #define COMMON_FORMAT "{ " FORMATS_1031 " }"
125 #define PRFOLIE_STR "{ " PROFILES_1031 " }"
128 #if (MFX_VERSION >= 1032)
131 #define FORMATS_1032 FORMATS_1031
132 #define PROFILES_1032 PROFILES_1031 ", screen-extended-main, " \
133 "screen-extended-main-10, screen-extended-main-444, " \
134 "screen-extended-main-444-10"
135 #define COMMON_FORMAT "{ " FORMATS_1032 " }"
136 #define PRFOLIE_STR "{ " PROFILES_1032 " }"
140 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
143 GST_STATIC_CAPS (GST_MSDK_CAPS_STR (COMMON_FORMAT,
144 "{ NV12, P010_10LE }") "; "
145 GST_MSDK_CAPS_MAKE_WITH_D3D11_FEATURE ("{ NV12, P010_10LE }")));
147 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
150 GST_STATIC_CAPS (GST_MSDK_CAPS_STR (COMMON_FORMAT,
151 "{ NV12, P010_10LE }") "; "
152 GST_MSDK_CAPS_MAKE_WITH_VA_FEATURE ("NV12")));
155 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
158 GST_STATIC_CAPS ("video/x-h265, "
159 "framerate = (fraction) [0/1, MAX], "
160 "width = (int) [ 1, MAX ], height = (int) [ 1, MAX ], "
161 "stream-format = (string) byte-stream , alignment = (string) au , "
162 "profile = (string) " PRFOLIE_STR)
165 #define gst_msdkh265enc_parent_class parent_class
166 G_DEFINE_TYPE (GstMsdkH265Enc, gst_msdkh265enc, GST_TYPE_MSDKENC);
169 gst_msdkh265enc_insert_sei (GstMsdkH265Enc * thiz, GstVideoCodecFrame * frame,
172 GstBuffer *new_buffer;
175 thiz->parser = gst_h265_parser_new ();
177 new_buffer = gst_h265_parser_insert_sei (thiz->parser,
178 frame->output_buffer, sei_mem);
181 GST_WARNING_OBJECT (thiz, "Cannot insert SEI nal into AU buffer");
185 gst_buffer_unref (frame->output_buffer);
186 frame->output_buffer = new_buffer;
190 gst_msdkh265enc_add_cc (GstMsdkH265Enc * thiz, GstVideoCodecFrame * frame)
192 GstVideoCaptionMeta *cc_meta;
193 gpointer iter = NULL;
194 GstBuffer *in_buf = frame->input_buffer;
195 GstMemory *mem = NULL;
197 if (thiz->cc_sei_array)
198 g_array_set_size (thiz->cc_sei_array, 0);
201 (GstVideoCaptionMeta *) gst_buffer_iterate_meta_filtered (in_buf,
202 &iter, GST_VIDEO_CAPTION_META_API_TYPE))) {
203 GstH265SEIMessage sei;
204 GstH265RegisteredUserData *rud;
207 if (cc_meta->caption_type != GST_VIDEO_CAPTION_TYPE_CEA708_RAW)
210 memset (&sei, 0, sizeof (GstH265SEIMessage));
211 sei.payloadType = GST_H265_SEI_REGISTERED_USER_DATA;
212 rud = &sei.payload.registered_user_data;
214 rud->country_code = 181;
215 rud->size = cc_meta->size + 10;
217 data = g_malloc (rud->size);
218 memcpy (data + 9, cc_meta->data, cc_meta->size);
220 data[0] = 0; /* 16-bits itu_t_t35_provider_code */
222 data[2] = 'G'; /* 32-bits ATSC_user_identifier */
226 data[6] = 3; /* 8-bits ATSC1_data_user_data_type_code */
228 * 1 bit process_em_data_flag (0)
229 * 1 bit process_cc_data_flag (1)
230 * 1 bit additional_data_flag (0)
233 data[7] = ((cc_meta->size / 3) & 0x1f) | 0x40;
234 data[8] = 255; /* 8 bits em_data, unused */
235 data[cc_meta->size + 9] = 255; /* 8 marker bits */
239 if (!thiz->cc_sei_array) {
241 g_array_new (FALSE, FALSE, sizeof (GstH265SEIMessage));
242 g_array_set_clear_func (thiz->cc_sei_array,
243 (GDestroyNotify) gst_h265_sei_free);
246 g_array_append_val (thiz->cc_sei_array, sei);
249 if (!thiz->cc_sei_array || !thiz->cc_sei_array->len)
252 /* layer_id and temporal_id will be updated by parser later */
253 mem = gst_h265_create_sei_memory (0, 1, 4, thiz->cc_sei_array);
256 GST_WARNING_OBJECT (thiz, "Cannot create SEI nal unit");
260 GST_DEBUG_OBJECT (thiz,
261 "Inserting %d closed caption SEI message(s)", thiz->cc_sei_array->len);
263 gst_msdkh265enc_insert_sei (thiz, frame, mem);
264 gst_memory_unref (mem);
268 gst_msdkh265enc_add_mdcv_sei (GstMsdkEnc * encoder, GstVideoCodecFrame * frame)
270 GstMsdkH265Enc *thiz = GST_MSDKH265ENC (encoder);
271 GstVideoMasteringDisplayInfo *mastering_display_info
272 = encoder->input_state->mastering_display_info;
273 GstH265SEIMessage sei;
274 GstH265MasteringDisplayColourVolume *mdcv;
275 GstMemory *mem = NULL;
278 memset (&sei, 0, sizeof (GstH265SEIMessage));
279 sei.payloadType = GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME;
280 mdcv = &sei.payload.mastering_display_colour_volume;
282 for (i = 0; i < 3; i++) {
283 mdcv->display_primaries_x[i] =
284 mastering_display_info->display_primaries[i].x;
285 mdcv->display_primaries_y[i] =
286 mastering_display_info->display_primaries[i].y;
289 mdcv->white_point_x = mastering_display_info->white_point.x;
290 mdcv->white_point_y = mastering_display_info->white_point.y;
291 mdcv->max_display_mastering_luminance =
292 mastering_display_info->max_display_mastering_luminance;
293 mdcv->min_display_mastering_luminance =
294 mastering_display_info->min_display_mastering_luminance;
296 if (!thiz->cc_sei_array)
297 thiz->cc_sei_array = g_array_new (FALSE, FALSE, sizeof (GstH265SEIMessage));
299 g_array_set_size (thiz->cc_sei_array, 0);
301 g_array_append_val (thiz->cc_sei_array, sei);
303 if (!thiz->cc_sei_array || !thiz->cc_sei_array->len)
306 /* layer_id and temporal_id will be updated by parser later */
307 mem = gst_h265_create_sei_memory (0, 1, 4, thiz->cc_sei_array);
310 GST_WARNING_OBJECT (thiz, "Cannot create SEI nal unit");
314 GST_DEBUG_OBJECT (thiz,
315 "Inserting %d mastering display colout volume SEI message(s)",
316 thiz->cc_sei_array->len);
318 gst_msdkh265enc_insert_sei (thiz, frame, mem);
319 gst_memory_unref (mem);
323 gst_msdkh265enc_add_cll_sei (GstMsdkEnc * encoder, GstVideoCodecFrame * frame)
325 GstMsdkH265Enc *thiz = GST_MSDKH265ENC (encoder);
326 GstVideoContentLightLevel *content_light_level
327 = encoder->input_state->content_light_level;
328 GstH265ContentLightLevel *cll;
329 GstH265SEIMessage sei;
330 GstMemory *mem = NULL;
332 memset (&sei, 0, sizeof (GstH265SEIMessage));
333 sei.payloadType = GST_H265_SEI_CONTENT_LIGHT_LEVEL;
334 cll = &sei.payload.content_light_level;
336 cll->max_content_light_level = content_light_level->max_content_light_level;
337 cll->max_pic_average_light_level =
338 content_light_level->max_frame_average_light_level;
340 if (!thiz->cc_sei_array)
341 thiz->cc_sei_array = g_array_new (FALSE, FALSE, sizeof (GstH265SEIMessage));
343 g_array_set_size (thiz->cc_sei_array, 0);
345 g_array_append_val (thiz->cc_sei_array, sei);
347 if (!thiz->cc_sei_array || !thiz->cc_sei_array->len)
350 /* layer_id and temporal_id will be updated by parser later */
351 mem = gst_h265_create_sei_memory (0, 1, 4, thiz->cc_sei_array);
354 GST_WARNING_OBJECT (thiz, "Cannot create SEI nal unit");
358 GST_DEBUG_OBJECT (thiz,
359 "Inserting %d content light level SEI message(s)",
360 thiz->cc_sei_array->len);
362 gst_msdkh265enc_insert_sei (thiz, frame, mem);
363 gst_memory_unref (mem);
367 gst_msdkh265enc_pre_push (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
369 GstMsdkH265Enc *thiz = GST_MSDKH265ENC (encoder);
370 GstMsdkEnc *msdk_encoder = GST_MSDKENC (encoder);
372 gst_msdkh265enc_add_cc (thiz, frame);
374 if (msdk_encoder->input_state->mastering_display_info)
375 gst_msdkh265enc_add_mdcv_sei (msdk_encoder, frame);
377 if (msdk_encoder->input_state->content_light_level)
378 gst_msdkh265enc_add_cll_sei (msdk_encoder, frame);
384 gst_msdkh265enc_set_format (GstMsdkEnc * encoder)
386 GstMsdkH265Enc *thiz = GST_MSDKH265ENC (encoder);
387 GstCaps *template_caps, *allowed_caps;
389 g_free (thiz->profile_name);
390 thiz->profile_name = NULL;
392 allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
394 if (!allowed_caps || gst_caps_is_empty (allowed_caps)) {
396 gst_caps_unref (allowed_caps);
400 template_caps = gst_static_pad_template_get_caps (&src_factory);
402 if (gst_caps_is_equal (allowed_caps, template_caps)) {
403 GST_INFO_OBJECT (thiz,
404 "downstream have the same caps, profile set to auto");
407 const gchar *profile;
409 allowed_caps = gst_caps_make_writable (allowed_caps);
410 allowed_caps = gst_caps_fixate (allowed_caps);
411 s = gst_caps_get_structure (allowed_caps, 0);
412 profile = gst_structure_get_string (s, "profile");
415 thiz->profile_name = g_strdup (profile);
419 gst_caps_unref (allowed_caps);
420 gst_caps_unref (template_caps);
426 gst_msdkh265enc_configure (GstMsdkEnc * encoder)
428 GstMsdkH265Enc *h265enc = GST_MSDKH265ENC (encoder);
430 const mfxPluginUID *uid;
432 session = gst_msdk_context_get_session (encoder->context);
434 if (encoder->hardware)
435 uid = &MFX_PLUGINID_HEVCE_HW;
437 uid = &MFX_PLUGINID_HEVCE_SW;
439 if (!gst_msdk_load_plugin (session, uid, 1, "msdkh265enc"))
442 encoder->param.mfx.CodecId = MFX_CODEC_HEVC;
444 if (h265enc->profile_name) {
445 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_MAIN;
447 if (!strcmp (h265enc->profile_name, "main-10"))
448 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_MAIN10;
449 else if (!strcmp (h265enc->profile_name, "main-still-picture"))
450 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_MAINSP;
451 else if (!strcmp (h265enc->profile_name, "main-10-still-picture")) {
452 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_MAIN10;
453 h265enc->ext_param.Header.BufferId = MFX_EXTBUFF_HEVC_PARAM;
454 h265enc->ext_param.Header.BufferSz = sizeof (h265enc->ext_param);
455 h265enc->ext_param.GeneralConstraintFlags =
456 MFX_HEVC_CONSTR_REXT_ONE_PICTURE_ONLY;
457 gst_msdkenc_add_extra_param (encoder,
458 (mfxExtBuffer *) & h265enc->ext_param);
459 } else if (!strcmp (h265enc->profile_name, "main-444") ||
460 !strcmp (h265enc->profile_name, "main-422-10") ||
461 !strcmp (h265enc->profile_name, "main-444-10") ||
462 !strcmp (h265enc->profile_name, "main-12"))
463 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_REXT;
465 #if (MFX_VERSION >= 1032)
466 else if (!strcmp (h265enc->profile_name, "screen-extended-main") ||
467 !strcmp (h265enc->profile_name, "screen-extended-main-10") ||
468 !strcmp (h265enc->profile_name, "screen-extended-main-444") ||
469 !strcmp (h265enc->profile_name, "screen-extended-main-444-10"))
470 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_SCC;
473 switch (encoder->param.mfx.FrameInfo.FourCC) {
474 case MFX_FOURCC_P010:
475 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_MAIN10;
477 case MFX_FOURCC_AYUV:
478 case MFX_FOURCC_YUY2:
479 case MFX_FOURCC_A2RGB10:
480 #if (MFX_VERSION >= 1027)
481 case MFX_FOURCC_Y410:
482 case MFX_FOURCC_Y210:
484 #if (MFX_VERSION >= 1031)
485 case MFX_FOURCC_P016:
487 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_REXT;
490 encoder->param.mfx.CodecProfile = MFX_PROFILE_HEVC_MAIN;
494 /* IdrInterval field of MediaSDK HEVC encoder behaves differently
495 * than other encoders. IdrInteval == 1 indicate every
496 * I-frame should be an IDR, IdrInteval == 2 means every other
497 * I-frame is an IDR etc. So we generalize the behaviour of property
498 * "i-frames" by incrementing the value by one in each case*/
499 encoder->param.mfx.IdrInterval += 1;
501 /* Enable Extended coding options */
502 encoder->option2.MaxSliceSize = h265enc->max_slice_size;
503 encoder->option2.MinQPI = encoder->option2.MinQPP = encoder->option2.MinQPB =
505 encoder->option2.MaxQPI = encoder->option2.MaxQPP = encoder->option2.MaxQPB =
507 encoder->option2.DisableDeblockingIdc = h265enc->dblk_idc;
509 if (h265enc->tune_mode == 16 || h265enc->lowpower) {
510 encoder->option2.IntRefType = h265enc->intra_refresh_type;
511 encoder->option2.IntRefCycleSize = h265enc->intra_refresh_cycle_size;
512 encoder->option2.IntRefQPDelta = h265enc->intra_refresh_qp_delta;
513 encoder->option3.IntRefCycleDist = h265enc->intra_refresh_cycle_dist;
514 encoder->enable_extopt3 = TRUE;
515 } else if (h265enc->intra_refresh_type || h265enc->intra_refresh_cycle_size
516 || h265enc->intra_refresh_qp_delta || h265enc->intra_refresh_cycle_dist) {
517 GST_WARNING_OBJECT (h265enc,
518 "Intra refresh is only supported under lowpower mode, ingoring...");
520 #if (MFX_VERSION >= 1026)
521 if (h265enc->transform_skip != MFX_CODINGOPTION_UNKNOWN) {
522 encoder->option3.TransformSkip = h265enc->transform_skip;
523 encoder->enable_extopt3 = TRUE;
527 if (h265enc->b_pyramid) {
528 encoder->option2.BRefType = MFX_B_REF_PYRAMID;
529 /* Don't define Gop structure for B-pyramid, otherwise EncodeInit
530 * will throw Invalid param error */
531 encoder->param.mfx.GopRefDist = 0;
534 if (h265enc->p_pyramid) {
535 encoder->option3.PRefType = MFX_P_REF_PYRAMID;
536 /* MFX_P_REF_PYRAMID is available for GopRefDist = 1 */
537 encoder->param.mfx.GopRefDist = 1;
538 /* SDK decides the DPB size for P pyramid */
539 encoder->param.mfx.NumRefFrame = 0;
540 encoder->enable_extopt3 = TRUE;
543 if (encoder->option3.LowDelayBRC == MFX_CODINGOPTION_ON) {
544 h265enc->option.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
545 h265enc->option.Header.BufferSz = sizeof (h265enc->option);
546 h265enc->option.NalHrdConformance = MFX_CODINGOPTION_OFF;
547 gst_msdkenc_add_extra_param (encoder, (mfxExtBuffer *) & h265enc->option);
550 gst_msdkenc_ensure_extended_coding_options (encoder);
552 if (h265enc->num_tile_rows > 1 || h265enc->num_tile_cols > 1) {
553 h265enc->ext_tiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
554 h265enc->ext_tiles.Header.BufferSz = sizeof (h265enc->ext_tiles);
555 h265enc->ext_tiles.NumTileRows = h265enc->num_tile_rows;
556 h265enc->ext_tiles.NumTileColumns = h265enc->num_tile_cols;
558 gst_msdkenc_add_extra_param (encoder,
559 (mfxExtBuffer *) & h265enc->ext_tiles);
561 /* Set a valid value to NumSlice */
562 if (encoder->param.mfx.NumSlice == 0)
563 encoder->param.mfx.NumSlice =
564 h265enc->num_tile_rows * h265enc->num_tile_cols;
567 encoder->param.mfx.LowPower = h265enc->tune_mode;
572 static inline const gchar *
573 level_to_string (gint level)
576 case MFX_LEVEL_HEVC_1:
578 case MFX_LEVEL_HEVC_2:
580 case MFX_LEVEL_HEVC_21:
582 case MFX_LEVEL_HEVC_3:
584 case MFX_LEVEL_HEVC_31:
586 case MFX_LEVEL_HEVC_4:
588 case MFX_LEVEL_HEVC_41:
590 case MFX_LEVEL_HEVC_5:
592 case MFX_LEVEL_HEVC_51:
594 case MFX_LEVEL_HEVC_52:
596 case MFX_LEVEL_HEVC_6:
598 case MFX_LEVEL_HEVC_61:
600 case MFX_LEVEL_HEVC_62:
610 gst_msdkh265enc_set_src_caps (GstMsdkEnc * encoder)
612 GstMsdkH265Enc *thiz = GST_MSDKH265ENC (encoder);
614 GstStructure *structure;
617 caps = gst_caps_new_empty_simple ("video/x-h265");
618 structure = gst_caps_get_structure (caps, 0);
620 gst_structure_set (structure, "stream-format", G_TYPE_STRING, "byte-stream",
623 gst_structure_set (structure, "alignment", G_TYPE_STRING, "au", NULL);
625 if (thiz->profile_name)
626 gst_structure_set (structure, "profile", G_TYPE_STRING, thiz->profile_name,
629 switch (encoder->param.mfx.FrameInfo.FourCC) {
630 case MFX_FOURCC_P010:
631 gst_structure_set (structure, "profile", G_TYPE_STRING, "main-10",
634 case MFX_FOURCC_AYUV:
635 gst_structure_set (structure, "profile", G_TYPE_STRING, "main-444",
638 case MFX_FOURCC_YUY2:
639 /* The profile is main-422-10 for 8-bit 422 */
640 gst_structure_set (structure, "profile", G_TYPE_STRING, "main-422-10",
643 case MFX_FOURCC_A2RGB10:
644 gst_structure_set (structure, "profile", G_TYPE_STRING, "main-444-10",
647 #if (MFX_VERSION >= 1027)
648 case MFX_FOURCC_Y410:
649 gst_structure_set (structure, "profile", G_TYPE_STRING, "main-444-10",
652 case MFX_FOURCC_Y210:
653 gst_structure_set (structure, "profile", G_TYPE_STRING, "main-422-10",
657 #if (MFX_VERSION >= 1031)
658 case MFX_FOURCC_P016:
659 gst_structure_set (structure, "profile", G_TYPE_STRING, "main-12",
664 gst_structure_set (structure, "profile", G_TYPE_STRING, "main", NULL);
669 level = level_to_string (encoder->param.mfx.CodecLevel);
671 gst_structure_set (structure, "level", G_TYPE_STRING, level, NULL);
677 gst_msdkh265enc_finalize (GObject * object)
679 GstMsdkH265Enc *thiz = GST_MSDKH265ENC (object);
682 gst_h265_parser_free (thiz->parser);
683 if (thiz->cc_sei_array)
684 g_array_unref (thiz->cc_sei_array);
686 g_free (thiz->profile_name);
688 G_OBJECT_CLASS (parent_class)->finalize (object);
692 gst_msdkh265enc_set_property (GObject * object, guint prop_id,
693 const GValue * value, GParamSpec * pspec)
695 GstMsdkH265Enc *thiz = GST_MSDKH265ENC (object);
697 if (gst_msdkenc_set_common_property (object, prop_id, value, pspec))
700 GST_OBJECT_LOCK (thiz);
703 #ifndef GST_REMOVE_DEPRECATED
705 thiz->lowpower = g_value_get_boolean (value);
706 thiz->prop_flag |= GST_MSDK_FLAG_LOW_POWER;
708 /* Ignore it if user set tune mode explicitly */
709 if (!(thiz->prop_flag & GST_MSDK_FLAG_TUNE_MODE))
711 thiz->lowpower ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
717 thiz->num_tile_rows = g_value_get_uint (value);
721 thiz->num_tile_cols = g_value_get_uint (value);
724 case PROP_MAX_SLICE_SIZE:
725 thiz->max_slice_size = g_value_get_uint (value);
729 thiz->tune_mode = g_value_get_enum (value);
730 thiz->prop_flag |= GST_MSDK_FLAG_TUNE_MODE;
733 case PROP_TRANSFORM_SKIP:
734 thiz->transform_skip = g_value_get_enum (value);
738 thiz->b_pyramid = g_value_get_boolean (value);
742 thiz->p_pyramid = g_value_get_boolean (value);
746 thiz->min_qp = g_value_get_uint (value);
750 thiz->max_qp = g_value_get_uint (value);
753 case PROP_INTRA_REFRESH_TYPE:
754 thiz->intra_refresh_type = g_value_get_enum (value);
757 case PROP_INTRA_REFRESH_CYCLE_SIZE:
758 thiz->intra_refresh_cycle_size = g_value_get_uint (value);
761 case PROP_INTRA_REFRESH_QP_DELTA:
762 thiz->intra_refresh_qp_delta = g_value_get_int (value);
765 case PROP_INTRA_REFRESH_CYCLE_DIST:
766 thiz->intra_refresh_cycle_dist = g_value_get_uint (value);
770 thiz->dblk_idc = g_value_get_uint (value);
774 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
777 GST_OBJECT_UNLOCK (thiz);
781 gst_msdkh265enc_get_property (GObject * object, guint prop_id, GValue * value,
784 GstMsdkH265Enc *thiz = GST_MSDKH265ENC (object);
786 if (gst_msdkenc_get_common_property (object, prop_id, value, pspec))
789 GST_OBJECT_LOCK (thiz);
791 #ifndef GST_REMOVE_DEPRECATED
793 g_value_set_boolean (value, thiz->lowpower);
798 g_value_set_uint (value, thiz->num_tile_rows);
802 g_value_set_uint (value, thiz->num_tile_cols);
805 case PROP_MAX_SLICE_SIZE:
806 g_value_set_uint (value, thiz->max_slice_size);
810 g_value_set_enum (value, thiz->tune_mode);
813 case PROP_TRANSFORM_SKIP:
814 g_value_set_enum (value, thiz->transform_skip);
818 g_value_set_boolean (value, thiz->b_pyramid);
822 g_value_set_boolean (value, thiz->p_pyramid);
826 g_value_set_uint (value, thiz->min_qp);
830 g_value_set_uint (value, thiz->max_qp);
833 case PROP_INTRA_REFRESH_TYPE:
834 g_value_set_enum (value, thiz->intra_refresh_type);
837 case PROP_INTRA_REFRESH_CYCLE_SIZE:
838 g_value_set_uint (value, thiz->intra_refresh_cycle_size);
841 case PROP_INTRA_REFRESH_QP_DELTA:
842 g_value_set_int (value, thiz->intra_refresh_qp_delta);
845 case PROP_INTRA_REFRESH_CYCLE_DIST:
846 g_value_set_uint (value, thiz->intra_refresh_cycle_dist);
850 g_value_set_uint (value, thiz->dblk_idc);
854 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
857 GST_OBJECT_UNLOCK (thiz);
861 gst_msdkh265enc_need_reconfig (GstMsdkEnc * encoder, GstVideoCodecFrame * frame)
863 GstMsdkH265Enc *h265enc = GST_MSDKH265ENC (encoder);
865 return gst_msdkenc_get_roi_params (encoder, frame, h265enc->roi);
869 gst_msdkh265enc_set_extra_params (GstMsdkEnc * encoder,
870 GstVideoCodecFrame * frame)
872 GstMsdkH265Enc *h265enc = GST_MSDKH265ENC (encoder);
874 if (h265enc->roi[0].NumROI)
875 gst_msdkenc_add_extra_param (encoder, (mfxExtBuffer *) & h265enc->roi[0]);
879 gst_msdkh265enc_need_conversion (GstMsdkEnc * encoder, GstVideoInfo * info,
880 GstVideoFormat * out_format)
882 GstMsdkH265Enc *h265enc = GST_MSDKH265ENC (encoder);
884 switch (GST_VIDEO_INFO_FORMAT (info)) {
885 case GST_VIDEO_FORMAT_NV12:
886 case GST_VIDEO_FORMAT_BGR10A2_LE:
887 case GST_VIDEO_FORMAT_P010_10LE:
888 case GST_VIDEO_FORMAT_VUYA:
889 #if (MFX_VERSION >= 1027)
890 case GST_VIDEO_FORMAT_Y410:
891 case GST_VIDEO_FORMAT_Y210:
893 #if (MFX_VERSION >= 1031)
894 case GST_VIDEO_FORMAT_P012_LE:
898 case GST_VIDEO_FORMAT_YUY2:
899 #if (MFX_VERSION >= 1027)
900 if (encoder->codename >= MFX_PLATFORM_ICELAKE &&
901 h265enc->tune_mode == MFX_CODINGOPTION_OFF)
905 if (GST_VIDEO_INFO_COMP_DEPTH (info, 0) == 10)
906 *out_format = GST_VIDEO_FORMAT_P010_10LE;
908 *out_format = GST_VIDEO_FORMAT_NV12;
914 gst_msdkh265enc_class_init (GstMsdkH265EncClass * klass)
916 GObjectClass *gobject_class;
917 GstElementClass *element_class;
918 GstVideoEncoderClass *videoencoder_class;
919 GstMsdkEncClass *encoder_class;
921 gobject_class = G_OBJECT_CLASS (klass);
922 element_class = GST_ELEMENT_CLASS (klass);
923 videoencoder_class = GST_VIDEO_ENCODER_CLASS (klass);
924 encoder_class = GST_MSDKENC_CLASS (klass);
926 gobject_class->finalize = gst_msdkh265enc_finalize;
927 gobject_class->set_property = gst_msdkh265enc_set_property;
928 gobject_class->get_property = gst_msdkh265enc_get_property;
930 videoencoder_class->pre_push = gst_msdkh265enc_pre_push;
932 encoder_class->set_format = gst_msdkh265enc_set_format;
933 encoder_class->configure = gst_msdkh265enc_configure;
934 encoder_class->set_src_caps = gst_msdkh265enc_set_src_caps;
935 encoder_class->need_reconfig = gst_msdkh265enc_need_reconfig;
936 encoder_class->set_extra_params = gst_msdkh265enc_set_extra_params;
937 encoder_class->need_conversion = gst_msdkh265enc_need_conversion;
939 gst_msdkenc_install_common_properties (encoder_class);
941 #ifndef GST_REMOVE_DEPRECATED
942 g_object_class_install_property (gobject_class, PROP_LOW_POWER,
943 g_param_spec_boolean ("low-power", "Low power",
944 "Enable low power mode (DEPRECATED, use tune instead)",
945 PROP_LOWPOWER_DEFAULT,
946 G_PARAM_DEPRECATED | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
949 g_object_class_install_property (gobject_class, PROP_TILE_ROW,
950 g_param_spec_uint ("num-tile-rows", "number of rows for tiled encoding",
951 "number of rows for tiled encoding",
952 1, 8192, PROP_TILE_ROW_DEFAULT,
953 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
955 g_object_class_install_property (gobject_class, PROP_TILE_COL,
956 g_param_spec_uint ("num-tile-cols",
957 "number of columns for tiled encoding",
958 "number of columns for tiled encoding", 1, 8192,
959 PROP_TILE_COL_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
961 g_object_class_install_property (gobject_class, PROP_MAX_SLICE_SIZE,
962 g_param_spec_uint ("max-slice-size", "Max Slice Size",
963 "Maximum slice size in bytes (if enabled MSDK will ignore the control over num-slices)",
964 0, G_MAXUINT32, PROP_MAX_SLICE_SIZE_DEFAULT,
965 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
967 g_object_class_install_property (gobject_class, PROP_TUNE_MODE,
968 g_param_spec_enum ("tune", "Encoder tuning",
969 "Encoder tuning option",
970 gst_msdkenc_tune_mode_get_type (), PROP_TUNE_MODE_DEFAULT,
971 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
973 g_object_class_install_property (gobject_class, PROP_TRANSFORM_SKIP,
974 g_param_spec_enum ("transform-skip", "Transform Skip",
975 "Transform Skip option",
976 gst_msdkenc_transform_skip_get_type (), PROP_TRANSFORM_SKIP_DEFAULT,
977 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
979 g_object_class_install_property (gobject_class, PROP_B_PYRAMID,
980 g_param_spec_boolean ("b-pyramid", "B-pyramid",
981 "Enable B-Pyramid Reference structure", FALSE,
982 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
984 g_object_class_install_property (gobject_class, PROP_P_PYRAMID,
985 g_param_spec_boolean ("p-pyramid", "P-pyramid",
986 "Enable P-Pyramid Reference structure", FALSE,
987 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
989 g_object_class_install_property (gobject_class, PROP_MIN_QP,
990 g_param_spec_uint ("min-qp", "Min QP",
991 "Minimal quantizer for I/P/B frames",
992 0, 51, PROP_MIN_QP_DEFAULT,
993 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
995 g_object_class_install_property (gobject_class, PROP_MAX_QP,
996 g_param_spec_uint ("max-qp", "Max QP",
997 "Maximum quantizer for I/P/B frames",
998 0, 51, PROP_MAX_QP_DEFAULT,
999 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1001 g_object_class_install_property (gobject_class, PROP_INTRA_REFRESH_TYPE,
1002 g_param_spec_enum ("intra-refresh-type", "Intra refresh type",
1003 "Set intra refresh type",
1004 gst_msdkenc_intra_refresh_type_get_type (),
1005 PROP_INTRA_REFRESH_TYPE_DEFAULT,
1006 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1008 g_object_class_install_property (gobject_class, PROP_INTRA_REFRESH_CYCLE_SIZE,
1009 g_param_spec_uint ("intra-refresh-cycle-size", "Intra refresh cycle size",
1010 "Set intra refresh cycle size, valid value starts from 2, only available when tune=low-power",
1011 0, G_MAXUINT16, PROP_INTRA_REFRESH_CYCLE_SIZE_DEFAULT,
1012 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1014 g_object_class_install_property (gobject_class, PROP_INTRA_REFRESH_QP_DELTA,
1015 g_param_spec_int ("intra-refresh-qp-delta", "Intra refresh qp delta",
1016 "Set intra refresh qp delta, only available when tune=low-power",
1017 -51, 51, PROP_INTRA_REFRESH_QP_DELTA_DEFAULT,
1018 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1020 g_object_class_install_property (gobject_class, PROP_INTRA_REFRESH_CYCLE_DIST,
1021 g_param_spec_uint ("intra-refresh-cycle-dist", "Intra refresh cycle dist",
1022 "Set intra refresh cycle dist, only available when tune=low-power",
1023 0, G_MAXUINT16, PROP_INTRA_REFRESH_CYCLE_DIST_DEFAULT,
1024 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1026 g_object_class_install_property (gobject_class, PROP_DBLK_IDC,
1027 g_param_spec_uint ("dblk-idc", "Disable Deblocking Idc",
1028 "Option of disable deblocking idc",
1029 0, 2, PROP_DBLK_IDC_DEFAULT,
1030 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1032 gst_element_class_set_static_metadata (element_class,
1033 "Intel MSDK H265 encoder",
1034 "Codec/Encoder/Video/Hardware",
1035 "H265 video encoder based on " MFX_API_SDK,
1036 "Josep Torra <jtorra@oblong.com>");
1038 gst_element_class_add_static_pad_template (element_class, &sink_factory);
1039 gst_element_class_add_static_pad_template (element_class, &src_factory);
1043 gst_msdkh265enc_init (GstMsdkH265Enc * thiz)
1045 GstMsdkEnc *msdk_enc = (GstMsdkEnc *) thiz;
1046 thiz->lowpower = PROP_LOWPOWER_DEFAULT;
1047 thiz->num_tile_rows = PROP_TILE_ROW_DEFAULT;
1048 thiz->num_tile_cols = PROP_TILE_COL_DEFAULT;
1049 thiz->max_slice_size = PROP_MAX_SLICE_SIZE_DEFAULT;
1050 thiz->tune_mode = PROP_TUNE_MODE_DEFAULT;
1051 thiz->transform_skip = PROP_TRANSFORM_SKIP_DEFAULT;
1052 thiz->b_pyramid = PROP_B_PYRAMID_DEFAULT;
1053 thiz->p_pyramid = PROP_P_PYRAMID_DEFAULT;
1054 thiz->min_qp = PROP_MIN_QP_DEFAULT;
1055 thiz->max_qp = PROP_MAX_QP_DEFAULT;
1056 thiz->intra_refresh_type = PROP_INTRA_REFRESH_TYPE_DEFAULT;
1057 thiz->intra_refresh_cycle_size = PROP_INTRA_REFRESH_CYCLE_SIZE_DEFAULT;
1058 thiz->intra_refresh_qp_delta = PROP_INTRA_REFRESH_QP_DELTA_DEFAULT;
1059 thiz->intra_refresh_cycle_dist = PROP_INTRA_REFRESH_CYCLE_DIST_DEFAULT;
1060 thiz->dblk_idc = PROP_DBLK_IDC_DEFAULT;
1061 msdk_enc->num_extra_frames = 1;