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 * - Add support for interlaced content
34 * - Add support for MVC AVC
35 * - Wrap more configuration options and maybe move properties to derived
47 #include "gstmsdkenc.h"
48 #include "gstmsdkbufferpool.h"
49 #include "gstmsdkvideomemory.h"
50 #include "gstmsdksystemmemory.h"
51 #include "gstmsdkcontextutil.h"
54 #include "gstmsdkallocator_libva.h"
58 _aligned_alloc (size_t alignment, size_t size)
61 return _aligned_malloc (size, alignment);
64 if (posix_memalign (&out, alignment, size) != 0)
71 #define _aligned_free free
74 static void gst_msdkenc_close_encoder (GstMsdkEnc * thiz);
76 GST_DEBUG_CATEGORY_EXTERN (gst_msdkenc_debug);
77 #define GST_CAT_DEFAULT gst_msdkenc_debug
79 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
82 GST_STATIC_CAPS ("video/x-raw, "
83 "format = (string) { NV12, I420, YV12, YUY2, UYVY, BGRA }, "
84 "framerate = (fraction) [0, MAX], "
85 "width = (int) [ 16, MAX ], height = (int) [ 16, MAX ],"
86 "interlace-mode = (string) progressive" ";"
87 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF,
90 #define PROP_HARDWARE_DEFAULT TRUE
91 #define PROP_ASYNC_DEPTH_DEFAULT 4
92 #define PROP_TARGET_USAGE_DEFAULT (MFX_TARGETUSAGE_BALANCED)
93 #define PROP_RATE_CONTROL_DEFAULT (MFX_RATECONTROL_CBR)
94 #define PROP_BITRATE_DEFAULT (2 * 1024)
95 #define PROP_QPI_DEFAULT 0
96 #define PROP_QPP_DEFAULT 0
97 #define PROP_QPB_DEFAULT 0
98 #define PROP_GOP_SIZE_DEFAULT 256
99 #define PROP_REF_FRAMES_DEFAULT 1
100 #define PROP_I_FRAMES_DEFAULT 0
101 #define PROP_B_FRAMES_DEFAULT 0
102 #define PROP_NUM_SLICES_DEFAULT 0
103 #define PROP_AVBR_ACCURACY_DEFAULT 0
104 #define PROP_AVBR_CONVERGENCE_DEFAULT 0
105 #define PROP_RC_LOOKAHEAD_DEPTH_DEFAULT 10
106 #define PROP_MAX_VBV_BITRATE_DEFAULT 0
107 #define PROP_MAX_FRAME_SIZE_DEFAULT 0
108 #define PROP_MBBRC_DEFAULT MFX_CODINGOPTION_OFF
109 #define PROP_ADAPTIVE_I_DEFAULT MFX_CODINGOPTION_OFF
110 #define PROP_ADAPTIVE_B_DEFAULT MFX_CODINGOPTION_OFF
112 #define gst_msdkenc_parent_class parent_class
113 G_DEFINE_TYPE (GstMsdkEnc, gst_msdkenc, GST_TYPE_VIDEO_ENCODER);
117 mfxFrameSurface1 *surface;
122 gst_msdkenc_add_extra_param (GstMsdkEnc * thiz, mfxExtBuffer * param)
124 if (thiz->num_extra_params < MAX_EXTRA_PARAMS) {
125 thiz->extra_params[thiz->num_extra_params] = param;
126 thiz->num_extra_params++;
131 gst_msdkenc_set_context (GstElement * element, GstContext * context)
133 GstMsdkContext *msdk_context = NULL;
134 GstMsdkEnc *thiz = GST_MSDKENC (element);
136 if (gst_msdk_context_get_context (context, &msdk_context)) {
137 gst_object_replace ((GstObject **) & thiz->context,
138 (GstObject *) msdk_context);
139 gst_object_unref (msdk_context);
142 GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
146 ensure_bitrate_control (GstMsdkEnc * thiz)
148 mfxInfoMFX *mfx = &thiz->param.mfx;
149 mfxExtCodingOption2 *option2 = &thiz->option2;
150 mfxExtCodingOption3 *option3 = &thiz->option3;
152 mfx->RateControlMethod = thiz->rate_control;
153 /* No effect in CQP varient algorithms */
154 mfx->TargetKbps = thiz->bitrate;
155 mfx->MaxKbps = thiz->max_vbv_bitrate;
157 switch (mfx->RateControlMethod) {
158 case MFX_RATECONTROL_CQP:
159 mfx->QPI = thiz->qpi;
160 mfx->QPP = thiz->qpp;
161 mfx->QPB = thiz->qpb;
164 case MFX_RATECONTROL_LA_ICQ:
165 option2->LookAheadDepth = thiz->lookahead_depth;
166 case MFX_RATECONTROL_ICQ:
167 mfx->ICQQuality = CLAMP (thiz->qpi, 1, 51);
170 case MFX_RATECONTROL_LA: /* VBR with LA. Only supported in H264?? */
171 case MFX_RATECONTROL_LA_HRD: /* VBR with LA, HRD compliant */
172 option2->LookAheadDepth = thiz->lookahead_depth;
175 case MFX_RATECONTROL_QVBR:
176 option3->QVBRQuality = CLAMP (thiz->qpi, 1, 51);
177 thiz->enable_extopt3 = TRUE;
180 case MFX_RATECONTROL_AVBR:
181 mfx->Accuracy = thiz->accuracy;
182 mfx->Convergence = thiz->convergence;
185 case MFX_RATECONTROL_VBR:
186 option2->MaxFrameSize = thiz->max_frame_size * 1000;
189 case MFX_RATECONTROL_VCM:
190 /*Non HRD compliant mode with no B-frame and interlaced support */
191 thiz->param.mfx.GopRefDist = 0;
194 case MFX_RATECONTROL_CBR:
198 GST_ERROR ("Unsupported RateControl!");
204 gst_msdkenc_ensure_extended_coding_options (GstMsdkEnc * thiz)
206 mfxExtCodingOption2 *option2 = &thiz->option2;
207 mfxExtCodingOption3 *option3 = &thiz->option3;
209 /* Fill ExtendedCodingOption2, set non-zero defaults too */
210 option2->Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
211 option2->Header.BufferSz = sizeof (thiz->option2);
212 option2->MBBRC = thiz->mbbrc;
213 option2->AdaptiveI = thiz->adaptive_i;
214 option2->AdaptiveB = thiz->adaptive_b;
215 option2->BitrateLimit = MFX_CODINGOPTION_OFF;
216 option2->EnableMAD = MFX_CODINGOPTION_OFF;
217 option2->UseRawRef = MFX_CODINGOPTION_OFF;
218 gst_msdkenc_add_extra_param (thiz, (mfxExtBuffer *) option2);
220 if (thiz->enable_extopt3) {
221 option3->Header.BufferId = MFX_EXTBUFF_CODING_OPTION3;
222 option3->Header.BufferSz = sizeof (thiz->option3);
223 gst_msdkenc_add_extra_param (thiz, (mfxExtBuffer *) option3);
228 gst_msdkenc_init_encoder (GstMsdkEnc * thiz)
230 GstMsdkEncClass *klass = GST_MSDKENC_GET_CLASS (thiz);
234 mfxFrameAllocRequest request[2];
237 if (thiz->initialized)
240 if (!thiz->context) {
241 GST_WARNING_OBJECT (thiz, "No MSDK Context");
245 if (!thiz->input_state) {
246 GST_DEBUG_OBJECT (thiz, "Have no input state yet");
249 info = &thiz->input_state->info;
251 GST_OBJECT_LOCK (thiz);
252 session = gst_msdk_context_get_session (thiz->context);
254 thiz->has_vpp = FALSE;
255 if (thiz->use_video_memory)
256 gst_msdk_set_frame_allocator (thiz->context);
258 /* Check 10bit input */
259 if (GST_VIDEO_INFO_COMP_DEPTH (info, 0) == 10) {
260 if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_FORMAT_P010_10LE) {
261 GST_WARNING_OBJECT (thiz,
262 "P010_10LE is the only supported 10bit format\n");
265 } else if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_FORMAT_NV12) {
266 if (thiz->use_video_memory)
267 thiz->vpp_param.IOPattern =
268 MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
270 thiz->vpp_param.IOPattern =
271 MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
273 thiz->vpp_param.vpp.In.Width = GST_ROUND_UP_16 (info->width);
274 thiz->vpp_param.vpp.In.Height = GST_ROUND_UP_32 (info->height);
275 thiz->vpp_param.vpp.In.CropW = info->width;
276 thiz->vpp_param.vpp.In.CropH = info->height;
277 thiz->vpp_param.vpp.In.FrameRateExtN = info->fps_n;
278 thiz->vpp_param.vpp.In.FrameRateExtD = info->fps_d;
279 thiz->vpp_param.vpp.In.AspectRatioW = info->par_n;
280 thiz->vpp_param.vpp.In.AspectRatioH = info->par_d;
281 thiz->vpp_param.vpp.In.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
282 switch (GST_VIDEO_INFO_FORMAT (info)) {
283 case GST_VIDEO_FORMAT_NV12:
284 thiz->vpp_param.vpp.In.FourCC = MFX_FOURCC_NV12;
285 thiz->vpp_param.vpp.In.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
287 case GST_VIDEO_FORMAT_YV12:
288 case GST_VIDEO_FORMAT_I420:
289 thiz->vpp_param.vpp.In.FourCC = MFX_FOURCC_YV12;
290 thiz->vpp_param.vpp.In.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
292 case GST_VIDEO_FORMAT_YUY2:
293 thiz->vpp_param.vpp.In.FourCC = MFX_FOURCC_YUY2;
294 thiz->vpp_param.vpp.In.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
296 case GST_VIDEO_FORMAT_UYVY:
297 thiz->vpp_param.vpp.In.FourCC = MFX_FOURCC_UYVY;
298 thiz->vpp_param.vpp.In.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
300 case GST_VIDEO_FORMAT_BGRA:
301 thiz->vpp_param.vpp.In.FourCC = MFX_FOURCC_RGB4;
302 thiz->vpp_param.vpp.In.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
305 g_assert_not_reached ();
308 thiz->vpp_param.vpp.Out = thiz->vpp_param.vpp.In;
309 thiz->vpp_param.vpp.Out.FourCC = MFX_FOURCC_NV12;
310 thiz->vpp_param.vpp.Out.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
312 /* validate parameters and allow the Media SDK to make adjustments */
313 status = MFXVideoVPP_Query (session, &thiz->vpp_param, &thiz->vpp_param);
314 if (status < MFX_ERR_NONE) {
315 GST_ERROR_OBJECT (thiz, "Video VPP Query failed (%s)",
316 msdk_status_to_string (status));
318 } else if (status > MFX_ERR_NONE) {
319 GST_WARNING_OBJECT (thiz, "Video VPP Query returned: %s",
320 msdk_status_to_string (status));
323 status = MFXVideoVPP_QueryIOSurf (session, &thiz->vpp_param, request);
324 if (status < MFX_ERR_NONE) {
325 GST_ERROR_OBJECT (thiz, "VPP Query IO surfaces failed (%s)",
326 msdk_status_to_string (status));
328 } else if (status > MFX_ERR_NONE) {
329 GST_WARNING_OBJECT (thiz, "VPP Query IO surfaces returned: %s",
330 msdk_status_to_string (status));
333 if (thiz->use_video_memory)
334 request[0].NumFrameSuggested +=
335 gst_msdk_context_get_shared_async_depth (thiz->context);
336 thiz->num_vpp_surfaces = request[0].NumFrameSuggested;
338 if (thiz->use_video_memory)
339 gst_msdk_frame_alloc (thiz->context, &(request[0]),
340 &thiz->vpp_alloc_resp);
342 status = MFXVideoVPP_Init (session, &thiz->vpp_param);
343 if (status < MFX_ERR_NONE) {
344 GST_ERROR_OBJECT (thiz, "Init failed (%s)",
345 msdk_status_to_string (status));
347 } else if (status > MFX_ERR_NONE) {
348 GST_WARNING_OBJECT (thiz, "Init returned: %s",
349 msdk_status_to_string (status));
352 status = MFXVideoVPP_GetVideoParam (session, &thiz->vpp_param);
353 if (status < MFX_ERR_NONE) {
354 GST_ERROR_OBJECT (thiz, "Get VPP Parameters failed (%s)",
355 msdk_status_to_string (status));
356 MFXVideoVPP_Close (session);
358 } else if (status > MFX_ERR_NONE) {
359 GST_WARNING_OBJECT (thiz, "Get VPP Parameters returned: %s",
360 msdk_status_to_string (status));
363 thiz->has_vpp = TRUE;
366 thiz->param.AsyncDepth = thiz->async_depth;
367 if (thiz->use_video_memory)
368 thiz->param.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
370 thiz->param.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
372 thiz->param.mfx.TargetUsage = thiz->target_usage;
373 thiz->param.mfx.GopPicSize = thiz->gop_size;
374 thiz->param.mfx.GopRefDist = thiz->b_frames + 1;
375 thiz->param.mfx.IdrInterval = thiz->i_frames;
376 thiz->param.mfx.NumSlice = thiz->num_slices;
377 thiz->param.mfx.NumRefFrame = thiz->ref_frames;
378 thiz->param.mfx.EncodedOrder = 0; /* Take input frames in display order */
380 thiz->param.mfx.FrameInfo.Width = GST_ROUND_UP_16 (info->width);
381 thiz->param.mfx.FrameInfo.Height = GST_ROUND_UP_32 (info->height);
382 thiz->param.mfx.FrameInfo.CropW = info->width;
383 thiz->param.mfx.FrameInfo.CropH = info->height;
384 thiz->param.mfx.FrameInfo.FrameRateExtN = info->fps_n;
385 thiz->param.mfx.FrameInfo.FrameRateExtD = info->fps_d;
386 thiz->param.mfx.FrameInfo.AspectRatioW = info->par_n;
387 thiz->param.mfx.FrameInfo.AspectRatioH = info->par_d;
388 thiz->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
389 thiz->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
391 if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_P010_10LE) {
392 thiz->param.mfx.FrameInfo.FourCC = MFX_FOURCC_P010;
393 thiz->param.mfx.FrameInfo.BitDepthLuma = 10;
394 thiz->param.mfx.FrameInfo.BitDepthChroma = 10;
395 thiz->param.mfx.FrameInfo.Shift = 1;
397 thiz->param.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
398 thiz->param.mfx.FrameInfo.BitDepthLuma = 8;
399 thiz->param.mfx.FrameInfo.BitDepthChroma = 8;
402 /* ensure bitrate control parameters */
403 ensure_bitrate_control (thiz);
405 /* allow subclass configure further */
406 if (klass->configure) {
407 if (!klass->configure (thiz))
411 if (thiz->num_extra_params) {
412 thiz->param.NumExtParam = thiz->num_extra_params;
413 thiz->param.ExtParam = thiz->extra_params;
416 /* validate parameters and allow the Media SDK to make adjustments */
417 status = MFXVideoENCODE_Query (session, &thiz->param, &thiz->param);
418 if (status < MFX_ERR_NONE) {
419 GST_ERROR_OBJECT (thiz, "Video Encode Query failed (%s)",
420 msdk_status_to_string (status));
422 } else if (status > MFX_ERR_NONE) {
423 GST_WARNING_OBJECT (thiz, "Video Encode Query returned: %s",
424 msdk_status_to_string (status));
427 status = MFXVideoENCODE_QueryIOSurf (session, &thiz->param, request);
428 if (status < MFX_ERR_NONE) {
429 GST_ERROR_OBJECT (thiz, "Encode Query IO surfaces failed (%s)",
430 msdk_status_to_string (status));
432 } else if (status > MFX_ERR_NONE) {
433 GST_WARNING_OBJECT (thiz, "Encode Query IO surfaces returned: %s",
434 msdk_status_to_string (status));
438 request[0].NumFrameSuggested += thiz->num_vpp_surfaces + 1 - 4;
440 if (thiz->use_video_memory) {
441 if (thiz->use_dmabuf && !thiz->has_vpp)
442 request[0].Type |= MFX_MEMTYPE_EXPORT_FRAME;
443 gst_msdk_frame_alloc (thiz->context, &(request[0]), &thiz->alloc_resp);
446 /* Maximum of VPP output and encoder input, if using VPP */
448 request[0].NumFrameSuggested =
449 MAX (request[0].NumFrameSuggested, request[1].NumFrameSuggested);
450 if (request[0].NumFrameSuggested < thiz->param.AsyncDepth) {
451 GST_ERROR_OBJECT (thiz, "Required %d surfaces (%d suggested), async %d",
452 request[0].NumFrameMin, request[0].NumFrameSuggested,
453 thiz->param.AsyncDepth);
457 /* This is VPP output (if any) and encoder input */
458 thiz->num_surfaces = request[0].NumFrameSuggested;
460 GST_DEBUG_OBJECT (thiz, "Required %d surfaces (%d suggested), allocated %d",
461 request[0].NumFrameMin, request[0].NumFrameSuggested, thiz->num_surfaces);
463 status = MFXVideoENCODE_Init (session, &thiz->param);
464 if (status < MFX_ERR_NONE) {
465 GST_ERROR_OBJECT (thiz, "Init failed (%s)", msdk_status_to_string (status));
467 } else if (status > MFX_ERR_NONE) {
468 GST_WARNING_OBJECT (thiz, "Init returned: %s",
469 msdk_status_to_string (status));
472 status = MFXVideoENCODE_GetVideoParam (session, &thiz->param);
473 if (status < MFX_ERR_NONE) {
474 GST_ERROR_OBJECT (thiz, "Get Video Parameters failed (%s)",
475 msdk_status_to_string (status));
477 } else if (status > MFX_ERR_NONE) {
478 GST_WARNING_OBJECT (thiz, "Get Video Parameters returned: %s",
479 msdk_status_to_string (status));
482 thiz->num_tasks = thiz->param.AsyncDepth;
483 thiz->tasks = g_new0 (MsdkEncTask, thiz->num_tasks);
484 for (i = 0; i < thiz->num_tasks; i++) {
485 thiz->tasks[i].output_bitstream.Data = _aligned_alloc (32,
486 thiz->param.mfx.BufferSizeInKB * 1024);
487 if (!thiz->tasks[i].output_bitstream.Data) {
488 GST_ERROR_OBJECT (thiz, "Memory allocation failed");
491 thiz->tasks[i].output_bitstream.MaxLength =
492 thiz->param.mfx.BufferSizeInKB * 1024;
496 thiz->reconfig = FALSE;
497 thiz->initialized = TRUE;
499 GST_OBJECT_UNLOCK (thiz);
505 GST_OBJECT_UNLOCK (thiz);
510 gst_msdkenc_close_encoder (GstMsdkEnc * thiz)
515 if (!thiz->context || !thiz->initialized)
518 GST_DEBUG_OBJECT (thiz, "Closing encoder with context %" GST_PTR_FORMAT,
521 gst_object_replace ((GstObject **) & thiz->msdk_pool, NULL);
522 gst_object_replace ((GstObject **) & thiz->msdk_converted_pool, NULL);
524 if (thiz->use_video_memory)
525 gst_msdk_frame_free (thiz->context, &thiz->alloc_resp);
527 status = MFXVideoENCODE_Close (gst_msdk_context_get_session (thiz->context));
528 if (status != MFX_ERR_NONE && status != MFX_ERR_NOT_INITIALIZED) {
529 GST_WARNING_OBJECT (thiz, "Encoder close failed (%s)",
530 msdk_status_to_string (status));
534 for (i = 0; i < thiz->num_tasks; i++) {
535 MsdkEncTask *task = &thiz->tasks[i];
536 if (task->output_bitstream.Data) {
537 _aligned_free (task->output_bitstream.Data);
541 g_free (thiz->tasks);
544 /* Close VPP before freeing the surfaces. They are shared between encoder
547 if (thiz->use_video_memory)
548 gst_msdk_frame_free (thiz->context, &thiz->vpp_alloc_resp);
550 status = MFXVideoVPP_Close (gst_msdk_context_get_session (thiz->context));
551 if (status != MFX_ERR_NONE && status != MFX_ERR_NOT_INITIALIZED) {
552 GST_WARNING_OBJECT (thiz, "VPP close failed (%s)",
553 msdk_status_to_string (status));
557 memset (&thiz->param, 0, sizeof (thiz->param));
558 thiz->num_extra_params = 0;
559 thiz->initialized = FALSE;
564 GstVideoCodecFrame *frame;
565 MsdkSurface *frame_surface;
566 MsdkSurface *converted_surface;
570 gst_msdkenc_queue_frame (GstMsdkEnc * thiz, GstVideoCodecFrame * frame,
575 fdata = g_slice_new (FrameData);
576 fdata->frame = gst_video_codec_frame_ref (frame);
578 thiz->pending_frames = g_list_prepend (thiz->pending_frames, fdata);
584 gst_msdkenc_create_surface (mfxFrameSurface1 * surface, GstBuffer * buf)
586 MsdkSurface *msdk_surface;
587 msdk_surface = g_slice_new0 (MsdkSurface);
588 msdk_surface->surface = surface;
589 msdk_surface->buf = buf;
595 gst_msdkenc_free_surface (MsdkSurface * surface)
598 gst_buffer_unref (surface->buf);
600 g_slice_free (MsdkSurface, surface);
604 gst_msdkenc_free_frame_data (GstMsdkEnc * thiz, FrameData * fdata)
606 if (fdata->frame_surface)
607 gst_msdkenc_free_surface (fdata->frame_surface);
609 gst_msdkenc_free_surface (fdata->converted_surface);
611 gst_video_codec_frame_unref (fdata->frame);
612 g_slice_free (FrameData, fdata);
616 gst_msdkenc_dequeue_frame (GstMsdkEnc * thiz, GstVideoCodecFrame * frame)
620 for (l = thiz->pending_frames; l; l = l->next) {
621 FrameData *fdata = l->data;
623 if (fdata->frame != frame)
626 gst_msdkenc_free_frame_data (thiz, fdata);
628 thiz->pending_frames = g_list_delete_link (thiz->pending_frames, l);
634 gst_msdkenc_dequeue_all_frames (GstMsdkEnc * thiz)
638 for (l = thiz->pending_frames; l; l = l->next) {
639 FrameData *fdata = l->data;
641 gst_msdkenc_free_frame_data (thiz, fdata);
643 g_list_free (thiz->pending_frames);
644 thiz->pending_frames = NULL;
648 gst_msdkenc_get_free_task (GstMsdkEnc * thiz)
650 MsdkEncTask *tasks = thiz->tasks;
651 guint size = thiz->num_tasks;
652 guint start = thiz->next_task;
656 for (i = 0; i < size; i++) {
657 guint t = (start + i) % size;
658 if (tasks[t].sync_point == NULL)
666 gst_msdkenc_reset_task (MsdkEncTask * task)
668 task->output_bitstream.DataLength = 0;
669 task->sync_point = NULL;
673 gst_msdkenc_finish_frame (GstMsdkEnc * thiz, MsdkEncTask * task,
676 GstVideoCodecFrame *frame;
678 if (!task->sync_point)
681 frame = gst_video_encoder_get_oldest_frame (GST_VIDEO_ENCODER (thiz));
684 GST_ERROR_OBJECT (thiz, "failed to get a frame");
685 return GST_FLOW_ERROR;
688 /* Wait for encoding operation to complete, the magic number 300000 below
689 * is used in MSDK samples
690 * #define MSDK_ENC_WAIT_INTERVAL 300000
692 MFXVideoCORE_SyncOperation (gst_msdk_context_get_session (thiz->context),
693 task->sync_point, 300000);
694 if (!discard && task->output_bitstream.DataLength) {
695 GstBuffer *out_buf = NULL;
697 task->output_bitstream.Data + task->output_bitstream.DataOffset;
698 gsize size = task->output_bitstream.DataLength;
699 out_buf = gst_buffer_new_allocate (NULL, size, NULL);
700 gst_buffer_fill (out_buf, 0, data, size);
701 frame->output_buffer = out_buf;
703 gst_util_uint64_scale (task->output_bitstream.TimeStamp, GST_SECOND,
706 gst_util_uint64_scale (task->output_bitstream.DecodeTimeStamp,
709 if ((task->output_bitstream.FrameType & MFX_FRAMETYPE_IDR) != 0 ||
710 (task->output_bitstream.FrameType & MFX_FRAMETYPE_xIDR) != 0) {
711 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
714 /* Mark task as available */
715 gst_msdkenc_reset_task (task);
718 gst_video_codec_frame_unref (frame);
719 gst_msdkenc_dequeue_frame (thiz, frame);
721 return gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (thiz), frame);
725 gst_msdkenc_encode_frame (GstMsdkEnc * thiz, mfxFrameSurface1 * surface,
726 GstVideoCodecFrame * input_frame)
732 if (G_UNLIKELY (thiz->context == NULL)) {
733 gst_msdkenc_dequeue_frame (thiz, input_frame);
734 gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (thiz), input_frame);
735 return GST_FLOW_NOT_NEGOTIATED;
737 session = gst_msdk_context_get_session (thiz->context);
739 task = gst_msdkenc_get_free_task (thiz);
742 /* Force key-frame if needed */
743 if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (input_frame))
744 thiz->enc_cntrl.FrameType =
745 MFX_FRAMETYPE_I | MFX_FRAMETYPE_IDR | MFX_FRAMETYPE_REF;
747 thiz->enc_cntrl.FrameType = MFX_FRAMETYPE_UNKNOWN;
750 MFXVideoENCODE_EncodeFrameAsync (session, &thiz->enc_cntrl, surface,
751 &task->output_bitstream, &task->sync_point);
752 if (status != MFX_WRN_DEVICE_BUSY)
754 /* If device is busy, wait 1ms and retry, as per MSDK's recomendation */
758 if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA) {
759 GST_ELEMENT_ERROR (thiz, STREAM, ENCODE, ("Encode frame failed."),
760 ("MSDK encode error (%s)", msdk_status_to_string (status)));
761 gst_msdkenc_dequeue_frame (thiz, input_frame);
762 gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (thiz), input_frame);
763 return GST_FLOW_ERROR;
766 if (task->sync_point) {
767 thiz->next_task = ((task - thiz->tasks) + 1) % thiz->num_tasks;
768 } else if (status == MFX_ERR_MORE_DATA) {
769 gst_msdkenc_dequeue_frame (thiz, input_frame);
772 /* Ensure that next task is available */
773 task = thiz->tasks + thiz->next_task;
774 return gst_msdkenc_finish_frame (thiz, task, FALSE);
778 gst_msdkenc_maximum_delayed_frames (GstMsdkEnc * thiz)
780 return thiz->num_tasks;
784 gst_msdkenc_set_latency (GstMsdkEnc * thiz)
786 GstVideoInfo *info = &thiz->input_state->info;
787 gint max_delayed_frames;
788 GstClockTime latency;
790 max_delayed_frames = gst_msdkenc_maximum_delayed_frames (thiz);
793 latency = gst_util_uint64_scale_ceil (GST_SECOND * info->fps_d,
794 max_delayed_frames, info->fps_n);
796 /* FIXME: Assume 25fps. This is better than reporting no latency at
797 * all and then later failing in live pipelines
799 latency = gst_util_uint64_scale_ceil (GST_SECOND * 1,
800 max_delayed_frames, 25);
803 GST_INFO_OBJECT (thiz,
804 "Updating latency to %" GST_TIME_FORMAT " (%d frames)",
805 GST_TIME_ARGS (latency), max_delayed_frames);
807 gst_video_encoder_set_latency (GST_VIDEO_ENCODER (thiz), latency, latency);
811 gst_msdkenc_flush_frames (GstMsdkEnc * thiz, gboolean discard)
821 session = gst_msdk_context_get_session (thiz->context);
824 task = thiz->tasks + thiz->next_task;
825 gst_msdkenc_finish_frame (thiz, task, FALSE);
827 status = MFXVideoENCODE_EncodeFrameAsync (session, NULL, NULL,
828 &task->output_bitstream, &task->sync_point);
830 if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA) {
831 GST_ELEMENT_ERROR (thiz, STREAM, ENCODE, ("Encode frame failed."),
832 ("MSDK encode error (%s)", msdk_status_to_string (status)));
836 if (task->sync_point) {
837 thiz->next_task = ((task - thiz->tasks) + 1) % thiz->num_tasks;
838 } else if (status == MFX_ERR_MORE_DATA) {
844 for (i = 0; i < thiz->num_tasks; i++) {
845 gst_msdkenc_finish_frame (thiz, &thiz->tasks[t], discard);
846 t = (t + 1) % thiz->num_tasks;
851 gst_msdkenc_set_src_caps (GstMsdkEnc * thiz)
853 GstMsdkEncClass *klass = GST_MSDKENC_GET_CLASS (thiz);
854 GstCaps *outcaps = NULL;
855 GstVideoCodecState *state;
858 if (klass->set_src_caps)
859 outcaps = klass->set_src_caps (thiz);
864 state = gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (thiz),
865 outcaps, thiz->input_state);
866 GST_DEBUG_OBJECT (thiz, "output caps: %" GST_PTR_FORMAT, state->caps);
868 gst_video_codec_state_unref (state);
870 tags = gst_tag_list_new_empty ();
871 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER, "msdkenc",
872 GST_TAG_MAXIMUM_BITRATE, thiz->bitrate * 1024,
873 GST_TAG_NOMINAL_BITRATE, thiz->bitrate * 1024, NULL);
874 gst_video_encoder_merge_tags (GST_VIDEO_ENCODER (thiz), tags,
875 GST_TAG_MERGE_REPLACE);
876 gst_tag_list_unref (tags);
881 static GstBufferPool *
882 gst_msdkenc_create_buffer_pool (GstMsdkEnc * thiz, GstCaps * caps,
883 guint num_buffers, gboolean set_align)
885 GstBufferPool *pool = NULL;
886 GstStructure *config;
887 GstAllocator *allocator = NULL;
889 GstVideoAlignment align;
890 GstAllocationParams params = { 0, 31, 0, 0, };
891 mfxFrameAllocResponse *alloc_resp = NULL;
894 alloc_resp = set_align ? &thiz->vpp_alloc_resp : &thiz->alloc_resp;
896 alloc_resp = &thiz->alloc_resp;
898 pool = gst_msdk_buffer_pool_new (thiz->context, alloc_resp);
902 if (!gst_video_info_from_caps (&info, caps)) {
903 GST_INFO_OBJECT (thiz, "failed to get video info");
907 gst_msdk_set_video_alignment (&info, &align);
908 gst_video_info_align (&info, &align);
910 if (thiz->use_dmabuf)
912 gst_msdk_dmabuf_allocator_new (thiz->context, &info, alloc_resp);
913 else if (thiz->use_video_memory)
914 allocator = gst_msdk_video_allocator_new (thiz->context, &info, alloc_resp);
916 allocator = gst_msdk_system_allocator_new (&info);
919 goto error_no_allocator;
921 config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
922 gst_buffer_pool_config_set_params (config, caps, info.size, num_buffers, 0);
923 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
924 gst_buffer_pool_config_add_option (config,
925 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
927 if (thiz->use_video_memory) {
928 gst_buffer_pool_config_add_option (config,
929 GST_BUFFER_POOL_OPTION_MSDK_USE_VIDEO_MEMORY);
930 if (thiz->use_dmabuf)
931 gst_buffer_pool_config_add_option (config,
932 GST_BUFFER_POOL_OPTION_MSDK_USE_DMABUF);
935 gst_buffer_pool_config_set_video_alignment (config, &align);
936 gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);
937 gst_object_unref (allocator);
939 if (!gst_buffer_pool_set_config (pool, config))
940 goto error_pool_config;
943 thiz->aligned_info = info;
949 GST_INFO_OBJECT (thiz, "failed to create bufferpool");
954 GST_INFO_OBJECT (thiz, "failed to create allocator");
955 gst_object_unref (pool);
960 GST_INFO_OBJECT (thiz, "failed to set config");
961 gst_object_unref (pool);
962 gst_object_unref (allocator);
967 /* Fixme: Common routine used by all msdk elements, should be
968 * moved to a common util file */
970 _gst_caps_has_feature (const GstCaps * caps, const gchar * feature)
974 for (i = 0; i < gst_caps_get_size (caps); i++) {
975 GstCapsFeatures *const features = gst_caps_get_features (caps, i);
976 /* Skip ANY features, we need an exact match for correct evaluation */
977 if (gst_caps_features_is_any (features))
979 if (gst_caps_features_contains (features, feature))
986 sinkpad_can_dmabuf (GstMsdkEnc * thiz)
988 gboolean ret = FALSE;
989 GstCaps *caps, *allowed_caps;
992 sinkpad = GST_VIDEO_ENCODER_SINK_PAD (thiz);
993 caps = gst_pad_get_pad_template_caps (sinkpad);
995 allowed_caps = gst_pad_peer_query_caps (sinkpad, caps);
998 if (gst_caps_is_any (allowed_caps) || gst_caps_is_empty (allowed_caps)
999 || allowed_caps == caps)
1002 if (_gst_caps_has_feature (allowed_caps, GST_CAPS_FEATURE_MEMORY_DMABUF))
1007 gst_caps_unref (caps);
1009 gst_caps_unref (allowed_caps);
1014 gst_msdkenc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state)
1016 GstMsdkEnc *thiz = GST_MSDKENC (encoder);
1017 GstMsdkEncClass *klass = GST_MSDKENC_GET_CLASS (thiz);
1020 if (thiz->input_state)
1021 gst_video_codec_state_unref (thiz->input_state);
1022 thiz->input_state = gst_video_codec_state_ref (state);
1025 /* TODO: Currently d3d allocator is not implemented.
1026 * So encoder uses system memory by default on Windows.
1029 thiz->use_video_memory = TRUE;
1031 thiz->use_video_memory = FALSE;
1034 GST_INFO_OBJECT (encoder, "This MSDK encoder uses %s memory",
1035 thiz->use_video_memory ? "video" : "system");
1037 if (klass->set_format) {
1038 if (!klass->set_format (thiz))
1042 /* If upstream supports DMABufCapsfeatures, then we request for the dmabuf
1043 * based pipeline usage. Ideally we should have dmabuf support even with
1044 * raw-caps negotiation, but we don't have dmabuf-import support in msdk
1046 if (sinkpad_can_dmabuf (thiz)) {
1047 thiz->input_state->caps = gst_caps_make_writable (thiz->input_state->caps);
1048 gst_caps_set_features (thiz->input_state->caps, 0,
1049 gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_DMABUF, NULL));
1050 thiz->use_dmabuf = TRUE;
1053 if (!gst_msdkenc_init_encoder (thiz))
1056 if (!gst_msdkenc_set_src_caps (thiz)) {
1057 gst_msdkenc_close_encoder (thiz);
1061 if (!thiz->msdk_pool) {
1062 guint num_buffers = gst_msdkenc_maximum_delayed_frames (thiz) + 1;
1064 gst_msdkenc_create_buffer_pool (thiz, thiz->input_state->caps,
1068 gst_msdkenc_set_latency (thiz);
1070 /* Create another bufferpool if VPP requires */
1071 if (thiz->has_vpp) {
1072 GstVideoInfo *info = &thiz->input_state->info;
1073 GstVideoInfo nv12_info;
1075 GstBufferPool *pool = NULL;
1077 gst_video_info_init (&nv12_info);
1078 gst_video_info_set_format (&nv12_info, GST_VIDEO_FORMAT_NV12, info->width,
1080 caps = gst_video_info_to_caps (&nv12_info);
1083 gst_msdkenc_create_buffer_pool (thiz, caps, thiz->num_surfaces, FALSE);
1085 thiz->msdk_converted_pool = pool;
1086 gst_caps_unref (caps);
1092 static MsdkSurface *
1093 gst_msdkenc_get_surface_from_pool (GstMsdkEnc * thiz, GstBufferPool * pool,
1094 GstBufferPoolAcquireParams * params)
1096 GstBuffer *new_buffer;
1097 mfxFrameSurface1 *new_surface;
1098 MsdkSurface *msdk_surface;
1100 if (!gst_buffer_pool_is_active (pool) &&
1101 !gst_buffer_pool_set_active (pool, TRUE)) {
1102 GST_ERROR_OBJECT (pool, "failed to activate buffer pool");
1106 if (gst_buffer_pool_acquire_buffer (pool, &new_buffer, params) != GST_FLOW_OK) {
1107 GST_ERROR_OBJECT (pool, "failed to acquire a buffer from pool");
1111 if (gst_msdk_is_msdk_buffer (new_buffer))
1112 new_surface = gst_msdk_get_surface_from_buffer (new_buffer);
1114 GST_ERROR_OBJECT (pool, "the acquired memory is not MSDK memory");
1118 msdk_surface = gst_msdkenc_create_surface (new_surface, new_buffer);
1120 return msdk_surface;
1125 import_dmabuf_to_msdk_surface (GstMsdkEnc * thiz, GstBuffer * buf,
1126 MsdkSurface * msdk_surface)
1128 GstMemory *mem = NULL;
1130 GstVideoMeta *vmeta;
1131 GstMsdkMemoryID *msdk_mid = NULL;
1132 mfxFrameSurface1 *mfx_surface = NULL;
1134 mem = gst_buffer_peek_memory (buf, 0);
1135 fd = gst_dmabuf_memory_get_fd (mem);
1139 vinfo = thiz->input_state->info;
1140 /* Update offset/stride/size if there is VideoMeta attached to
1142 vmeta = gst_buffer_get_video_meta (buf);
1144 if (GST_VIDEO_INFO_FORMAT (&vinfo) != vmeta->format ||
1145 GST_VIDEO_INFO_WIDTH (&vinfo) != vmeta->width ||
1146 GST_VIDEO_INFO_HEIGHT (&vinfo) != vmeta->height ||
1147 GST_VIDEO_INFO_N_PLANES (&vinfo) != vmeta->n_planes) {
1148 GST_ERROR_OBJECT (thiz, "VideoMeta attached to buffer is not matching"
1149 "the negotiated width/height/format");
1152 for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&vinfo); ++i) {
1153 GST_VIDEO_INFO_PLANE_OFFSET (&vinfo, i) = vmeta->offset[i];
1154 GST_VIDEO_INFO_PLANE_STRIDE (&vinfo, i) = vmeta->stride[i];
1156 GST_VIDEO_INFO_SIZE (&vinfo) = gst_buffer_get_size (buf);
1159 /* Upstream neither accepted the msdk pool nor the msdk buffer size restrictions.
1160 * Current media-driver and GMMLib will fail due to strict memory size restrictions.
1161 * Ideally, media-driver should accept what ever memory coming from other drivers
1162 * in case of dmabuf-import and this is how the intel-vaapi-driver works.
1163 * For now, in order to avoid any crash we check the buffer size and fallback
1164 * to copy frame method.
1166 * See this: https://github.com/intel/media-driver/issues/169
1168 if (GST_VIDEO_INFO_SIZE (&vinfo) < GST_VIDEO_INFO_SIZE (&thiz->aligned_info))
1171 mfx_surface = msdk_surface->surface;
1172 msdk_mid = (GstMsdkMemoryID *) mfx_surface->Data.MemId;
1174 /* release the internal memory storage of associated mfxSurface */
1175 gst_msdk_replace_mfx_memid (thiz->context, mfx_surface, VA_INVALID_ID);
1177 /* export dmabuf to vasurface */
1178 if (!gst_msdk_export_dmabuf_to_vasurface (thiz->context, &vinfo, fd,
1186 static MsdkSurface *
1187 gst_msdkenc_get_surface_from_frame (GstMsdkEnc * thiz,
1188 GstVideoCodecFrame * frame)
1190 GstVideoFrame src_frame, out_frame;
1191 MsdkSurface *msdk_surface;
1193 GstMemory *mem = NULL;
1195 inbuf = frame->input_buffer;
1196 if (gst_msdk_is_msdk_buffer (inbuf)) {
1197 msdk_surface = g_slice_new0 (MsdkSurface);
1198 msdk_surface->surface = gst_msdk_get_surface_from_buffer (inbuf);
1199 return msdk_surface;
1202 /* If upstream hasn't accpeted the proposed msdk bufferpool,
1203 * just copy frame (if not dmabuf backed )to msdk buffer and take a surface from it.
1205 if (!(msdk_surface =
1206 gst_msdkenc_get_surface_from_pool (thiz, thiz->msdk_pool, NULL)))
1210 /************ dmabuf-import ************* */
1211 /* if upstream provided a dmabuf backed memory, but not an msdk
1212 * buffer, we could try to export the dmabuf to underlined vasurface */
1213 mem = gst_buffer_peek_memory (inbuf, 0);
1214 if (gst_is_dmabuf_memory (mem)) {
1215 if (import_dmabuf_to_msdk_surface (thiz, inbuf, msdk_surface))
1216 return msdk_surface;
1218 GST_INFO_OBJECT (thiz, "Upstream dmabuf-backed memory is not imported"
1219 "to the msdk surface, fall back to the copy input frame method");
1223 if (!gst_video_frame_map (&src_frame, &thiz->input_state->info, inbuf,
1225 GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
1229 if (!gst_video_frame_map (&out_frame, &thiz->aligned_info, msdk_surface->buf,
1231 GST_ERROR_OBJECT (thiz, "failed to map the frame for destination");
1232 gst_video_frame_unmap (&src_frame);
1236 if (!gst_video_frame_copy (&out_frame, &src_frame)) {
1237 GST_ERROR_OBJECT (thiz, "failed to copy frame");
1238 gst_video_frame_unmap (&out_frame);
1239 gst_video_frame_unmap (&src_frame);
1243 gst_video_frame_unmap (&out_frame);
1244 gst_video_frame_unmap (&src_frame);
1246 gst_buffer_replace (&frame->input_buffer, msdk_surface->buf);
1247 gst_buffer_unref (msdk_surface->buf);
1248 msdk_surface->buf = NULL;
1250 return msdk_surface;
1254 if (msdk_surface->buf)
1255 gst_buffer_unref (msdk_surface->buf);
1256 g_slice_free (MsdkSurface, msdk_surface);
1261 static GstFlowReturn
1262 gst_msdkenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
1264 GstMsdkEnc *thiz = GST_MSDKENC (encoder);
1265 GstVideoInfo *info = &thiz->input_state->info;
1267 MsdkSurface *surface;
1269 if (thiz->reconfig) {
1270 gst_msdkenc_flush_frames (thiz, FALSE);
1271 gst_msdkenc_set_format (encoder, NULL);
1274 if (G_UNLIKELY (thiz->context == NULL))
1277 if (thiz->has_vpp) {
1278 MsdkSurface *vpp_surface;
1279 GstVideoFrame vframe;
1281 mfxSyncPoint vpp_sync_point = NULL;
1284 vpp_surface = gst_msdkenc_get_surface_from_frame (thiz, frame);
1286 goto invalid_surface;
1288 gst_msdkenc_get_surface_from_pool (thiz, thiz->msdk_converted_pool,
1291 goto invalid_surface;
1293 if (!gst_video_frame_map (&vframe, info, frame->input_buffer, GST_MAP_READ))
1296 if (frame->pts != GST_CLOCK_TIME_NONE) {
1297 vpp_surface->surface->Data.TimeStamp =
1298 gst_util_uint64_scale (frame->pts, 90000, GST_SECOND);
1299 surface->surface->Data.TimeStamp =
1300 gst_util_uint64_scale (frame->pts, 90000, GST_SECOND);
1302 vpp_surface->surface->Data.TimeStamp = MFX_TIMESTAMP_UNKNOWN;
1303 surface->surface->Data.TimeStamp = MFX_TIMESTAMP_UNKNOWN;
1306 session = gst_msdk_context_get_session (thiz->context);
1309 MFXVideoVPP_RunFrameVPPAsync (session, vpp_surface->surface,
1310 surface->surface, NULL, &vpp_sync_point);
1311 if (status != MFX_WRN_DEVICE_BUSY)
1313 /* If device is busy, wait 1ms and retry, as per MSDK's recomendation */
1317 gst_video_frame_unmap (&vframe);
1319 if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA) {
1320 GST_ELEMENT_ERROR (thiz, STREAM, ENCODE, ("Converting frame failed."),
1321 ("MSDK VPP error (%s)", msdk_status_to_string (status)));
1322 gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (thiz), frame);
1323 return GST_FLOW_ERROR;
1326 fdata = g_slice_new0 (FrameData);
1327 fdata->frame = gst_video_codec_frame_ref (frame);
1328 fdata->frame_surface = vpp_surface;
1329 fdata->converted_surface = surface;
1331 thiz->pending_frames = g_list_prepend (thiz->pending_frames, fdata);
1333 surface = gst_msdkenc_get_surface_from_frame (thiz, frame);
1335 goto invalid_surface;
1337 fdata = gst_msdkenc_queue_frame (thiz, frame, info);
1341 fdata->frame_surface = surface;
1343 if (frame->pts != GST_CLOCK_TIME_NONE) {
1344 surface->surface->Data.TimeStamp =
1345 gst_util_uint64_scale (frame->pts, 90000, GST_SECOND);
1347 surface->surface->Data.TimeStamp = MFX_TIMESTAMP_UNKNOWN;
1351 return gst_msdkenc_encode_frame (thiz, surface->surface, frame);
1356 GST_WARNING_OBJECT (encoder, "Got buffer before set_caps was called");
1357 return GST_FLOW_NOT_NEGOTIATED;
1361 GST_ERROR_OBJECT (encoder, "Surface pool is full");
1362 return GST_FLOW_ERROR;
1366 GST_WARNING_OBJECT (encoder, "Failed to map frame");
1372 gst_msdkenc_start (GstVideoEncoder * encoder)
1374 GstMsdkEnc *thiz = GST_MSDKENC (encoder);
1376 if (gst_msdk_context_prepare (GST_ELEMENT_CAST (thiz), &thiz->context)) {
1377 GST_INFO_OBJECT (thiz, "Found context %" GST_PTR_FORMAT " from neighbour",
1380 if (gst_msdk_context_get_job_type (thiz->context) & GST_MSDK_JOB_ENCODER) {
1381 GstMsdkContext *parent_context, *msdk_context;
1383 parent_context = thiz->context;
1384 msdk_context = gst_msdk_context_new_with_parent (parent_context);
1386 if (!msdk_context) {
1387 GST_ERROR_OBJECT (thiz, "Context creation failed");
1391 thiz->context = msdk_context;
1392 gst_object_unref (parent_context);
1394 GST_INFO_OBJECT (thiz,
1395 "Creating new context %" GST_PTR_FORMAT " with joined session",
1398 gst_msdk_context_add_job_type (thiz->context, GST_MSDK_JOB_ENCODER);
1401 gst_msdk_context_ensure_context (GST_ELEMENT_CAST (thiz), thiz->hardware,
1402 GST_MSDK_JOB_ENCODER);
1404 GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT,
1408 gst_msdk_context_add_shared_async_depth (thiz->context, thiz->async_depth);
1410 /* Set the minimum pts to some huge value (1000 hours). This keeps
1411 the dts at the start of the stream from needing to be
1413 gst_video_encoder_set_min_pts (encoder, GST_SECOND * 60 * 60 * 1000);
1419 gst_msdkenc_stop (GstVideoEncoder * encoder)
1421 GstMsdkEnc *thiz = GST_MSDKENC (encoder);
1423 gst_msdkenc_flush_frames (thiz, TRUE);
1424 gst_msdkenc_close_encoder (thiz);
1425 gst_msdkenc_dequeue_all_frames (thiz);
1427 if (thiz->input_state)
1428 gst_video_codec_state_unref (thiz->input_state);
1429 thiz->input_state = NULL;
1431 gst_object_replace ((GstObject **) & thiz->context, NULL);
1437 gst_msdkenc_flush (GstVideoEncoder * encoder)
1439 GstMsdkEnc *thiz = GST_MSDKENC (encoder);
1441 gst_msdkenc_flush_frames (thiz, TRUE);
1442 gst_msdkenc_close_encoder (thiz);
1443 gst_msdkenc_dequeue_all_frames (thiz);
1445 gst_msdkenc_init_encoder (thiz);
1450 static GstFlowReturn
1451 gst_msdkenc_finish (GstVideoEncoder * encoder)
1453 GstMsdkEnc *thiz = GST_MSDKENC (encoder);
1455 gst_msdkenc_flush_frames (thiz, FALSE);
1462 gst_msdkenc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
1464 GstMsdkEnc *thiz = GST_MSDKENC (encoder);
1466 GstBufferPool *pool = NULL;
1467 GstAllocator *allocator = NULL;
1471 if (!thiz->input_state)
1474 gst_query_parse_allocation (query, &caps, NULL);
1477 GST_INFO_OBJECT (encoder, "failed to get caps");
1481 if (!gst_video_info_from_caps (&info, caps)) {
1482 GST_INFO_OBJECT (encoder, "failed to get video info");
1486 /* if upstream allocation query supports dmabuf-capsfeatures,
1487 * we do allocate dmabuf backed memory */
1488 if (_gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) {
1489 GST_INFO_OBJECT (thiz, "MSDK VPP srcpad uses DMABuf memory");
1490 thiz->use_dmabuf = TRUE;
1493 num_buffers = gst_msdkenc_maximum_delayed_frames (thiz) + 1;
1494 pool = gst_msdkenc_create_buffer_pool (thiz, caps, num_buffers, TRUE);
1496 gst_query_add_allocation_pool (query, pool, GST_VIDEO_INFO_SIZE (&info),
1498 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
1501 GstStructure *config;
1502 GstAllocationParams params = { 0, 31, 0, 0, };
1504 config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
1506 if (gst_buffer_pool_config_get_allocator (config, &allocator, NULL))
1507 gst_query_add_allocation_param (query, allocator, ¶ms);
1508 gst_structure_free (config);
1511 gst_object_unref (pool);
1513 return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
1519 gst_msdkenc_finalize (GObject * object)
1521 GstMsdkEnc *thiz = GST_MSDKENC (object);
1523 if (thiz->input_state)
1524 gst_video_codec_state_unref (thiz->input_state);
1525 thiz->input_state = NULL;
1527 gst_object_replace ((GstObject **) & thiz->msdk_pool, NULL);
1528 gst_object_replace ((GstObject **) & thiz->msdk_converted_pool, NULL);
1530 G_OBJECT_CLASS (parent_class)->finalize (object);
1534 gst_msdkenc_class_init (GstMsdkEncClass * klass)
1536 GObjectClass *gobject_class;
1537 GstElementClass *element_class;
1538 GstVideoEncoderClass *gstencoder_class;
1540 gobject_class = G_OBJECT_CLASS (klass);
1541 element_class = GST_ELEMENT_CLASS (klass);
1542 gstencoder_class = GST_VIDEO_ENCODER_CLASS (klass);
1544 gobject_class->finalize = gst_msdkenc_finalize;
1546 element_class->set_context = gst_msdkenc_set_context;
1548 gstencoder_class->set_format = GST_DEBUG_FUNCPTR (gst_msdkenc_set_format);
1549 gstencoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_msdkenc_handle_frame);
1550 gstencoder_class->start = GST_DEBUG_FUNCPTR (gst_msdkenc_start);
1551 gstencoder_class->stop = GST_DEBUG_FUNCPTR (gst_msdkenc_stop);
1552 gstencoder_class->flush = GST_DEBUG_FUNCPTR (gst_msdkenc_flush);
1553 gstencoder_class->finish = GST_DEBUG_FUNCPTR (gst_msdkenc_finish);
1554 gstencoder_class->propose_allocation =
1555 GST_DEBUG_FUNCPTR (gst_msdkenc_propose_allocation);
1557 gst_element_class_add_static_pad_template (element_class, &sink_factory);
1561 gst_msdkenc_init (GstMsdkEnc * thiz)
1563 thiz->hardware = PROP_HARDWARE_DEFAULT;
1564 thiz->async_depth = PROP_ASYNC_DEPTH_DEFAULT;
1565 thiz->target_usage = PROP_TARGET_USAGE_DEFAULT;
1566 thiz->rate_control = PROP_RATE_CONTROL_DEFAULT;
1567 thiz->bitrate = PROP_BITRATE_DEFAULT;
1568 thiz->max_frame_size = PROP_MAX_FRAME_SIZE_DEFAULT;
1569 thiz->max_vbv_bitrate = PROP_MAX_VBV_BITRATE_DEFAULT;
1570 thiz->accuracy = PROP_AVBR_ACCURACY_DEFAULT;
1571 thiz->convergence = PROP_AVBR_ACCURACY_DEFAULT;
1572 thiz->lookahead_depth = PROP_RC_LOOKAHEAD_DEPTH_DEFAULT;
1573 thiz->qpi = PROP_QPI_DEFAULT;
1574 thiz->qpp = PROP_QPP_DEFAULT;
1575 thiz->qpb = PROP_QPB_DEFAULT;
1576 thiz->gop_size = PROP_GOP_SIZE_DEFAULT;
1577 thiz->ref_frames = PROP_REF_FRAMES_DEFAULT;
1578 thiz->i_frames = PROP_I_FRAMES_DEFAULT;
1579 thiz->b_frames = PROP_B_FRAMES_DEFAULT;
1580 thiz->num_slices = PROP_NUM_SLICES_DEFAULT;
1581 thiz->mbbrc = PROP_MBBRC_DEFAULT;
1582 thiz->adaptive_i = PROP_ADAPTIVE_I_DEFAULT;
1583 thiz->adaptive_b = PROP_ADAPTIVE_B_DEFAULT;
1586 /* gst_msdkenc_set_common_property:
1588 * This is a helper function to set the common property
1589 * of base encoder from subclass implementation.
1592 gst_msdkenc_set_common_property (GObject * object, guint prop_id,
1593 const GValue * value, GParamSpec * pspec)
1595 GstMsdkEnc *thiz = GST_MSDKENC (object);
1597 gboolean ret = TRUE;
1599 GST_OBJECT_LOCK (thiz);
1601 state = GST_STATE (thiz);
1602 if ((state != GST_STATE_READY && state != GST_STATE_NULL) &&
1603 !(pspec->flags & GST_PARAM_MUTABLE_PLAYING)) {
1609 case GST_MSDKENC_PROP_HARDWARE:
1610 thiz->hardware = g_value_get_boolean (value);
1612 case GST_MSDKENC_PROP_ASYNC_DEPTH:
1613 thiz->async_depth = g_value_get_uint (value);
1615 case GST_MSDKENC_PROP_TARGET_USAGE:
1616 thiz->target_usage = g_value_get_uint (value);
1618 case GST_MSDKENC_PROP_RATE_CONTROL:
1619 thiz->rate_control = g_value_get_enum (value);
1621 case GST_MSDKENC_PROP_BITRATE:
1622 thiz->bitrate = g_value_get_uint (value);
1623 thiz->reconfig = TRUE;
1625 case GST_MSDKENC_PROP_MAX_FRAME_SIZE:
1626 thiz->max_frame_size = g_value_get_uint (value);
1628 case GST_MSDKENC_PROP_MAX_VBV_BITRATE:
1629 thiz->max_vbv_bitrate = g_value_get_uint (value);
1631 case GST_MSDKENC_PROP_AVBR_ACCURACY:
1632 thiz->accuracy = g_value_get_uint (value);
1634 case GST_MSDKENC_PROP_AVBR_CONVERGENCE:
1635 thiz->convergence = g_value_get_uint (value);
1637 case GST_MSDKENC_PROP_RC_LOOKAHEAD_DEPTH:
1638 thiz->lookahead_depth = g_value_get_uint (value);
1640 case GST_MSDKENC_PROP_QPI:
1641 thiz->qpi = g_value_get_uint (value);
1643 case GST_MSDKENC_PROP_QPP:
1644 thiz->qpp = g_value_get_uint (value);
1646 case GST_MSDKENC_PROP_QPB:
1647 thiz->qpb = g_value_get_uint (value);
1649 case GST_MSDKENC_PROP_GOP_SIZE:
1650 thiz->gop_size = g_value_get_uint (value);
1652 case GST_MSDKENC_PROP_REF_FRAMES:
1653 thiz->ref_frames = g_value_get_uint (value);
1655 case GST_MSDKENC_PROP_I_FRAMES:
1656 thiz->i_frames = g_value_get_uint (value);
1658 case GST_MSDKENC_PROP_B_FRAMES:
1659 thiz->b_frames = g_value_get_uint (value);
1661 case GST_MSDKENC_PROP_NUM_SLICES:
1662 thiz->num_slices = g_value_get_uint (value);
1664 case GST_MSDKENC_PROP_MBBRC:
1665 thiz->mbbrc = g_value_get_enum (value);
1667 case GST_MSDKENC_PROP_ADAPTIVE_I:
1668 thiz->adaptive_i = g_value_get_enum (value);
1670 case GST_MSDKENC_PROP_ADAPTIVE_B:
1671 thiz->adaptive_b = g_value_get_enum (value);
1677 GST_OBJECT_UNLOCK (thiz);
1683 GST_WARNING_OBJECT (thiz, "setting property in wrong state");
1684 GST_OBJECT_UNLOCK (thiz);
1689 /* gst_msdkenc_get_common_property:
1691 * This is a helper function to get the common property
1692 * of base encoder from subclass implementation.
1695 gst_msdkenc_get_common_property (GObject * object, guint prop_id,
1696 GValue * value, GParamSpec * pspec)
1698 GstMsdkEnc *thiz = GST_MSDKENC (object);
1699 gboolean ret = TRUE;
1701 GST_OBJECT_LOCK (thiz);
1703 case GST_MSDKENC_PROP_HARDWARE:
1704 g_value_set_boolean (value, thiz->hardware);
1706 case GST_MSDKENC_PROP_ASYNC_DEPTH:
1707 g_value_set_uint (value, thiz->async_depth);
1709 case GST_MSDKENC_PROP_TARGET_USAGE:
1710 g_value_set_uint (value, thiz->target_usage);
1712 case GST_MSDKENC_PROP_RATE_CONTROL:
1713 g_value_set_enum (value, thiz->rate_control);
1715 case GST_MSDKENC_PROP_BITRATE:
1716 g_value_set_uint (value, thiz->bitrate);
1718 case GST_MSDKENC_PROP_MAX_FRAME_SIZE:
1719 g_value_set_uint (value, thiz->max_frame_size);
1721 case GST_MSDKENC_PROP_MAX_VBV_BITRATE:
1722 g_value_set_uint (value, thiz->max_vbv_bitrate);
1724 case GST_MSDKENC_PROP_AVBR_ACCURACY:
1725 g_value_set_uint (value, thiz->accuracy);
1727 case GST_MSDKENC_PROP_AVBR_CONVERGENCE:
1728 g_value_set_uint (value, thiz->convergence);
1730 case GST_MSDKENC_PROP_RC_LOOKAHEAD_DEPTH:
1731 g_value_set_uint (value, thiz->lookahead_depth);
1733 case GST_MSDKENC_PROP_QPI:
1734 g_value_set_uint (value, thiz->qpi);
1736 case GST_MSDKENC_PROP_QPP:
1737 g_value_set_uint (value, thiz->qpp);
1739 case GST_MSDKENC_PROP_QPB:
1740 g_value_set_uint (value, thiz->qpb);
1742 case GST_MSDKENC_PROP_GOP_SIZE:
1743 g_value_set_uint (value, thiz->gop_size);
1745 case GST_MSDKENC_PROP_REF_FRAMES:
1746 g_value_set_uint (value, thiz->ref_frames);
1748 case GST_MSDKENC_PROP_I_FRAMES:
1749 g_value_set_uint (value, thiz->i_frames);
1751 case GST_MSDKENC_PROP_B_FRAMES:
1752 g_value_set_uint (value, thiz->b_frames);
1754 case GST_MSDKENC_PROP_NUM_SLICES:
1755 g_value_set_uint (value, thiz->num_slices);
1757 case GST_MSDKENC_PROP_MBBRC:
1758 g_value_set_enum (value, thiz->mbbrc);
1760 case GST_MSDKENC_PROP_ADAPTIVE_I:
1761 g_value_set_enum (value, thiz->adaptive_i);
1763 case GST_MSDKENC_PROP_ADAPTIVE_B:
1764 g_value_set_enum (value, thiz->adaptive_b);
1770 GST_OBJECT_UNLOCK (thiz);
1774 /* gst_msdkenc_install_common_properties:
1775 * @thiz: a #GstMsdkEnc
1777 * This is a helper function to install common properties
1778 * of base encoder from subclass implementation.
1779 * Encoders like jpeg do't require all the common properties
1780 * and they can avoid installing it into base gobject.
1783 gst_msdkenc_install_common_properties (GstMsdkEncClass * klass)
1785 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1786 GParamSpec *obj_properties[GST_MSDKENC_PROP_MAX] = { NULL, };
1788 obj_properties[GST_MSDKENC_PROP_HARDWARE] =
1789 g_param_spec_boolean ("hardware", "Hardware", "Enable hardware encoders",
1790 PROP_HARDWARE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1792 obj_properties[GST_MSDKENC_PROP_ASYNC_DEPTH] =
1793 g_param_spec_uint ("async-depth", "Async Depth",
1794 "Depth of asynchronous pipeline",
1795 1, 20, PROP_ASYNC_DEPTH_DEFAULT,
1796 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1798 obj_properties[GST_MSDKENC_PROP_TARGET_USAGE] =
1799 g_param_spec_uint ("target-usage", "Target Usage",
1800 "1: Best quality, 4: Balanced, 7: Best speed",
1801 1, 7, PROP_TARGET_USAGE_DEFAULT,
1802 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1804 obj_properties[GST_MSDKENC_PROP_RATE_CONTROL] =
1805 g_param_spec_enum ("rate-control", "Rate Control",
1806 "Rate control method", gst_msdkenc_rate_control_get_type (),
1807 PROP_RATE_CONTROL_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1809 obj_properties[GST_MSDKENC_PROP_BITRATE] =
1810 g_param_spec_uint ("bitrate", "Bitrate", "Bitrate in kbit/sec", 1,
1811 2000 * 1024, PROP_BITRATE_DEFAULT,
1812 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_PLAYING);
1814 obj_properties[GST_MSDKENC_PROP_MAX_FRAME_SIZE] =
1815 g_param_spec_uint ("max-frame-size", "Max Frame Size",
1816 "Maximum possible size (in kb) of any compressed frames (0: auto-calculate)",
1817 0, G_MAXUINT16, PROP_MAX_FRAME_SIZE_DEFAULT,
1818 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1820 obj_properties[GST_MSDKENC_PROP_MAX_VBV_BITRATE] =
1821 g_param_spec_uint ("max-vbv-bitrate", "Max VBV Bitrate",
1822 "Maximum bitrate(kbit/sec) at which data enters Video Buffering Verifier (0: auto-calculate)",
1823 0, G_MAXUINT16, PROP_MAX_VBV_BITRATE_DEFAULT,
1824 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1826 obj_properties[GST_MSDKENC_PROP_AVBR_ACCURACY] =
1827 g_param_spec_uint ("accuracy", "Accuracy", "The AVBR Accuracy in "
1828 "the unit of tenth of percent", 0, G_MAXUINT16,
1829 PROP_AVBR_ACCURACY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1831 obj_properties[GST_MSDKENC_PROP_AVBR_CONVERGENCE] =
1832 g_param_spec_uint ("convergence", "Convergence",
1833 "The AVBR Convergence in the unit of 100 frames", 0, G_MAXUINT16,
1834 PROP_AVBR_CONVERGENCE_DEFAULT,
1835 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1837 obj_properties[GST_MSDKENC_PROP_RC_LOOKAHEAD_DEPTH] =
1838 g_param_spec_uint ("rc-lookahead", "Look-ahead depth",
1839 "Number of frames to look ahead for Rate control", 10, 100,
1840 PROP_RC_LOOKAHEAD_DEPTH_DEFAULT,
1841 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1843 obj_properties[GST_MSDKENC_PROP_QPI] =
1844 g_param_spec_uint ("qpi", "QPI",
1845 "Constant quantizer for I frames (0 unlimited). Also used as "
1846 "ICQQuality or QVBRQuality for different RateControl methods",
1847 0, 51, PROP_QPI_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1849 obj_properties[GST_MSDKENC_PROP_QPP] =
1850 g_param_spec_uint ("qpp", "QPP",
1851 "Constant quantizer for P frames (0 unlimited)",
1852 0, 51, PROP_QPP_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1854 obj_properties[GST_MSDKENC_PROP_QPB] =
1855 g_param_spec_uint ("qpb", "QPB",
1856 "Constant quantizer for B frames (0 unlimited)",
1857 0, 51, PROP_QPB_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1859 obj_properties[GST_MSDKENC_PROP_GOP_SIZE] =
1860 g_param_spec_uint ("gop-size", "GOP Size", "GOP Size", 0,
1861 G_MAXINT, PROP_GOP_SIZE_DEFAULT,
1862 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1864 obj_properties[GST_MSDKENC_PROP_REF_FRAMES] =
1865 g_param_spec_uint ("ref-frames", "Reference Frames",
1866 "Number of reference frames",
1867 0, G_MAXINT, PROP_REF_FRAMES_DEFAULT,
1868 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1870 obj_properties[GST_MSDKENC_PROP_I_FRAMES] =
1871 g_param_spec_uint ("i-frames", "I Frames",
1872 "Number of I frames between IDR frames",
1873 0, G_MAXINT, PROP_I_FRAMES_DEFAULT,
1874 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1876 obj_properties[GST_MSDKENC_PROP_B_FRAMES] =
1877 g_param_spec_uint ("b-frames", "B Frames",
1878 "Number of B frames between I and P frames",
1879 0, G_MAXINT, PROP_B_FRAMES_DEFAULT,
1880 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1882 obj_properties[GST_MSDKENC_PROP_NUM_SLICES] =
1883 g_param_spec_uint ("num-slices", "Number of Slices",
1884 "Number of slices per frame, Zero tells the encoder to "
1885 "choose any slice partitioning allowed by the codec standard",
1886 0, G_MAXINT, PROP_NUM_SLICES_DEFAULT,
1887 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1889 obj_properties[GST_MSDKENC_PROP_MBBRC] =
1890 g_param_spec_enum ("mbbrc", "MB level bitrate control",
1891 "Macroblock level bitrate control",
1892 gst_msdkenc_mbbrc_get_type (),
1893 PROP_MBBRC_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1895 obj_properties[GST_MSDKENC_PROP_ADAPTIVE_I] =
1896 g_param_spec_enum ("i-adapt", "Adaptive I-Frame Insertion",
1897 "Adaptive I-Frame Insertion control",
1898 gst_msdkenc_adaptive_i_get_type (),
1899 PROP_ADAPTIVE_I_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1901 obj_properties[GST_MSDKENC_PROP_ADAPTIVE_B] =
1902 g_param_spec_enum ("b-adapt", "Adaptive B-Frame Insertion",
1903 "Adaptive B-Frame Insertion control",
1904 gst_msdkenc_adaptive_b_get_type (),
1905 PROP_ADAPTIVE_B_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1907 g_object_class_install_properties (gobject_class,
1908 GST_MSDKENC_PROP_MAX, obj_properties);