taglist, plugins: fix compiler warnings with GLib >= 2.76
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / msdk / gstmsdkav1enc.c
1 /*
2  * GStreamer Intel MSDK plugin
3  * Copyright (c) 2022 Intel Corporation. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *
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.
14  *
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.
18  *
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.
30  */
31
32 /**
33  * SECTION: element-msdkav1enc
34  * @title: msdkav1enc
35  * @short_description: Intel MSDK AV1 encoder
36  *
37  * AV1 video encoder based on Intel MFX
38  *
39  * ## Example launch line
40  * ```
41  * gst-launch-1.0 videotestsrc num-buffers=90 ! msdkav1enc ! av1parse ! matroskamux ! filesink location=output.webm
42  * ```
43  *
44  * Since: 1.21
45  *
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #  include <config.h>
50 #endif
51
52 #include <gst/allocators/gstdmabuf.h>
53
54 #include "gstmsdkav1enc.h"
55
56 GST_DEBUG_CATEGORY_EXTERN (gst_msdkav1enc_debug);
57 #define GST_CAT_DEFAULT gst_msdkav1enc_debug
58
59 enum
60 {
61   PROP_TILE_ROW = GST_MSDKENC_PROP_MAX,
62   PROP_TILE_COL,
63   PROP_B_PYRAMID,
64   PROP_P_PYRAMID,
65 };
66
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
71
72 #define RAW_FORMATS "NV12, P010_10LE"
73 #define PROFILES    "main"
74
75 #define COMMON_FORMAT "{ " RAW_FORMATS " }"
76 #define SRC_PROFILES  "{ " PROFILES " }"
77
78 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
79     GST_PAD_SINK,
80     GST_PAD_ALWAYS,
81     GST_STATIC_CAPS (GST_MSDK_CAPS_STR (COMMON_FORMAT,
82             COMMON_FORMAT)));
83
84 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
85     GST_PAD_SRC,
86     GST_PAD_ALWAYS,
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)
91     );
92
93 #define gst_msdkav1enc_parent_class parent_class
94 G_DEFINE_TYPE (GstMsdkAV1Enc, gst_msdkav1enc, GST_TYPE_MSDKENC);
95
96 static gboolean
97 gst_msdkav1enc_set_format (GstMsdkEnc * encoder)
98 {
99   GstMsdkAV1Enc *thiz = GST_MSDKAV1ENC (encoder);
100   GstCaps *template_caps;
101   GstCaps *allowed_caps = NULL;
102
103   thiz->profile = MFX_PROFILE_AV1_MAIN;
104
105   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
106
107   if (!allowed_caps || gst_caps_is_empty (allowed_caps)) {
108     if (allowed_caps)
109       gst_caps_unref (allowed_caps);
110     return FALSE;
111   }
112
113   template_caps = gst_static_pad_template_get_caps (&src_factory);
114
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");
119   } else {
120     GstStructure *s;
121     const gchar *profile;
122
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");
127
128     if (profile) {
129       if (!strcmp (profile, "main"))
130         thiz->profile = MFX_PROFILE_AV1_MAIN;
131       else
132         g_assert_not_reached ();
133     }
134   }
135
136   gst_caps_unref (allowed_caps);
137   gst_caps_unref (template_caps);
138
139   return TRUE;
140 }
141
142 static gboolean
143 gst_msdkav1enc_configure (GstMsdkEnc * encoder)
144 {
145   GstMsdkAV1Enc *av1enc = GST_MSDKAV1ENC (encoder);
146
147   encoder->num_extra_frames = encoder->async_depth - 1;
148   encoder->param.mfx.CodecId = MFX_CODEC_AV1;
149   encoder->param.mfx.CodecLevel = 0;
150
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;
155       break;
156
157     default:
158       g_assert_not_reached ();
159       break;
160   }
161
162   /* Always turn on this flag for AV1 */
163   /* encoder->param.mfx.LowPower = MFX_CODINGOPTION_ON; */
164
165   /* Enable Extended coding options */
166   if (av1enc->b_pyramid)
167     encoder->option2.BRefType = MFX_B_REF_PYRAMID;
168
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;
175   }
176
177   encoder->option3.GPB = MFX_CODINGOPTION_OFF;
178   encoder->enable_extopt3 = TRUE;
179
180   gst_msdkenc_ensure_extended_coding_options (encoder);
181
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);
188
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);
197
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);
206
207   return TRUE;
208 }
209
210 static inline const gchar *
211 profile_to_string (gint profile)
212 {
213   switch (profile) {
214     case MFX_PROFILE_AV1_MAIN:
215       return "main";
216     default:
217       break;
218   }
219
220   return NULL;
221 }
222
223 static GstCaps *
224 gst_msdkav1enc_set_src_caps (GstMsdkEnc * encoder)
225 {
226   GstCaps *caps;
227   GstStructure *structure;
228   const gchar *profile;
229
230   caps = gst_caps_new_empty_simple ("video/x-av1");
231   structure = gst_caps_get_structure (caps, 0);
232
233   profile = profile_to_string (encoder->param.mfx.CodecProfile);
234   if (profile)
235     gst_structure_set (structure, "profile", G_TYPE_STRING, profile, NULL);
236
237   return caps;
238 }
239
240 static void
241 gst_msdkav1enc_set_property (GObject * object, guint prop_id,
242     const GValue * value, GParamSpec * pspec)
243 {
244   GstMsdkAV1Enc *thiz = GST_MSDKAV1ENC (object);
245
246   if (gst_msdkenc_set_common_property (object, prop_id, value, pspec))
247     return;
248
249   GST_OBJECT_LOCK (thiz);
250
251   switch (prop_id) {
252     case PROP_TILE_ROW:
253       thiz->num_tile_rows = g_value_get_uint (value);
254       break;
255
256     case PROP_TILE_COL:
257       thiz->num_tile_cols = g_value_get_uint (value);
258       break;
259
260     case PROP_B_PYRAMID:
261       thiz->b_pyramid = g_value_get_boolean (value);
262       break;
263
264     case PROP_P_PYRAMID:
265       thiz->p_pyramid = g_value_get_boolean (value);
266       break;
267
268     default:
269       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
270       break;
271   }
272   GST_OBJECT_UNLOCK (thiz);
273 }
274
275 static void
276 gst_msdkav1enc_get_property (GObject * object, guint prop_id, GValue * value,
277     GParamSpec * pspec)
278 {
279   GstMsdkAV1Enc *thiz = GST_MSDKAV1ENC (object);
280
281   if (gst_msdkenc_get_common_property (object, prop_id, value, pspec))
282     return;
283
284   GST_OBJECT_LOCK (thiz);
285
286   switch (prop_id) {
287     case PROP_TILE_ROW:
288       g_value_set_uint (value, thiz->num_tile_rows);
289       break;
290
291     case PROP_TILE_COL:
292       g_value_set_uint (value, thiz->num_tile_cols);
293       break;
294
295     case PROP_B_PYRAMID:
296       g_value_set_boolean (value, thiz->b_pyramid);
297       break;
298
299     case PROP_P_PYRAMID:
300       g_value_set_boolean (value, thiz->p_pyramid);
301       break;
302
303     default:
304       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
305       break;
306   }
307   GST_OBJECT_UNLOCK (thiz);
308 }
309
310 static void
311 gst_msdkav1enc_finalize (GObject * object)
312 {
313   G_OBJECT_CLASS (parent_class)->finalize (object);
314 }
315
316 static void
317 gst_msdkav1enc_class_init (GstMsdkAV1EncClass * klass)
318 {
319   GObjectClass *gobject_class;
320   GstElementClass *element_class;
321   GstMsdkEncClass *encoder_class;
322
323   gobject_class = G_OBJECT_CLASS (klass);
324   element_class = GST_ELEMENT_CLASS (klass);
325   encoder_class = GST_MSDKENC_CLASS (klass);
326
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;
330
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;
336
337   gst_msdkenc_install_common_properties (encoder_class);
338
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));
344
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));
350
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));
355
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));
360
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>");
367
368   gst_element_class_add_static_pad_template (element_class, &sink_factory);
369   gst_element_class_add_static_pad_template (element_class, &src_factory);
370 }
371
372 static void
373 gst_msdkav1enc_init (GstMsdkAV1Enc * thiz)
374 {
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;
379 }