From 499d515a9f7211d61155ff312023d00cf93c0c40 Mon Sep 17 00:00:00 2001 From: Sreerenj Balachandran Date: Sat, 24 Aug 2013 00:46:38 +0300 Subject: [PATCH] webp: Add WebP image decoder plugin https://bugzilla.gnome.org/show_bug.cgi?id=706285 --- configure.ac | 12 ++ ext/Makefile.am | 11 +- ext/webp/Makefile.am | 17 ++ ext/webp/gstwebp.c | 42 ++++ ext/webp/gstwebpdec.c | 466 ++++++++++++++++++++++++++++++++++++++++++ ext/webp/gstwebpdec.h | 74 +++++++ 6 files changed, 620 insertions(+), 2 deletions(-) create mode 100644 ext/webp/Makefile.am create mode 100644 ext/webp/gstwebp.c create mode 100644 ext/webp/gstwebpdec.c create mode 100644 ext/webp/gstwebpdec.h diff --git a/configure.ac b/configure.ac index 7e3bca2dea..fbf8f655b8 100644 --- a/configure.ac +++ b/configure.ac @@ -1223,6 +1223,16 @@ AG_GST_CHECK_FEATURE(WAYLAND, [wayland sink], wayland , [ ]) ]) +dnl **** WebP **** +translit(dnm, m, l) AM_CONDITIONAL(USE_WEBP, true) +AG_GST_CHECK_FEATURE(WEBP, [WebP], webp , [ + PKG_CHECK_MODULES(WEBP, libwebp >= 0.2.1, [ + HAVE_WEBP="yes" ], [ HAVE_WEBP="no" + ]) + AC_SUBST(WEBP_CFLAGS) + AC_SUBST(WEBP_LIBS) +]) + dnl *** Daala *** translit(dnm, m, l) AM_CONDITIONAL(USE_DAALA, true) AG_GST_CHECK_FEATURE(DAALA, [daala], daala, [ @@ -2239,6 +2249,7 @@ AM_CONDITIONAL(USE_RTMP, false) AM_CONDITIONAL(USE_TELETEXTDEC, false) AM_CONDITIONAL(USE_SNDIO, false) AM_CONDITIONAL(USE_UVCH264, false) +AM_CONDITIONAL(USE_WEBP, false) fi dnl of EXT plugins @@ -2498,6 +2509,7 @@ ext/gsettings/Makefile ext/gsettings/org.freedesktop.gstreamer.default-elements.gschema.xml ext/spc/Makefile ext/timidity/Makefile +ext/webp/Makefile ext/xvid/Makefile ext/zbar/Makefile po/Makefile.in diff --git a/ext/Makefile.am b/ext/Makefile.am index e13ce6a24c..8be0ea7e77 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -376,6 +376,11 @@ else HLS_DIR = endif +if USE_WEBP +WEBP_DIR=webp +else +WEBP_DIR= +endif SUBDIRS=\ $(VOAACENC_DIR) \ @@ -439,7 +444,8 @@ SUBDIRS=\ $(XVID_DIR) \ $(ZBAR_DIR) \ $(RTMP_DIR) \ - $(HLS_DIR) + $(HLS_DIR) \ + $(WEBP_DIR) DIST_SUBDIRS = \ assrender \ @@ -499,6 +505,7 @@ DIST_SUBDIRS = \ voamrwbenc \ xvid \ zbar \ - rtmp + rtmp \ + webp include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/ext/webp/Makefile.am b/ext/webp/Makefile.am new file mode 100644 index 0000000000..25c35571ea --- /dev/null +++ b/ext/webp/Makefile.am @@ -0,0 +1,17 @@ +plugin_LTLIBRARIES = libgstwebp.la + +noinst_HEADERS = gstwebpdec.h + +libgstwebp_la_SOURCES = gstwebp.c \ + gstwebpdec.c + +libgstwebp_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(WEBP_CFLAGS) +libgstwebp_la_LIBADD = \ + $(GST_PLUGINS_BASE_LIBS) \ + -lgstvideo-$(GST_API_VERSION) \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) \ + $(WEBP_LIBS) +libgstwebp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstwebp_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) + diff --git a/ext/webp/gstwebp.c b/ext/webp/gstwebp.c new file mode 100644 index 0000000000..d0c18311d0 --- /dev/null +++ b/ext/webp/gstwebp.c @@ -0,0 +1,42 @@ +/* GStreamer + * Copyright (C) <2013> Sreerenj Balachandran + * Copyright (C) <2013> Intel Corporation + * + * 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 +#endif + +#include + +#include + +#include "gstwebpdec.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_webp_dec_register (plugin); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + webp, + "WebP plugin", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/webp/gstwebpdec.c b/ext/webp/gstwebpdec.c new file mode 100644 index 0000000000..4acf96ce8e --- /dev/null +++ b/ext/webp/gstwebpdec.c @@ -0,0 +1,466 @@ +/* GStreamer + * Copyright (C) <2013> Sreerenj Balachandran + * Copyright (C) <2013> Intel Corporation + * + * 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 + +#include "gstwebpdec.h" + +#define MIN_WIDTH 1 +#define MAX_WIDTH 16383 +#define MIN_HEIGHT 1 +#define MAX_HEIGHT 16383 + +enum +{ + PROP_0, + PROP_BYPASS_FILTERING, + PROP_NO_FANCY_UPSAMPLING, + PROP_USE_THREADS +}; + +static GstStaticPadTemplate gst_webp_dec_sink_pad_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/webp") + ); + +/*Fixme: Add YUV support */ +static GstStaticPadTemplate gst_webp_dec_src_pad_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE + ("{ RGB, RGBA, BGR, BGRA, ARGB, RGB16}")) + ); + +GST_DEBUG_CATEGORY_STATIC (webp_dec_debug); +#define GST_CAT_DEFAULT webp_dec_debug + +static void gst_webp_dec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_webp_dec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_webp_dec_start (GstVideoDecoder * bdec); +static gboolean gst_webp_dec_stop (GstVideoDecoder * bdec); +static gboolean gst_webp_dec_set_format (GstVideoDecoder * dec, + GstVideoCodecState * state); +static GstFlowReturn gst_webp_dec_parse (GstVideoDecoder * bdec, + GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos); +static GstFlowReturn gst_webp_dec_handle_frame (GstVideoDecoder * bdec, + GstVideoCodecFrame * frame); +static gboolean gst_webp_dec_decide_allocation (GstVideoDecoder * bdec, + GstQuery * query); + +static gboolean gst_webp_dec_reset_frame (GstWebPDec * webpdec); + +#define gst_webp_dec_parent_class parent_class +G_DEFINE_TYPE (GstWebPDec, gst_webp_dec, GST_TYPE_VIDEO_DECODER); + +static void +gst_webp_dec_class_init (GstWebPDecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *element_class; + GstVideoDecoderClass *vdec_class; + + gobject_class = (GObjectClass *) klass; + element_class = (GstElementClass *) klass; + vdec_class = (GstVideoDecoderClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_webp_dec_set_property; + gobject_class->get_property = gst_webp_dec_get_property; + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_webp_dec_src_pad_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_webp_dec_sink_pad_template)); + gst_element_class_set_static_metadata (element_class, "WebP image decoder", + "Codec/Decoder/Image", + "Decode images from WebP format", + "Sreerenj Balachandran "); + + g_object_class_install_property (gobject_class, PROP_BYPASS_FILTERING, + g_param_spec_boolean ("bypass-filtering", "Bypass Filtering", + "When enabled, skip the in-loop filtering", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_NO_FANCY_UPSAMPLING, + g_param_spec_boolean ("no-fancy-upsampling", "No Fancy Upsampling", + "When enabled, use faster pointwise upsampler", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_USE_THREADS, + g_param_spec_boolean ("use-threads", "Use Threads", + "When enabled, use multi-threaded decoding", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + vdec_class->start = gst_webp_dec_start; + vdec_class->stop = gst_webp_dec_stop; + vdec_class->parse = gst_webp_dec_parse; + vdec_class->set_format = gst_webp_dec_set_format; + vdec_class->handle_frame = gst_webp_dec_handle_frame; + vdec_class->decide_allocation = gst_webp_dec_decide_allocation; + + GST_DEBUG_CATEGORY_INIT (webp_dec_debug, "webpdec", 0, "WebP decoder"); +} + +static void +gst_webp_dec_init (GstWebPDec * dec) +{ + GST_DEBUG ("Initialize the webp decoder"); + + memset (&dec->config, 0, sizeof (dec->config)); + dec->saw_header = FALSE; + + dec->bypass_filtering = FALSE; + dec->no_fancy_upsampling = FALSE; + dec->use_threads = FALSE; +} + +static gboolean +gst_webp_dec_reset_frame (GstWebPDec * webpdec) +{ + GST_DEBUG ("Reset the current frame properties"); + + webpdec->saw_header = FALSE; + + if (!WebPInitDecoderConfig (&webpdec->config)) { + GST_WARNING_OBJECT (webpdec, + "Failed to configure the WebP image decoding libraray"); + return FALSE; + } + return TRUE; +} + +static void +gst_webp_dec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstWebPDec *dec; + + dec = GST_WEBP_DEC (object); + + switch (prop_id) { + case PROP_BYPASS_FILTERING: + dec->bypass_filtering = g_value_get_boolean (value); + break; + case PROP_NO_FANCY_UPSAMPLING: + dec->no_fancy_upsampling = g_value_get_boolean (value); + break; + case PROP_USE_THREADS: + dec->use_threads = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_webp_dec_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstWebPDec *dec; + + dec = GST_WEBP_DEC (object); + + switch (prop_id) { + case PROP_BYPASS_FILTERING: + g_value_set_boolean (value, dec->bypass_filtering); + break; + case PROP_NO_FANCY_UPSAMPLING: + g_value_set_boolean (value, dec->no_fancy_upsampling); + break; + case PROP_USE_THREADS: + g_value_set_boolean (value, dec->use_threads); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_webp_dec_start (GstVideoDecoder * decoder) +{ + GstWebPDec *webpdec = (GstWebPDec *) decoder; + + gst_video_decoder_set_packetized (GST_VIDEO_DECODER (webpdec), FALSE); + + return gst_webp_dec_reset_frame (webpdec); +} + +static gboolean +gst_webp_dec_stop (GstVideoDecoder * bdec) +{ + GstWebPDec *webpdec = (GstWebPDec *) bdec; + + if (webpdec->input_state) { + gst_video_codec_state_unref (webpdec->input_state); + webpdec->input_state = NULL; + } + if (webpdec->output_state) { + gst_video_codec_state_unref (webpdec->output_state); + webpdec->output_state = NULL; + } + return TRUE; +} + +static gboolean +gst_webp_dec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state) +{ + GstWebPDec *webpdec = (GstWebPDec *) decoder; + GstVideoInfo *info = &state->info; + + if (webpdec->input_state) + gst_video_codec_state_unref (webpdec->input_state); + webpdec->input_state = gst_video_codec_state_ref (state); + + if (GST_VIDEO_INFO_FPS_N (info) != 1 && GST_VIDEO_INFO_FPS_D (info) != 1) + gst_video_decoder_set_packetized (decoder, TRUE); + else + gst_video_decoder_set_packetized (decoder, FALSE); + + return TRUE; +} + +static gboolean +gst_webp_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) +{ + GstBufferPool *pool = NULL; + GstStructure *config; + + if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (bdec, query)) + return FALSE; + + if (gst_query_get_n_allocation_pools (query) > 0) + gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL); + + if (pool == NULL) + return FALSE; + + config = gst_buffer_pool_get_config (pool); + if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) { + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_META); + } + gst_buffer_pool_set_config (pool, config); + gst_object_unref (pool); + + return TRUE; +} + +static GstFlowReturn +gst_webp_dec_parse (GstVideoDecoder * decoder, GstVideoCodecFrame * frame, + GstAdapter * adapter, gboolean at_eos) +{ + gsize toadd = 0; + gsize size; + gconstpointer data; + GstByteReader reader; + GstWebPDec *webpdec = (GstWebPDec *) decoder; + + size = gst_adapter_available (adapter); + GST_DEBUG_OBJECT (decoder, "parsing webp image data (%u bytes)", size); + + if (at_eos) { + GST_DEBUG ("Flushing all data out"); + toadd = size; + + /* If we have leftover data, throw it away */ + if (!webpdec->saw_header) + goto drop_frame; + goto have_full_frame; + } + + if (!webpdec->saw_header) { + guint32 code; + + if (size < 12) + goto need_more_data; + + data = gst_adapter_map (adapter, size); + gst_byte_reader_init (&reader, data, size); + + if (!gst_byte_reader_get_uint32_le (&reader, &code)) + goto error; + + if (code == GST_MAKE_FOURCC ('R', 'I', 'F', 'F')) { + if (!gst_byte_reader_get_uint32_le (&reader, &webpdec->frame_size)) + goto error; + + if (!gst_byte_reader_get_uint32_le (&reader, &code)) + goto error; + + if (code == GST_MAKE_FOURCC ('W', 'E', 'B', 'P')) + webpdec->saw_header = TRUE; + + } + } + + if (!webpdec->saw_header) + goto error; + + if (size >= (webpdec->frame_size + 8)) { + toadd = webpdec->frame_size + 8; + webpdec->saw_header = FALSE; + goto have_full_frame; + } + +need_more_data: + return GST_VIDEO_DECODER_FLOW_NEED_DATA; + +have_full_frame: + if (toadd) + gst_video_decoder_add_to_frame (decoder, toadd); + return gst_video_decoder_have_frame (decoder); + +drop_frame: + gst_adapter_flush (adapter, size); + return GST_FLOW_OK; + +error: + g_assert_not_reached (); + return GST_FLOW_ERROR; +} + +static GstFlowReturn +gst_webp_dec_update_src_caps (GstWebPDec * dec, GstMapInfo * map_info) +{ + WebPBitstreamFeatures features; + GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN; + + if (WebPGetFeatures (map_info->data, map_info->size, + &features) != VP8_STATUS_OK) { + GST_ERROR_OBJECT (dec, "Failed to execute WebPGetFeatures"); + return GST_FLOW_ERROR; + } + + if (features.width < MIN_WIDTH || features.width > MAX_WIDTH + || features.height < MIN_HEIGHT || features.height > MAX_HEIGHT) { + GST_ERROR_OBJECT (dec, "Dimensions of the frame is unspported by libwebp"); + return GST_FLOW_ERROR; + } + /*Fixme: Add support for other formats */ + if (features.has_alpha) { + format = GST_VIDEO_FORMAT_ARGB; + dec->colorspace = MODE_ARGB; + } else { + format = GST_VIDEO_FORMAT_RGB; + dec->colorspace = MODE_RGB; + } + + /* Check if output state changed */ + if (dec->output_state) { + GstVideoInfo *info = &dec->output_state->info; + + if (features.width == GST_VIDEO_INFO_WIDTH (info) && + features.height == GST_VIDEO_INFO_HEIGHT (info) && + GST_VIDEO_INFO_FORMAT (info) == format) { + goto beach; + } + gst_video_codec_state_unref (dec->output_state); + } + + dec->output_state = + gst_video_decoder_set_output_state (GST_VIDEO_DECODER (dec), format, + features.width, features.height, dec->input_state); + + gst_video_decoder_negotiate (GST_VIDEO_DECODER (dec)); +beach: + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_webp_dec_handle_frame (GstVideoDecoder * decoder, + GstVideoCodecFrame * frame) +{ + GstWebPDec *webpdec = (GstWebPDec *) decoder; + GstMapInfo map_info; + GstFlowReturn ret = GST_FLOW_OK; + GstVideoFrame vframe; + + gst_buffer_map (frame->input_buffer, &map_info, GST_MAP_READ); + + ret = gst_webp_dec_update_src_caps (webpdec, &map_info); + if (ret != GST_FLOW_OK) + goto done; + + ret = gst_video_decoder_allocate_output_frame (decoder, frame); + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + GST_ERROR_OBJECT (decoder, "failed to allocate output frame"); + ret = GST_FLOW_ERROR; + goto done; + } + + if (!gst_video_frame_map (&vframe, &webpdec->output_state->info, + frame->output_buffer, GST_MAP_READWRITE)) { + GST_ERROR_OBJECT (decoder, "Failed to map output videoframe"); + ret = GST_FLOW_ERROR; + goto done; + } + + /* configure output buffer parameteres */ + webpdec->config.options.bypass_filtering = webpdec->bypass_filtering; + webpdec->config.options.no_fancy_upsampling = webpdec->no_fancy_upsampling; + webpdec->config.options.use_threads = webpdec->use_threads; + webpdec->config.output.colorspace = webpdec->colorspace; + webpdec->config.output.u.RGBA.rgba = (uint8_t *) vframe.map[0].data; + webpdec->config.output.u.RGBA.stride = + GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0); + webpdec->config.output.u.RGBA.size = GST_VIDEO_FRAME_SIZE (&vframe); + webpdec->config.output.is_external_memory = 1; + + if (WebPDecode (map_info.data, map_info.size, + &webpdec->config) != VP8_STATUS_OK) { + GST_ERROR_OBJECT (decoder, "Failed to decode the webp frame"); + ret = GST_FLOW_ERROR; + goto done; + } + + gst_video_frame_unmap (&vframe); + gst_buffer_unmap (frame->input_buffer, &map_info); + + ret = gst_video_decoder_finish_frame (decoder, frame); + + if (!gst_webp_dec_reset_frame (webpdec)) { + ret = GST_FLOW_ERROR; + goto done; + } + +done: + return ret; +} + +gboolean +gst_webp_dec_register (GstPlugin * plugin) +{ + return gst_element_register (plugin, "webpdec", + GST_RANK_PRIMARY, GST_TYPE_WEBP_DEC); +} diff --git a/ext/webp/gstwebpdec.h b/ext/webp/gstwebpdec.h new file mode 100644 index 0000000000..bf2586e906 --- /dev/null +++ b/ext/webp/gstwebpdec.h @@ -0,0 +1,74 @@ +/* GStreamer + * Copyright (C) <2013> Sreerenj Balachandran + * Copyright (C) <2013> Intel Corporation + * + * 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_WEBP_DEC_H__ +#define __GST_WEBP_DEC_H__ + +#include +#include +#include +#include +#include + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_WEBP_DEC \ + (gst_webp_dec_get_type()) +#define GST_WEBP_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_WEBP_DEC,GstWebPDec)) +#define GST_WEBP_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_WEBP_DEC,GstWebPDecClass)) +#define GST_IS_WEBP_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_WEBP_DEC)) +#define GST_IS_WEBP_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_WEBP_DEC)) + +typedef struct _GstWebPDec GstWebPDec; +typedef struct _GstWebPDecClass GstWebPDecClass; + +struct _GstWebPDec { + GstVideoDecoder decoder; + + GstVideoCodecState *input_state; + GstVideoCodecState *output_state; + + gboolean saw_header; + guint frame_size; + + /* properties */ + gboolean bypass_filtering; + gboolean no_fancy_upsampling; + gboolean use_threads; + + WEBP_CSP_MODE colorspace; + WebPDecoderConfig config; +}; + +struct _GstWebPDecClass { + GstVideoDecoderClass decoder_class; +}; + +GType gst_webp_dec_get_type (void); +gboolean gst_webp_dec_register (GstPlugin * plugin); + +#endif /* __GST_WEBP_DEC_H__ */