From fffee978c2f850a1a08454ed27c960ff3c6f3a2c Mon Sep 17 00:00:00 2001 From: Aaron Boxer Date: Wed, 1 Jun 2016 19:02:33 -0400 Subject: [PATCH] jpeg2000parse: Add JPEG2000 parser element https://bugzilla.gnome.org/show_bug.cgi?id=766236 --- .../plugins/gst-plugins-bad-plugins.hierarchy | 1 + .../inspect/plugin-videoparsersbad.xml | 21 + gst/videoparsers/Makefile.am | 2 + gst/videoparsers/gstjpeg2000parse.c | 402 ++++++++++++++++++ gst/videoparsers/gstjpeg2000parse.h | 66 +++ gst/videoparsers/gstjpeg2000sampling.h | 16 + gst/videoparsers/plugin.c | 3 + 7 files changed, 511 insertions(+) create mode 100644 gst/videoparsers/gstjpeg2000parse.c create mode 100644 gst/videoparsers/gstjpeg2000parse.h diff --git a/docs/plugins/gst-plugins-bad-plugins.hierarchy b/docs/plugins/gst-plugins-bad-plugins.hierarchy index fc7db6b719..6f57b8f742 100644 --- a/docs/plugins/gst-plugins-bad-plugins.hierarchy +++ b/docs/plugins/gst-plugins-bad-plugins.hierarchy @@ -66,6 +66,7 @@ GObject GstMpegvParse GstOpusParse GstPngParse + GstJPEG2000Parse GstVC1Parse GstBaseSink GstAudioBaseSink diff --git a/docs/plugins/inspect/plugin-videoparsersbad.xml b/docs/plugins/inspect/plugin-videoparsersbad.xml index 03a7b8a7a6..abc3c9fb53 100644 --- a/docs/plugins/inspect/plugin-videoparsersbad.xml +++ b/docs/plugins/inspect/plugin-videoparsersbad.xml @@ -156,6 +156,27 @@ + + jpeg2000parse + JPEG 2000 parser + Codec/Parser/Video/Image + Parses JPEG 2000 files + Aaron Boxer <boxerab@gmail.com> + + + sink + sink + always +
image/x-jpc
+
+ + src + source + always +
image/x-jpc, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], parsed=(boolean)true
+
+
+
vc1parse VC1 parser diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index 03d72040d5..588c78137c 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -5,6 +5,7 @@ libgstvideoparsersbad_la_SOURCES = plugin.c \ gstdiracparse.c dirac_parse.c \ gsth264parse.c gstmpegvideoparse.c \ gstmpeg4videoparse.c \ + gstjpeg2000parse.c \ gstpngparse.c \ gstvc1parse.c \ gsth265parse.c @@ -29,6 +30,7 @@ noinst_HEADERS = gsth263parse.h h263parse.h \ gstdiracparse.h dirac_parse.h \ gsth264parse.h gstmpegvideoparse.h \ gstmpeg4videoparse.h \ + gstjpeg2000parse.h \ gstjpeg2000sampling.h \ gstpngparse.h \ gstvc1parse.h \ diff --git a/gst/videoparsers/gstjpeg2000parse.c b/gst/videoparsers/gstjpeg2000parse.c new file mode 100644 index 0000000000..cabe6d09f1 --- /dev/null +++ b/gst/videoparsers/gstjpeg2000parse.c @@ -0,0 +1,402 @@ +/* GStreamer JPEG 2000 Parser + * Copyright (C) <2016> Grok Image Compession Inc. + * @author Aaron Boxer + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstjpeg2000parse.h" +#include + +/* SOC marker plus minimum size of SIZ marker */ +#define GST_JPEG2000_PARSE_MIN_FRAME_SIZE (4+36) +#define GST_JPEG2000_PARSE_J2K_MAGIC 0xFF4FFF51 +#define GST_JPEG2000_PARSE_SIZE_OF_J2K_MAGIC 4 + +GST_DEBUG_CATEGORY (jpeg2000_parse_debug); +#define GST_CAT_DEFAULT jpeg2000_parse_debug + +static GstStaticPadTemplate srctemplate = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/x-jpc," + " width = (int)[1, MAX], height = (int)[1, MAX]," + "colorspace = (string) { sRGB, sYUV, GRAY }," "parsed = (boolean) true") + ); + +static GstStaticPadTemplate sinktemplate = +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/x-jpc," + "colorspace = (string) { sRGB, sYUV, GRAY }") + ); + +#define parent_class gst_jpeg2000_parse_parent_class +G_DEFINE_TYPE (GstJPEG2000Parse, gst_jpeg2000_parse, GST_TYPE_BASE_PARSE); + +static gboolean gst_jpeg2000_parse_start (GstBaseParse * parse); +static gboolean gst_jpeg2000_parse_event (GstBaseParse * parse, + GstEvent * event); +static GstFlowReturn gst_jpeg2000_parse_handle_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, gint * skipsize); + +static void +gst_jpeg2000_parse_class_init (GstJPEG2000ParseClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass); + + GST_DEBUG_CATEGORY_INIT (jpeg2000_parse_debug, "jpeg2000parse", 0, + "jpeg 2000 parser"); + + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); + gst_element_class_set_static_metadata (gstelement_class, "JPEG 2000 parser", + "Codec/Parser/Video/Image", + "Parses JPEG 2000 files", "Aaron Boxer "); + + /* Override BaseParse vfuncs */ + parse_class->start = GST_DEBUG_FUNCPTR (gst_jpeg2000_parse_start); + parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_jpeg2000_parse_event); + parse_class->handle_frame = + GST_DEBUG_FUNCPTR (gst_jpeg2000_parse_handle_frame); +} + +static void +gst_jpeg2000_parse_init (GstJPEG2000Parse * jpeg2000parse) +{ + GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (jpeg2000parse)); + GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (jpeg2000parse)); +} + +static gboolean +gst_jpeg2000_parse_start (GstBaseParse * parse) +{ + GstJPEG2000Parse *jpeg2000parse = GST_JPEG2000_PARSE (parse); + guint i; + GST_DEBUG_OBJECT (jpeg2000parse, "start"); + gst_base_parse_set_min_frame_size (parse, GST_JPEG2000_PARSE_MIN_FRAME_SIZE); + + jpeg2000parse->width = 0; + jpeg2000parse->height = 0; + + for (i = 0; i < GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS; ++i) { + jpeg2000parse->dx[i] = 0; + jpeg2000parse->dy[i] = 0; + } + + jpeg2000parse->sampling = GST_RTP_SAMPLING_NONE; + return TRUE; +} + +static gboolean +gst_jpeg2000_parse_event (GstBaseParse * parse, GstEvent * event) +{ + gboolean res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + gst_base_parse_set_min_frame_size (parse, + GST_JPEG2000_PARSE_MIN_FRAME_SIZE); + break; + default: + break; + } + return res; +} + +static GstFlowReturn +gst_jpeg2000_parse_handle_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, gint * skipsize) +{ + GstJPEG2000Parse *jpeg2000parse = GST_JPEG2000_PARSE (parse); + GstMapInfo map; + GstByteReader reader; + GstFlowReturn ret = GST_FLOW_OK; + guint eoc_offset = 0; + + GstCaps *current_caps = NULL; + GstStructure *current_caps_struct = NULL; + const gchar *colorspace = NULL; + guint x0, y0, x1, y1; + guint width, height; + gboolean dimensions_changed = FALSE; + guint8 dx[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS]; + guint8 dy[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS]; /* sub-sampling factors */ + gboolean subsampling_changed = FALSE; + guint16 numcomps; + guint16 compno; + const char *sampling = NULL; + GstRtpSampling samplingEnum = GST_RTP_SAMPLING_NONE; + guint magic_offset = 0; + + if (!gst_buffer_map (frame->buffer, &map, GST_MAP_READ)) { + GST_ERROR_OBJECT (jpeg2000parse, "Unable to map buffer"); + return GST_FLOW_ERROR; + } + + gst_byte_reader_init (&reader, map.data, map.size); + + /* skip to beginning of frame */ + magic_offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, + GST_JPEG2000_PARSE_J2K_MAGIC, 0, gst_byte_reader_get_remaining (&reader)); + + if (magic_offset == -1) { + *skipsize = + gst_byte_reader_get_size (&reader) - + GST_JPEG2000_PARSE_SIZE_OF_J2K_MAGIC; + goto beach; + } else { + GST_DEBUG_OBJECT (jpeg2000parse, "Found magic at offset = %d", + magic_offset); + if (magic_offset > 0) { + *skipsize = magic_offset; + goto beach; + } + } + + /* 2 to skip marker size, and another 2 to skip rsiz field */ + if (!gst_byte_reader_skip (&reader, + GST_JPEG2000_PARSE_SIZE_OF_J2K_MAGIC + 2 + 2)) + goto beach; + + if (!gst_byte_reader_get_uint32_be (&reader, &x1)) + goto beach; + + if (!gst_byte_reader_get_uint32_be (&reader, &y1)) + goto beach; + + if (!gst_byte_reader_get_uint32_be (&reader, &x0)) + goto beach; + + if (!gst_byte_reader_get_uint32_be (&reader, &y0)) + goto beach; + + /* sanity check on image dimensions */ + if (x1 < x0 || y1 < y0) { + GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL, + ("Nonsensical image dimensions %d,%d,%d,%d", x0, y0, x1, y1)); + ret = GST_FLOW_NOT_NEGOTIATED; + goto beach; + } + + width = x1 - x0; + height = y1 - y0; + + GST_DEBUG_OBJECT (jpeg2000parse, "Parsed image dimensions %d,%d", width, + height); + + /* skip tile dimensions */ + if (!gst_byte_reader_skip (&reader, 4 * 4)) + goto beach; + + /* read number of components */ + if (!gst_byte_reader_get_uint16_be (&reader, &numcomps)) + goto beach; + + if (numcomps > GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS) { + GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL, + ("Unsupported number of components %d", numcomps)); + ret = GST_FLOW_NOT_NEGOTIATED; + goto beach; + } + + current_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse)); + if (!current_caps) { + GST_ERROR_OBJECT (jpeg2000parse, "Unable to get current caps"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto beach; + } + + current_caps_struct = gst_caps_get_structure (current_caps, 0); + if (!current_caps_struct) { + GST_ERROR_OBJECT (jpeg2000parse, "Unable to get structure of current caps"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto beach; + } + + /* colorspace is a required field */ + colorspace = gst_structure_get_string (current_caps_struct, "colorspace"); + if (!colorspace) { + GST_ERROR_OBJECT (jpeg2000parse, "Missing color space"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto beach; + } + + for (compno = 0; compno < numcomps; ++compno) { + + /* skip Ssiz (precision and signed/unsigned bit ) */ + if (!gst_byte_reader_skip (&reader, 1)) + goto beach; + + if (!gst_byte_reader_get_uint8 (&reader, dx + compno)) + goto beach; + + if (!gst_byte_reader_get_uint8 (&reader, dy + compno)) + goto beach; + + GST_DEBUG_OBJECT (jpeg2000parse, + "Parsed sub-sampling %d,%d for component %d", dx[compno], dy[compno], + compno); + + } + + /* now we can set the dimensions and sub-sampling */ + if (width != jpeg2000parse->width || height != jpeg2000parse->height) { + dimensions_changed = TRUE; + } + jpeg2000parse->width = width; + jpeg2000parse->height = height; + + for (compno = 0; compno < numcomps; ++compno) { + if (dx[compno] != jpeg2000parse->dx[compno] + || dy[compno] != jpeg2000parse->dy[compno]) { + subsampling_changed = TRUE; + } + jpeg2000parse->dx[compno] = dx[compno]; + jpeg2000parse->dx[compno] = dy[compno]; + } + + /* we do not set sampling field for sub-sampled RGB or monochrome */ + for (compno = 0; compno < numcomps; ++compno) { + if (strcmp (colorspace, "sYUV") && (dx[compno] > 1 || dy[compno] > 1)) { + GST_WARNING_OBJECT (jpeg2000parse, + "Unable to set sampling field for sub-sampled RGB or monochrome color spaces"); + goto set_caps; + } + + } + + /* sanity check on sub-sampling */ + if (dx[1] != dx[2] || dy[1] != dy[2]) { + GST_WARNING_OBJECT (jpeg2000parse, + "Unable to set sampling field because chroma channel sub-sampling factors are not equal"); + goto set_caps; + } + + if (!strcmp (colorspace, "sYUV")) { + /* reject sub-sampled YUVA image */ + if (numcomps == 4) { + guint i; + for (i = 0; i < 4; ++i) { + if (dx[i] > 1 || dy[i] > 1) { + GST_WARNING_OBJECT (jpeg2000parse, + "Unable to set sampling field for sub-sampled YUVA images"); + goto set_caps; + } + } + + sampling = GST_RTP_J2K_YBRA; + samplingEnum = GST_RTP_SAMPLING_YBRA; + + } else if (numcomps == 3) { + /* use sub-sampling from U chroma channel */ + if (dx[1] == 1 && dy[1] == 1) { + sampling = GST_RTP_J2K_YBR444; + samplingEnum = GST_RTP_SAMPLING_YBR444; + } else if (dx[1] == 2 && dy[1] == 2) { + sampling = GST_RTP_J2K_YBR420; + samplingEnum = GST_RTP_SAMPLING_YBR420; + } else if (dx[1] == 4 && dy[1] == 2) { + sampling = GST_RTP_J2K_YBR410; + samplingEnum = GST_RTP_SAMPLING_YBR410; + } else if (dx[1] == 2 && dy[1] == 1) { + sampling = GST_RTP_J2K_YBR422; + samplingEnum = GST_RTP_SAMPLING_YBR422; + } else { + GST_WARNING_OBJECT (jpeg2000parse, + "Unable to set sampling field for sub-sampling factors %d,%d", + dx[1], dy[1]); + goto set_caps; + } + } + } else if (!strcmp (colorspace, "GRAY")) { + sampling = GST_RTP_J2K_GRAYSCALE; + samplingEnum = GST_RTP_SAMPLING_GRAYSCALE; + } else { + if (numcomps == 4) { + sampling = GST_RTP_J2K_RGBA; + samplingEnum = GST_RTP_SAMPLING_RGBA; + } else { + sampling = GST_RTP_J2K_RGB; + samplingEnum = GST_RTP_SAMPLING_RGB; + } + } + +set_caps: + + if (dimensions_changed || subsampling_changed) { + GstCaps *src_caps = NULL; + gint fr_num, fr_denom; + + src_caps = + gst_caps_new_simple (gst_structure_get_name (current_caps_struct), + "width", G_TYPE_INT, jpeg2000parse->width, "height", G_TYPE_INT, + jpeg2000parse->height, "colorspace", G_TYPE_STRING, colorspace, NULL); + + + if (sampling) { + gst_caps_set_simple (src_caps, "sampling", G_TYPE_STRING, sampling, NULL); + } + + if (gst_structure_get_fraction (current_caps_struct, "framerate", &fr_num, + &fr_denom)) { + gst_caps_set_simple (src_caps, "framerate", GST_TYPE_FRACTION, fr_num, + fr_denom, NULL); + } else { + GST_WARNING_OBJECT (jpeg2000parse, "No framerate set"); + } + + + if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), src_caps)) { + GST_ERROR_OBJECT (jpeg2000parse, "Unable to set source caps"); + ret = GST_FLOW_NOT_NEGOTIATED; + gst_caps_unref (src_caps); + goto beach; + } + + gst_caps_unref (src_caps); + jpeg2000parse->sampling = samplingEnum; + } + + /* look for EOC end of codestream marker */ + eoc_offset = gst_byte_reader_masked_scan_uint32 (&reader, 0x0000ffff, + 0xFFD9, 0, gst_byte_reader_get_remaining (&reader)); + + if (eoc_offset != -1) { + /* add 4 for eoc marker and eoc marker size */ + guint frame_size = gst_byte_reader_get_pos (&reader) + eoc_offset + 4; + GST_DEBUG_OBJECT (jpeg2000parse, + "Found EOC at offset = %d, frame size = %d", eoc_offset, frame_size); + + if (frame_size < gst_byte_reader_get_size (&reader)) + goto beach; + + gst_caps_unref (current_caps); + gst_buffer_unmap (frame->buffer, &map); + return gst_base_parse_finish_frame (parse, frame, frame_size); + } + +beach: + if (current_caps) + gst_caps_unref (current_caps); + gst_buffer_unmap (frame->buffer, &map); + return ret; + +} diff --git a/gst/videoparsers/gstjpeg2000parse.h b/gst/videoparsers/gstjpeg2000parse.h new file mode 100644 index 0000000000..e030dd6922 --- /dev/null +++ b/gst/videoparsers/gstjpeg2000parse.h @@ -0,0 +1,66 @@ +/* GStreamer JPEG 2000 Parser + * Copyright (C) <2016> Grok Image Compression Inc. + * @author Aaron Boxer + * + * 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. + */ + +#ifndef __GST_JPEG2000_PARSE_H__ +#define __GST_JPEG2000_PARSE_H__ + +#include +#include +#include +#include "gstjpeg2000sampling.h" + +G_BEGIN_DECLS +#define GST_TYPE_JPEG2000_PARSE \ + (gst_jpeg2000_parse_get_type()) +#define GST_JPEG2000_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_JPEG2000_PARSE,GstJPEG2000Parse)) +#define GST_JPEG2000_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_JPEG2000_PARSE,GstJPEG2000ParseClass)) +#define GST_IS_JPEG2000_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_JPEG2000_PARSE)) +#define GST_IS_JPEG2000_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_JPEG2000_PARSE)) + GType gst_jpeg2000_parse_get_type (void); + +typedef struct _GstJPEG2000Parse GstJPEG2000Parse; +typedef struct _GstJPEG2000ParseClass GstJPEG2000ParseClass; + +#define GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS 4 + +struct _GstJPEG2000Parse +{ + GstBaseParse baseparse; + + guint width; + guint height; + + guint8 dx[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS]; + guint8 dy[GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS]; /* subsampling factors */ + + GstRtpSampling sampling; +}; + +struct _GstJPEG2000ParseClass +{ + GstBaseParseClass parent_class; +}; + +G_END_DECLS +#endif diff --git a/gst/videoparsers/gstjpeg2000sampling.h b/gst/videoparsers/gstjpeg2000sampling.h index e6334f2759..abd4fa88ee 100644 --- a/gst/videoparsers/gstjpeg2000sampling.h +++ b/gst/videoparsers/gstjpeg2000sampling.h @@ -58,6 +58,22 @@ GRAYSCALE: basically, a single component image of just multilevels of grey. #define GST_RTP_J2K_SAMPLING_LIST "sampling = (string) {\"RGB\", \"BGR\", \"RGBA\", \"BGRA\", \"YCbCrA\", \"YCbCr-4:4:4\", \"YCbCr-4:2:2\", \"YCbCr-4:2:0\", \"YCbCr-4:1:1\", \"GRAYSCALE\"}" +typedef enum +{ + + GST_RTP_SAMPLING_NONE, + GST_RTP_SAMPLING_RGB, + GST_RTP_SAMPLING_BGR, + GST_RTP_SAMPLING_RGBA, + GST_RTP_SAMPLING_BGRA, + GST_RTP_SAMPLING_YBRA, + GST_RTP_SAMPLING_YBR444, + GST_RTP_SAMPLING_YBR422, + GST_RTP_SAMPLING_YBR420, + GST_RTP_SAMPLING_YBR410, + GST_RTP_SAMPLING_GRAYSCALE +} GstRtpSampling; + /* * GstJ2KMarker: diff --git a/gst/videoparsers/plugin.c b/gst/videoparsers/plugin.c index 79d1df65d5..2deddf4723 100644 --- a/gst/videoparsers/plugin.c +++ b/gst/videoparsers/plugin.c @@ -28,6 +28,7 @@ #include "gstmpegvideoparse.h" #include "gstmpeg4videoparse.h" #include "gstpngparse.h" +#include "gstjpeg2000parse.h" #include "gstvc1parse.h" #include "gsth265parse.h" @@ -48,6 +49,8 @@ plugin_init (GstPlugin * plugin) GST_RANK_PRIMARY + 1, GST_TYPE_MPEG4VIDEO_PARSE); ret |= gst_element_register (plugin, "pngparse", GST_RANK_PRIMARY, GST_TYPE_PNG_PARSE); + ret |= gst_element_register (plugin, "jpeg2000parse", + GST_RANK_PRIMARY, GST_TYPE_JPEG2000_PARSE); ret |= gst_element_register (plugin, "h265parse", GST_RANK_SECONDARY, GST_TYPE_H265_PARSE); ret |= gst_element_register (plugin, "vc1parse",