2 * GStreamer Intel MSDK plugin
3 * Copyright (c) 2022 Intel Corporation. All rights reserved.
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-msdkav1enc
35 * @short_description: Intel MSDK AV1 encoder
37 * AV1 video encoder based on Intel MFX
39 * ## Example launch line
41 * gst-launch-1.0 videotestsrc num-buffers=90 ! msdkav1enc ! av1parse ! matroskamux ! filesink location=output.webm
52 #include <gst/allocators/gstdmabuf.h>
54 #include "gstmsdkav1enc.h"
56 GST_DEBUG_CATEGORY_EXTERN (gst_msdkav1enc_debug);
57 #define GST_CAT_DEFAULT gst_msdkav1enc_debug
61 PROP_TILE_ROW = GST_MSDKENC_PROP_MAX,
67 #define PROP_TILE_ROW_DEFAULT 1
68 #define PROP_TILE_COL_DEFAULT 1
69 #define PROP_B_PYRAMID_DEFAULT MFX_B_REF_UNKNOWN
70 #define PROP_P_PYRAMID_DEFAULT MFX_P_REF_DEFAULT
72 #define RAW_FORMATS "NV12, P010_10LE"
73 #define PROFILES "main"
75 #define COMMON_FORMAT "{ " RAW_FORMATS " }"
76 #define SRC_PROFILES "{ " PROFILES " }"
78 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
81 GST_STATIC_CAPS (GST_MSDK_CAPS_STR (COMMON_FORMAT,
84 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
87 GST_STATIC_CAPS ("video/x-av1, "
88 "framerate = (fraction) [0/1, MAX], "
89 "width = (int) [ 1, MAX ], height = (int) [ 1, MAX ], "
90 "profile = (string) " SRC_PROFILES)
93 #define gst_msdkav1enc_parent_class parent_class
94 G_DEFINE_TYPE (GstMsdkAV1Enc, gst_msdkav1enc, GST_TYPE_MSDKENC);
97 gst_msdkav1enc_set_format (GstMsdkEnc * encoder)
99 GstMsdkAV1Enc *thiz = GST_MSDKAV1ENC (encoder);
100 GstCaps *template_caps;
101 GstCaps *allowed_caps = NULL;
103 thiz->profile = MFX_PROFILE_AV1_MAIN;
105 allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
107 if (!allowed_caps || gst_caps_is_empty (allowed_caps)) {
109 gst_caps_unref (allowed_caps);
113 template_caps = gst_static_pad_template_get_caps (&src_factory);
115 /* If downstream has ANY caps let encoder decide profile and level */
116 if (gst_caps_is_equal (allowed_caps, template_caps)) {
117 GST_INFO_OBJECT (thiz,
118 "downstream has ANY caps, profile/level set to auto");
121 const gchar *profile;
123 allowed_caps = gst_caps_make_writable (allowed_caps);
124 allowed_caps = gst_caps_fixate (allowed_caps);
125 s = gst_caps_get_structure (allowed_caps, 0);
126 profile = gst_structure_get_string (s, "profile");
129 if (!strcmp (profile, "main"))
130 thiz->profile = MFX_PROFILE_AV1_MAIN;
132 g_assert_not_reached ();
136 gst_caps_unref (allowed_caps);
137 gst_caps_unref (template_caps);
143 gst_msdkav1enc_configure (GstMsdkEnc * encoder)
145 GstMsdkAV1Enc *av1enc = GST_MSDKAV1ENC (encoder);
147 encoder->num_extra_frames = encoder->async_depth - 1;
148 encoder->param.mfx.CodecId = MFX_CODEC_AV1;
149 encoder->param.mfx.CodecLevel = 0;
151 switch (encoder->param.mfx.FrameInfo.FourCC) {
152 case MFX_FOURCC_NV12:
153 case MFX_FOURCC_P010:
154 encoder->param.mfx.CodecProfile = MFX_PROFILE_AV1_MAIN;
158 g_assert_not_reached ();
162 /* Always turn on this flag for AV1 */
163 /* encoder->param.mfx.LowPower = MFX_CODINGOPTION_ON; */
165 /* Enable Extended coding options */
166 if (av1enc->b_pyramid)
167 encoder->option2.BRefType = MFX_B_REF_PYRAMID;
169 if (av1enc->p_pyramid) {
170 encoder->option3.PRefType = MFX_P_REF_PYRAMID;
171 /* MFX_P_REF_PYRAMID is available for GopRefDist = 1 */
172 encoder->param.mfx.GopRefDist = 1;
173 /* SDK decides the DPB size for P pyramid */
174 encoder->param.mfx.NumRefFrame = 0;
177 encoder->option3.GPB = MFX_CODINGOPTION_OFF;
178 encoder->enable_extopt3 = TRUE;
180 gst_msdkenc_ensure_extended_coding_options (encoder);
182 memset (&av1enc->ext_av1_bs_param, 0, sizeof (av1enc->ext_av1_bs_param));
183 av1enc->ext_av1_bs_param.Header.BufferId = MFX_EXTBUFF_AV1_BITSTREAM_PARAM;
184 av1enc->ext_av1_bs_param.Header.BufferSz = sizeof (av1enc->ext_av1_bs_param);
185 av1enc->ext_av1_bs_param.WriteIVFHeaders = MFX_CODINGOPTION_OFF;
186 gst_msdkenc_add_extra_param (encoder,
187 (mfxExtBuffer *) & av1enc->ext_av1_bs_param);
189 memset (&av1enc->ext_av1_res_param, 0, sizeof (av1enc->ext_av1_res_param));
190 av1enc->ext_av1_res_param.Header.BufferId = MFX_EXTBUFF_AV1_RESOLUTION_PARAM;
191 av1enc->ext_av1_res_param.Header.BufferSz =
192 sizeof (av1enc->ext_av1_res_param);
193 av1enc->ext_av1_res_param.FrameWidth = encoder->param.mfx.FrameInfo.CropW;
194 av1enc->ext_av1_res_param.FrameHeight = encoder->param.mfx.FrameInfo.CropH;
195 gst_msdkenc_add_extra_param (encoder,
196 (mfxExtBuffer *) & av1enc->ext_av1_res_param);
198 memset (&av1enc->ext_av1_tile_param, 0, sizeof (av1enc->ext_av1_tile_param));
199 av1enc->ext_av1_tile_param.Header.BufferId = MFX_EXTBUFF_AV1_TILE_PARAM;
200 av1enc->ext_av1_tile_param.Header.BufferSz =
201 sizeof (av1enc->ext_av1_tile_param);
202 av1enc->ext_av1_tile_param.NumTileRows = av1enc->num_tile_rows;
203 av1enc->ext_av1_tile_param.NumTileColumns = av1enc->num_tile_cols;
204 gst_msdkenc_add_extra_param (encoder,
205 (mfxExtBuffer *) & av1enc->ext_av1_tile_param);
210 static inline const gchar *
211 profile_to_string (gint profile)
214 case MFX_PROFILE_AV1_MAIN:
224 gst_msdkav1enc_set_src_caps (GstMsdkEnc * encoder)
227 GstStructure *structure;
228 const gchar *profile;
230 caps = gst_caps_new_empty_simple ("video/x-av1");
231 structure = gst_caps_get_structure (caps, 0);
233 profile = profile_to_string (encoder->param.mfx.CodecProfile);
235 gst_structure_set (structure, "profile", G_TYPE_STRING, profile, NULL);
241 gst_msdkav1enc_set_property (GObject * object, guint prop_id,
242 const GValue * value, GParamSpec * pspec)
244 GstMsdkAV1Enc *thiz = GST_MSDKAV1ENC (object);
246 if (gst_msdkenc_set_common_property (object, prop_id, value, pspec))
249 GST_OBJECT_LOCK (thiz);
253 thiz->num_tile_rows = g_value_get_uint (value);
257 thiz->num_tile_cols = g_value_get_uint (value);
261 thiz->b_pyramid = g_value_get_boolean (value);
265 thiz->p_pyramid = g_value_get_boolean (value);
269 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
272 GST_OBJECT_UNLOCK (thiz);
276 gst_msdkav1enc_get_property (GObject * object, guint prop_id, GValue * value,
279 GstMsdkAV1Enc *thiz = GST_MSDKAV1ENC (object);
281 if (gst_msdkenc_get_common_property (object, prop_id, value, pspec))
284 GST_OBJECT_LOCK (thiz);
288 g_value_set_uint (value, thiz->num_tile_rows);
292 g_value_set_uint (value, thiz->num_tile_cols);
296 g_value_set_boolean (value, thiz->b_pyramid);
300 g_value_set_boolean (value, thiz->p_pyramid);
304 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
307 GST_OBJECT_UNLOCK (thiz);
311 gst_msdkav1enc_finalize (GObject * object)
313 G_OBJECT_CLASS (parent_class)->finalize (object);
317 gst_msdkav1enc_class_init (GstMsdkAV1EncClass * klass)
319 GObjectClass *gobject_class;
320 GstElementClass *element_class;
321 GstMsdkEncClass *encoder_class;
323 gobject_class = G_OBJECT_CLASS (klass);
324 element_class = GST_ELEMENT_CLASS (klass);
325 encoder_class = GST_MSDKENC_CLASS (klass);
327 gobject_class->finalize = gst_msdkav1enc_finalize;
328 gobject_class->set_property = gst_msdkav1enc_set_property;
329 gobject_class->get_property = gst_msdkav1enc_get_property;
331 encoder_class->set_format = gst_msdkav1enc_set_format;
332 encoder_class->configure = gst_msdkav1enc_configure;
333 encoder_class->set_src_caps = gst_msdkav1enc_set_src_caps;
334 encoder_class->qp_max = 255;
335 encoder_class->qp_min = 0;
337 gst_msdkenc_install_common_properties (encoder_class);
339 g_object_class_install_property (gobject_class, PROP_TILE_ROW,
340 g_param_spec_uint ("num-tile-rows",
341 "number of rows for tiled encoding",
342 "number of rows for tiled encoding", 1, 64,
343 PROP_TILE_ROW_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
345 g_object_class_install_property (gobject_class, PROP_TILE_COL,
346 g_param_spec_uint ("num-tile-cols",
347 "number of columns for tiled encoding",
348 "number of columns for tiled encoding", 1, 64,
349 PROP_TILE_COL_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
351 g_object_class_install_property (gobject_class, PROP_B_PYRAMID,
352 g_param_spec_boolean ("b-pyramid", "B-pyramid",
353 "Enable B-Pyramid Reference structure", PROP_B_PYRAMID_DEFAULT,
354 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
356 g_object_class_install_property (gobject_class, PROP_P_PYRAMID,
357 g_param_spec_boolean ("p-pyramid", "P-pyramid",
358 "Enable P-Pyramid Reference structure", PROP_P_PYRAMID_DEFAULT,
359 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
361 gst_element_class_set_static_metadata (element_class,
362 "Intel MSDK AV1 encoder",
363 "Codec/Encoder/Video/Hardware",
364 "AV1 video encoder based on Intel Media SDK",
365 "Haihao Xiang <haihao.xiang@intel.com>, "
366 "Mengkejiergeli Ba <mengkejiergeli.ba@intel.com>");
368 gst_element_class_add_static_pad_template (element_class, &sink_factory);
369 gst_element_class_add_static_pad_template (element_class, &src_factory);
373 gst_msdkav1enc_init (GstMsdkAV1Enc * thiz)
375 thiz->num_tile_rows = PROP_TILE_ROW_DEFAULT;
376 thiz->num_tile_cols = PROP_TILE_COL_DEFAULT;
377 thiz->b_pyramid = PROP_B_PYRAMID_DEFAULT;
378 thiz->p_pyramid = PROP_P_PYRAMID_DEFAULT;