From 1853dd56a42ee43b6ebb9359abe8a69a4923207f Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 3 Nov 2022 05:12:31 +0900 Subject: [PATCH] qsv: Add JPEG decoder Because DXVA does not define JPEG decoding, we need this vendor specific API for Windows Part-of: --- .../docs/plugins/gst_plugins_cache.json | 27 ++ .../sys/qsv/gstqsvallocator.cpp | 20 +- .../gst-plugins-bad/sys/qsv/gstqsvallocator.h | 1 + .../sys/qsv/gstqsvallocator_d3d11.cpp | 8 + .../gst-plugins-bad/sys/qsv/gstqsvdecoder.cpp | 54 +++- .../gst-plugins-bad/sys/qsv/gstqsvjpegdec.cpp | 303 ++++++++++++++++++ .../gst-plugins-bad/sys/qsv/gstqsvjpegdec.h | 34 ++ .../gst-plugins-bad/sys/qsv/meson.build | 1 + .../gst-plugins-bad/sys/qsv/plugin.cpp | 2 + 9 files changed, 442 insertions(+), 8 deletions(-) create mode 100644 subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegdec.cpp create mode 100644 subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegdec.h diff --git a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json index 619e4b31e0..119cc2f6c7 100644 --- a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json @@ -226060,6 +226060,33 @@ }, "rank": "none" }, + "qsvjpegdec": { + "author": "Seungha Yang ", + "description": "Intel Quick Sync Video JPEG Decoder", + "hierarchy": [ + "GstQsvJpegDec", + "GstQsvDecoder", + "GstVideoDecoder", + "GstElement", + "GstObject", + "GInitiallyUnowned", + "GObject" + ], + "klass": "Codec/Decoder/Video/Hardware", + "pad-templates": { + "sink": { + "caps": "image/jpeg:\n width: [ 1, 16384 ]\n height: [ 1, 16384 ]\n", + "direction": "sink", + "presence": "always" + }, + "src": { + "caps": "video/x-raw(memory:D3D11Memory):\n format: { NV12, YUY2, BGRA }\n width: [ 1, 16384 ]\n height: [ 1, 16384 ]\nvideo/x-raw:\n format: { NV12, YUY2, BGRA }\n width: [ 1, 16384 ]\n height: [ 1, 16384 ]\n", + "direction": "src", + "presence": "always" + } + }, + "rank": "secondary" + }, "qsvjpegenc": { "author": "Seungha Yang ", "description": "Intel Quick Sync Video JPEG Encoder", diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator.cpp index 86030f5ed6..a022719507 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator.cpp @@ -215,6 +215,12 @@ gst_qsv_allocator_alloc_default (GstQsvAllocator * self, gboolean dummy_alloc, case MFX_FOURCC_Y410: format = GST_VIDEO_FORMAT_Y410; break; + case MFX_FOURCC_YUY2: + format = GST_VIDEO_FORMAT_YUY2; + break; + case MFX_FOURCC_RGB4: + format = GST_VIDEO_FORMAT_BGRA; + break; default: /* TODO: add more formats */ break; @@ -407,6 +413,7 @@ gst_qsv_allocator_lock (mfxHDL pthis, mfxMemId mid, mfxFrameData * ptr) switch (GST_VIDEO_INFO_FORMAT (&frame->info)) { case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_P010_10LE: + case GST_VIDEO_FORMAT_P016_LE: ptr->Pitch = (mfxU16) stride; ptr->Y = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0); ptr->UV = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 1); @@ -438,6 +445,12 @@ gst_qsv_allocator_lock (mfxHDL pthis, mfxMemId mid, mfxFrameData * ptr) ptr->B = ptr->R + 2; ptr->A = ptr->R + 3; break; + case GST_VIDEO_FORMAT_YUY2: + ptr->Pitch = (mfxU16) stride; + ptr->Y = (mfxU8 *) GST_VIDEO_FRAME_PLANE_DATA (&frame->frame, 0); + ptr->U = ptr->Y + 1; + ptr->V = ptr->Y + 3; + break; default: break; } @@ -485,10 +498,8 @@ gst_qsv_allocator_get_hdl (mfxHDL pthis, mfxMemId mid, mfxHDL * handle) GstQsvFrame *frame = GST_QSV_FRAME_CAST (mid); GstMapInfo map_info; - if (!GST_QSV_MEM_TYPE_IS_VIDEO (frame->mem_type)) { - GST_ERROR_OBJECT (self, "Unexpected call"); + if (!GST_QSV_MEM_TYPE_IS_VIDEO (frame->mem_type)) return MFX_ERR_UNSUPPORTED; - } g_mutex_lock (&frame->lock); if (!frame->buffer) { @@ -673,7 +684,8 @@ gst_qsv_allocator_acquire_frame (GstQsvAllocator * allocator, if ((mem_type & GST_QSV_ENCODER_IN_MEMORY) != 0) { map_flags |= GST_MAP_READ; - } else if ((mem_type & GST_QSV_DECODER_OUT_MEMORY) != 0) { + } else if ((mem_type & GST_QSV_DECODER_OUT_MEMORY) != 0 || + (mem_type & GST_QSV_PROCESS_TARGET) != 0) { map_flags |= GST_MAP_WRITE; } else { GST_ERROR_OBJECT (allocator, diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator.h index fc1e68e73f..10227fa3af 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator.h +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator.h @@ -73,6 +73,7 @@ typedef enum GST_QSV_VIDEO_MEMORY = (1 << 1), GST_QSV_ENCODER_IN_MEMORY = (1 << 2), GST_QSV_DECODER_OUT_MEMORY = (1 << 3), + GST_QSV_PROCESS_TARGET = (1 << 4), } GstQsvMemoryType; #define GST_QSV_MEM_TYPE_IS_SYSTEM(type) ((type & GST_QSV_SYSTEM_MEMORY) != 0) diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.cpp index fa94e2f3d0..d70077dd22 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvallocator_d3d11.cpp @@ -121,6 +121,9 @@ gst_qsv_d3d11_allocator_alloc (GstQsvAllocator * allocator, case MFX_FOURCC_BGR4: dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM; break; + case MFX_FOURCC_YUY2: + dxgi_format = DXGI_FORMAT_YUY2; + break; default: /* TODO: add more formats */ break; @@ -191,6 +194,11 @@ gst_qsv_d3d11_allocator_alloc (GstQsvAllocator * allocator, mem_type |= GST_QSV_DECODER_OUT_MEMORY; } + if ((request->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) != 0) { + bind_flags |= D3D11_BIND_RENDER_TARGET; + mem_type |= GST_QSV_PROCESS_TARGET; + } + if (mem_type == GST_QSV_VIDEO_MEMORY) { GST_ERROR_OBJECT (self, "Unknown read/write access"); return MFX_ERR_UNSUPPORTED; diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvdecoder.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvdecoder.cpp index 2176dce30e..e737355294 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvdecoder.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvdecoder.cpp @@ -912,16 +912,33 @@ gst_qsv_decoder_prepare_d3d11_pool (GstQsvDecoder * self, GstStructure *config; GstD3D11AllocationParams *params; GstD3D11Device *device = GST_D3D11_DEVICE_CAST (priv->device); + guint bind_flags = 0; + GstD3D11Format d3d11_format; GST_DEBUG_OBJECT (self, "Use d3d11 memory pool"); priv->internal_pool = gst_d3d11_buffer_pool_new (device); config = gst_buffer_pool_get_config (priv->internal_pool); + + gst_d3d11_device_get_format (device, GST_VIDEO_INFO_FORMAT (info), + &d3d11_format); + + /* May not support DOV, specifically RGB output case */ + if ((d3d11_format.format_support[0] & + (guint) D3D11_FORMAT_SUPPORT_DECODER_OUTPUT) != 0) { + bind_flags |= D3D11_BIND_DECODER; + } else if ((d3d11_format.format_support[0] & + (guint) D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0) { + bind_flags |= D3D11_BIND_RENDER_TARGET; + } /* Bind to shader resource as well for this texture can be used * in generic pixel shader */ + if ((d3d11_format.format_support[0] & (guint) + D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) != 0) + bind_flags |= D3D11_BIND_SHADER_RESOURCE; + params = gst_d3d11_allocation_params_new (device, info, - GST_D3D11_ALLOCATION_FLAG_DEFAULT, - D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE, 0); + GST_D3D11_ALLOCATION_FLAG_DEFAULT, bind_flags, 0); gst_d3d11_allocation_params_alignment (params, align); gst_buffer_pool_config_set_d3d11_allocation_params (config, params); gst_d3d11_allocation_params_free (params); @@ -1201,10 +1218,25 @@ gst_qsv_decoder_negotiate (GstVideoDecoder * decoder) case MFX_FOURCC_P016: format = GST_VIDEO_FORMAT_P016_LE; break; + case MFX_FOURCC_RGB4: + format = GST_VIDEO_FORMAT_BGRA; + break; default: break; } + if (klass->codec_id == MFX_CODEC_JPEG) { + if (param->mfx.JPEGChromaFormat == MFX_CHROMAFORMAT_YUV422) { + format = GST_VIDEO_FORMAT_YUY2; + frame_info->FourCC = MFX_FOURCC_YUY2; + frame_info->ChromaFormat = MFX_CHROMAFORMAT_YUV422; + } else if (param->mfx.JPEGColorFormat == MFX_JPEG_COLORFORMAT_RGB) { + format = GST_VIDEO_FORMAT_BGRA; + frame_info->FourCC = MFX_FOURCC_RGB4; + frame_info->ChromaFormat = MFX_CHROMAFORMAT_YUV444; + } + } + if (format == GST_VIDEO_FORMAT_UNKNOWN) { GST_ERROR_OBJECT (self, "Unknown video format"); return FALSE; @@ -1296,17 +1328,31 @@ gst_qsv_decoder_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) /* Decoder will use internal pool to output but this pool is required for * copying in case of reverse playback */ if (use_d3d11_pool) { + guint bind_flags = 0; + GstD3D11Format d3d11_format; + d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config); if (!d3d11_params) { d3d11_params = gst_d3d11_allocation_params_new (device, &vinfo, GST_D3D11_ALLOCATION_FLAG_DEFAULT, 0, 0); } + + gst_d3d11_device_get_format (device, GST_VIDEO_INFO_FORMAT (&vinfo), + &d3d11_format); + /* Use both render target (for videoprocessor) and shader resource * for (pixel shader) bind flags for downstream to be able to use consistent * conversion path even when we copy textures */ - d3d11_params->desc[0].BindFlags |= - (D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE); + if ((d3d11_format.format_support[0] & + (guint) D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0) { + bind_flags |= D3D11_BIND_RENDER_TARGET; + } + if ((d3d11_format.format_support[0] & (guint) + D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) != 0) + bind_flags |= D3D11_BIND_SHADER_RESOURCE; + + d3d11_params->desc[0].BindFlags |= bind_flags; gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params); gst_d3d11_allocation_params_free (d3d11_params); } diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegdec.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegdec.cpp new file mode 100644 index 0000000000..7017c8730f --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegdec.cpp @@ -0,0 +1,303 @@ +/* GStreamer + * Copyright (C) 2022 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:element-qsvjpegdec + * @title: qsvjpegdec + * + * Intel Quick Sync JPEG decoder + * + * ## Example launch line + * ``` + * gst-launch-1.0 filesrc location=/path/to/jpeg/file ! parsebin ! qsvjpegdec ! videoconvert ! autovideosink + * ``` + * + * Since: 1.22 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstqsvjpegdec.h" +#include +#include +#include + +#ifdef G_OS_WIN32 +#include +#else +#include +#endif + +GST_DEBUG_CATEGORY_STATIC (gst_qsv_jpeg_dec_debug); +#define GST_CAT_DEFAULT gst_qsv_jpeg_dec_debug + +#define DOC_SINK_CAPS \ + "image/jpeg, width = (int) [ 1, 16384 ], height = (int) [ 1, 16384 ]" + +#define DOC_SRC_CAPS_COMM \ + "format = (string) { NV12, YUY2, BGRA }, " \ + "width = (int) [ 1, 16384 ], height = (int) [ 1, 16384 ]" + +#define DOC_SRC_CAPS \ + "video/x-raw(memory:D3D11Memory), " DOC_SRC_CAPS_COMM "; " \ + "video/x-raw, " DOC_SRC_CAPS_COMM + +typedef struct _GstQsvJpegDec +{ + GstQsvDecoder parent; +} GstQsvJpegDec; + +typedef struct _GstQsvJpegDecClass +{ + GstQsvDecoderClass parent_class; +} GstQsvJpegDecClass; + +static GTypeClass *parent_class = nullptr; + +#define GST_QSV_JPEG_DEC(object) ((GstQsvJpegDec *) (object)) +#define GST_QSV_JPEG_DEC_GET_CLASS(object) \ + (G_TYPE_INSTANCE_GET_CLASS ((object),G_TYPE_FROM_INSTANCE (object),GstQsvJpegDecClass)) + +static void +gst_qsv_jpeg_dec_class_init (GstQsvJpegDecClass * klass, gpointer data) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstQsvDecoderClass *qsvdec_class = GST_QSV_DECODER_CLASS (klass); + GstQsvDecoderClassData *cdata = (GstQsvDecoderClassData *) data; + GstPadTemplate *pad_templ; + GstCaps *doc_caps; + + parent_class = (GTypeClass *) g_type_class_peek_parent (klass); + +#ifdef G_OS_WIN32 + std::string long_name = "Intel Quick Sync Video " + + std::string (cdata->description) + " JPEG Decoder"; + + gst_element_class_set_metadata (element_class, long_name.c_str (), + "Codec/Decoder/Video/Hardware", + "Intel Quick Sync Video JPEG Decoder", + "Seungha Yang "); +#else + gst_element_class_set_static_metadata (element_class, + "Intel Quick Sync Video JPEG Decoder", + "Codec/Decoder/Video/Hardware", + "Intel Quick Sync Video JPEG Decoder", + "Seungha Yang "); +#endif + + pad_templ = gst_pad_template_new ("sink", + GST_PAD_SINK, GST_PAD_ALWAYS, cdata->sink_caps); + doc_caps = gst_caps_from_string (DOC_SINK_CAPS); + gst_pad_template_set_documentation_caps (pad_templ, doc_caps); + gst_caps_unref (doc_caps); + gst_element_class_add_pad_template (element_class, pad_templ); + + pad_templ = gst_pad_template_new ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, cdata->src_caps); + doc_caps = gst_caps_from_string (DOC_SRC_CAPS); + gst_pad_template_set_documentation_caps (pad_templ, doc_caps); + gst_caps_unref (doc_caps); + gst_element_class_add_pad_template (element_class, pad_templ); + + qsvdec_class->codec_id = MFX_CODEC_JPEG; + qsvdec_class->impl_index = cdata->impl_index; + qsvdec_class->adapter_luid = cdata->adapter_luid; + qsvdec_class->display_path = cdata->display_path; + + gst_caps_unref (cdata->sink_caps); + gst_caps_unref (cdata->src_caps); + g_free (cdata); +} + +static void +gst_qsv_jpeg_dec_init (GstQsvJpegDec * self) +{ +} + +void +gst_qsv_jpeg_dec_register (GstPlugin * plugin, guint rank, guint impl_index, + GstObject * device, mfxSession session) +{ + mfxVideoParam param; + mfxInfoMFX *mfx; + GstQsvResolution max_resolution; + std::vector < std::string > supported_formats; + + GST_DEBUG_CATEGORY_INIT (gst_qsv_jpeg_dec_debug, "qsvjpegdec", 0, + "qsvjpegdec"); + + memset (¶m, 0, sizeof (mfxVideoParam)); + memset (&max_resolution, 0, sizeof (GstQsvResolution)); + + param.AsyncDepth = 4; + param.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; + + mfx = ¶m.mfx; + mfx->CodecId = MFX_CODEC_JPEG; + + mfx->FrameInfo.FrameRateExtN = 30; + mfx->FrameInfo.FrameRateExtD = 1; + mfx->FrameInfo.AspectRatioW = 1; + mfx->FrameInfo.AspectRatioH = 1; + mfx->FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + mfx->FrameInfo.FourCC = MFX_FOURCC_NV12; + mfx->FrameInfo.BitDepthLuma = 8; + mfx->FrameInfo.BitDepthChroma = 8; + mfx->FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + mfx->CodecProfile = MFX_PROFILE_JPEG_BASELINE; + mfx->JPEGChromaFormat = MFX_CHROMAFORMAT_YUV420; + mfx->JPEGColorFormat = MFX_JPEG_COLORFORMAT_YCbCr; + + /* Check max-resolution */ + for (guint i = 0; i < G_N_ELEMENTS (gst_qsv_resolutions); i++) { + mfx->FrameInfo.Width = GST_ROUND_UP_16 (gst_qsv_resolutions[i].width); + mfx->FrameInfo.Height = GST_ROUND_UP_16 (gst_qsv_resolutions[i].height); + mfx->FrameInfo.CropW = gst_qsv_resolutions[i].width; + mfx->FrameInfo.CropH = gst_qsv_resolutions[i].height; + + if (MFXVideoDECODE_Query (session, ¶m, ¶m) != MFX_ERR_NONE) + break; + + max_resolution.width = gst_qsv_resolutions[i].width; + max_resolution.height = gst_qsv_resolutions[i].height; + } + + if (max_resolution.width == 0 || max_resolution.height == 0) + return; + + GST_INFO ("Maximum supported resolution: %dx%d", + max_resolution.width, max_resolution.height); + + supported_formats.push_back ("NV12"); + + mfx->FrameInfo.FourCC = MFX_FOURCC_YUY2; + mfx->FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV422; + mfx->JPEGChromaFormat = MFX_CHROMAFORMAT_YUV422; + if (MFXVideoDECODE_Query (session, ¶m, ¶m) == MFX_ERR_NONE) + supported_formats.push_back ("YUY2"); + + mfx->FrameInfo.FourCC = MFX_FOURCC_RGB4; + mfx->FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV444; + mfx->JPEGChromaFormat = MFX_CHROMAFORMAT_YUV444; + mfx->JPEGColorFormat = MFX_JPEG_COLORFORMAT_RGB; + if (MFXVideoDECODE_Query (session, ¶m, ¶m) == MFX_ERR_NONE) + supported_formats.push_back ("BGRA"); + + /* To cover both landscape and portrait, + * select max value (width in this case) */ + guint resolution = MAX (max_resolution.width, max_resolution.height); + std::string src_caps_str = "video/x-raw"; + + src_caps_str += ", width=(int) [ 1, " + std::to_string (resolution) + " ]"; + src_caps_str += ", height=(int) [ 1, " + std::to_string (resolution) + " ]"; + + /* *INDENT-OFF* */ + if (supported_formats.size () > 1) { + src_caps_str += ", format=(string) { "; + bool first = true; + for (const auto &iter: supported_formats) { + if (!first) { + src_caps_str += ", "; + } + + src_caps_str += iter; + first = false; + } + src_caps_str += " }"; + } else { + src_caps_str += ", format=(string) " + supported_formats[0]; + } + /* *INDENT-ON* */ + + GstCaps *src_caps = gst_caps_from_string (src_caps_str.c_str ()); + + /* TODO: Add support for VA */ +#ifdef G_OS_WIN32 + GstCaps *d3d11_caps = gst_caps_copy (src_caps); + GstCapsFeatures *caps_features = + gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr); + gst_caps_set_features_simple (d3d11_caps, caps_features); + gst_caps_append (d3d11_caps, src_caps); + src_caps = d3d11_caps; +#endif + std::string sink_caps_str = "image/jpeg"; + sink_caps_str += ", width=(int) [ 1, " + std::to_string (resolution) + " ]"; + sink_caps_str += ", height=(int) [ 1, " + std::to_string (resolution) + " ]"; + + GstCaps *sink_caps = gst_caps_from_string (sink_caps_str.c_str ()); + + GST_MINI_OBJECT_FLAG_SET (sink_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED); + GST_MINI_OBJECT_FLAG_SET (src_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED); + + GstQsvDecoderClassData *cdata = g_new0 (GstQsvDecoderClassData, 1); + cdata->sink_caps = sink_caps; + cdata->src_caps = src_caps; + cdata->impl_index = impl_index; + +#ifdef G_OS_WIN32 + g_object_get (device, "adapter-luid", &cdata->adapter_luid, + "description", &cdata->description, nullptr); +#else + g_object_get (device, "path", &cdata->display_path, nullptr); +#endif + + GType type; + gchar *type_name; + gchar *feature_name; + GTypeInfo type_info = { + sizeof (GstQsvJpegDecClass), + nullptr, + nullptr, + (GClassInitFunc) gst_qsv_jpeg_dec_class_init, + nullptr, + cdata, + sizeof (GstQsvJpegDec), + 0, + (GInstanceInitFunc) gst_qsv_jpeg_dec_init, + }; + + type_name = g_strdup ("GstQsvJpegDec"); + feature_name = g_strdup ("qsvjpegdec"); + + gint index = 0; + while (g_type_from_name (type_name)) { + index++; + g_free (type_name); + g_free (feature_name); + type_name = g_strdup_printf ("GstQsvJPEGDevice%dDec", index); + feature_name = g_strdup_printf ("qsvjpegdevice%ddec", index); + } + + type = g_type_register_static (GST_TYPE_QSV_DECODER, type_name, &type_info, + (GTypeFlags) 0); + + if (rank > 0 && index != 0) + rank--; + + if (index != 0) + gst_element_type_set_skip_documentation (type); + + if (!gst_element_register (plugin, feature_name, rank, type)) + GST_WARNING ("Failed to register plugin '%s'", type_name); + + g_free (type_name); + g_free (feature_name); +} diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegdec.h b/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegdec.h new file mode 100644 index 0000000000..092bb1eadc --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvjpegdec.h @@ -0,0 +1,34 @@ +/* GStreamer + * Copyright (C) 2022 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include +#include "gstqsvdecoder.h" + +G_BEGIN_DECLS + +void gst_qsv_jpeg_dec_register (GstPlugin * plugin, + guint rank, + guint impl_index, + GstObject * device, + mfxSession session); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/qsv/meson.build b/subprojects/gst-plugins-bad/sys/qsv/meson.build index ea0fc5af6a..dff24d0124 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/meson.build +++ b/subprojects/gst-plugins-bad/sys/qsv/meson.build @@ -7,6 +7,7 @@ qsv_sources = [ 'gstqsvh264enc.cpp', 'gstqsvh265dec.cpp', 'gstqsvh265enc.cpp', + 'gstqsvjpegdec.cpp', 'gstqsvjpegenc.cpp', 'gstqsvutils.cpp', 'gstqsvvp9dec.cpp', diff --git a/subprojects/gst-plugins-bad/sys/qsv/plugin.cpp b/subprojects/gst-plugins-bad/sys/qsv/plugin.cpp index 6b448fadf1..b71a01a0ff 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/plugin.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/plugin.cpp @@ -45,6 +45,7 @@ #include "gstqsvh264enc.h" #include "gstqsvh265dec.h" #include "gstqsvh265enc.h" +#include "gstqsvjpegdec.h" #include "gstqsvjpegenc.h" #include "gstqsvvp9dec.h" #include "gstqsvvp9enc.h" @@ -257,6 +258,7 @@ plugin_init (GstPlugin * plugin) gst_qsv_h264_dec_register (plugin, GST_RANK_MARGINAL, i, device, session); gst_qsv_h265_dec_register (plugin, GST_RANK_MARGINAL, i, device, session); + gst_qsv_jpeg_dec_register (plugin, GST_RANK_SECONDARY, i, device, session); gst_qsv_vp9_dec_register (plugin, GST_RANK_MARGINAL, i, device, session); gst_qsv_h264_enc_register (plugin, GST_RANK_NONE, i, device, session);