From a89b819191e16942a1ab144a977e2e2063c47c13 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sun, 29 Mar 2020 22:23:23 +0900 Subject: [PATCH] codecs: Add new baseclass for VP8 decoder This implemenation is similar to VP9 but much simpler than it. Part-of: --- gst-libs/gst/codecs/gstvp8decoder.c | 393 ++++++++++++++++++++++++++++ gst-libs/gst/codecs/gstvp8decoder.h | 121 +++++++++ gst-libs/gst/codecs/gstvp8picture.c | 104 ++++++++ gst-libs/gst/codecs/gstvp8picture.h | 98 +++++++ gst-libs/gst/codecs/meson.build | 8 +- 5 files changed, 723 insertions(+), 1 deletion(-) create mode 100644 gst-libs/gst/codecs/gstvp8decoder.c create mode 100644 gst-libs/gst/codecs/gstvp8decoder.h create mode 100644 gst-libs/gst/codecs/gstvp8picture.c create mode 100644 gst-libs/gst/codecs/gstvp8picture.h diff --git a/gst-libs/gst/codecs/gstvp8decoder.c b/gst-libs/gst/codecs/gstvp8decoder.c new file mode 100644 index 0000000000..b3179e23ca --- /dev/null +++ b/gst-libs/gst/codecs/gstvp8decoder.c @@ -0,0 +1,393 @@ +/* GStreamer + * Copyright (C) 2020 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:gstvp8decoder + * @title: GstVP8Decoder + * @short_description: Base class to implement stateless VP8 decoders + * @sources: + * - gstvp8picture.h + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gstvp8decoder.h" + +GST_DEBUG_CATEGORY (gst_vp8_decoder_debug); +#define GST_CAT_DEFAULT gst_vp8_decoder_debug + +struct _GstVp8DecoderPrivate +{ + gint width; + gint height; + + gboolean had_sequence; + GstVp8Parser parser; + gboolean wait_keyframe; +}; + +#define parent_class gst_vp8_decoder_parent_class +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstVp8Decoder, gst_vp8_decoder, + GST_TYPE_VIDEO_DECODER, + G_ADD_PRIVATE (GstVp8Decoder); + GST_DEBUG_CATEGORY_INIT (gst_vp8_decoder_debug, "vp8decoder", 0, + "VP8 Video Decoder")); + +static gboolean gst_vp8_decoder_start (GstVideoDecoder * decoder); +static gboolean gst_vp8_decoder_stop (GstVideoDecoder * decoder); +static gboolean gst_vp8_decoder_set_format (GstVideoDecoder * decoder, + GstVideoCodecState * state); +static GstFlowReturn gst_vp8_decoder_finish (GstVideoDecoder * decoder); +static gboolean gst_vp8_decoder_flush (GstVideoDecoder * decoder); +static GstFlowReturn gst_vp8_decoder_drain (GstVideoDecoder * decoder); +static GstFlowReturn gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder, + GstVideoCodecFrame * frame); + +static void +gst_vp8_decoder_class_init (GstVp8DecoderClass * klass) +{ + GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass); + + decoder_class->start = GST_DEBUG_FUNCPTR (gst_vp8_decoder_start); + decoder_class->stop = GST_DEBUG_FUNCPTR (gst_vp8_decoder_stop); + decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_vp8_decoder_set_format); + decoder_class->finish = GST_DEBUG_FUNCPTR (gst_vp8_decoder_finish); + decoder_class->flush = GST_DEBUG_FUNCPTR (gst_vp8_decoder_flush); + decoder_class->drain = GST_DEBUG_FUNCPTR (gst_vp8_decoder_drain); + decoder_class->handle_frame = + GST_DEBUG_FUNCPTR (gst_vp8_decoder_handle_frame); +} + +static void +gst_vp8_decoder_init (GstVp8Decoder * self) +{ + gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE); + + self->priv = gst_vp8_decoder_get_instance_private (self); +} + +static gboolean +gst_vp8_decoder_start (GstVideoDecoder * decoder) +{ + GstVp8Decoder *self = GST_VP8_DECODER (decoder); + GstVp8DecoderPrivate *priv = self->priv; + + gst_vp8_parser_init (&priv->parser); + priv->wait_keyframe = TRUE; + + return TRUE; +} + +static void +gst_vp8_decoder_reset (GstVp8Decoder * self) +{ + GstVp8DecoderPrivate *priv = self->priv; + + gst_vp8_picture_clear (&self->last_picture); + gst_vp8_picture_clear (&self->golden_ref_picture); + gst_vp8_picture_clear (&self->alt_ref_picture); + + priv->wait_keyframe = TRUE; +} + +static gboolean +gst_vp8_decoder_stop (GstVideoDecoder * decoder) +{ + GstVp8Decoder *self = GST_VP8_DECODER (decoder); + + if (self->input_state) { + gst_video_codec_state_unref (self->input_state); + self->input_state = NULL; + } + + gst_vp8_decoder_reset (self); + + return TRUE; +} + +static gboolean +gst_vp8_decoder_check_codec_change (GstVp8Decoder * self, + const GstVp8FrameHdr * frame_hdr) +{ + GstVp8DecoderPrivate *priv = self->priv; + gboolean ret = TRUE; + gboolean changed = FALSE; + + if (priv->width != frame_hdr->width || priv->height != frame_hdr->height) { + GST_INFO_OBJECT (self, "resolution changed %dx%d", frame_hdr->width, + frame_hdr->height); + priv->width = frame_hdr->width; + priv->height = frame_hdr->height; + changed = TRUE; + } + + if (changed || !priv->had_sequence) { + GstVp8DecoderClass *klass = GST_VP8_DECODER_GET_CLASS (self); + + priv->had_sequence = TRUE; + + if (klass->new_sequence) + ret = klass->new_sequence (self, frame_hdr); + } + + return ret; +} + +static gboolean +gst_vp8_decoder_set_format (GstVideoDecoder * decoder, + GstVideoCodecState * state) +{ + GstVp8Decoder *self = GST_VP8_DECODER (decoder); + GstVp8DecoderPrivate *priv = self->priv; + + GST_DEBUG_OBJECT (decoder, "Set format"); + + if (self->input_state) + gst_video_codec_state_unref (self->input_state); + + self->input_state = gst_video_codec_state_ref (state); + + priv->width = GST_VIDEO_INFO_WIDTH (&state->info); + priv->height = GST_VIDEO_INFO_HEIGHT (&state->info); + + return TRUE; +} + +static gboolean +gst_vp8_decoder_update_reference (GstVp8Decoder * self, GstVp8Picture * picture) +{ + GstVp8FrameHdr *frame_hdr = &picture->frame_hdr; + + if (frame_hdr->key_frame) { + gst_vp8_picture_replace (&self->last_picture, picture); + gst_vp8_picture_replace (&self->golden_ref_picture, picture); + gst_vp8_picture_replace (&self->alt_ref_picture, picture); + + goto done; + } + + if (frame_hdr->refresh_alternate_frame) { + gst_vp8_picture_replace (&self->alt_ref_picture, picture); + } else { + switch (frame_hdr->copy_buffer_to_alternate) { + case 0: + /* do nothing */ + break; + case 1: + gst_vp8_picture_replace (&self->alt_ref_picture, self->last_picture); + break; + case 2: + gst_vp8_picture_replace (&self->alt_ref_picture, + self->golden_ref_picture); + break; + default: + GST_WARNING_OBJECT (self, "unrecognized copy_buffer_to_alternate %d", + frame_hdr->copy_buffer_to_alternate); + break; + } + } + + if (frame_hdr->refresh_golden_frame) { + gst_vp8_picture_replace (&self->golden_ref_picture, picture); + } else { + switch (frame_hdr->copy_buffer_to_golden) { + case 0: + /* do nothing */ + break; + case 1: + gst_vp8_picture_replace (&self->golden_ref_picture, self->last_picture); + break; + case 2: + gst_vp8_picture_replace (&self->golden_ref_picture, + self->alt_ref_picture); + break; + default: + GST_WARNING_OBJECT (self, "unrecognized copy_buffer_to_golden %d", + frame_hdr->copy_buffer_to_alternate); + break; + } + } + + if (frame_hdr->refresh_last) + gst_vp8_picture_replace (&self->last_picture, picture); + +done: + gst_vp8_picture_unref (picture); + + return TRUE; +} + +static GstFlowReturn +gst_vp8_decoder_finish (GstVideoDecoder * decoder) +{ + GstVp8Decoder *self = GST_VP8_DECODER (decoder); + + GST_DEBUG_OBJECT (self, "finish"); + + gst_vp8_decoder_reset (self); + + return GST_FLOW_OK; +} + +static gboolean +gst_vp8_decoder_flush (GstVideoDecoder * decoder) +{ + GstVp8Decoder *self = GST_VP8_DECODER (decoder); + + GST_DEBUG_OBJECT (self, "flush"); + + gst_vp8_decoder_reset (self); + + return TRUE; +} + +static GstFlowReturn +gst_vp8_decoder_drain (GstVideoDecoder * decoder) +{ + GstVp8Decoder *self = GST_VP8_DECODER (decoder); + + GST_DEBUG_OBJECT (self, "drain"); + + gst_vp8_decoder_reset (self); + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder, + GstVideoCodecFrame * frame) +{ + GstVp8Decoder *self = GST_VP8_DECODER (decoder); + GstVp8DecoderClass *klass = GST_VP8_DECODER_GET_CLASS (self); + GstVp8DecoderPrivate *priv = self->priv; + GstBuffer *in_buf = frame->input_buffer; + GstMapInfo map; + GstVp8FrameHdr frame_hdr; + GstVp8ParserResult pres; + GstVp8Picture *picture = NULL; + + GST_LOG_OBJECT (self, + "handle frame, PTS: %" GST_TIME_FORMAT ", DTS: %" + GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (in_buf)), + GST_TIME_ARGS (GST_BUFFER_DTS (in_buf))); + + if (!gst_buffer_map (in_buf, &map, GST_MAP_READ)) { + GST_ERROR_OBJECT (self, "Cannot map buffer"); + + goto error; + } + + pres = gst_vp8_parser_parse_frame_header (&priv->parser, + &frame_hdr, map.data, map.size); + + if (pres != GST_VP8_PARSER_OK) { + GST_ERROR_OBJECT (self, "Cannot parser frame header"); + + goto unmap_and_error; + } + + if (priv->wait_keyframe) { + if (!frame_hdr.key_frame) { + GST_DEBUG_OBJECT (self, "Waiting initial keyframe, drop buffer %" + GST_PTR_FORMAT, in_buf); + + gst_buffer_unmap (in_buf, &map); + gst_video_decoder_drop_frame (decoder, frame); + + return GST_FLOW_OK; + } + } + + priv->wait_keyframe = FALSE; + + if (frame_hdr.key_frame && + !gst_vp8_decoder_check_codec_change (self, &frame_hdr)) { + GST_ERROR_OBJECT (self, "Subclass cannot handle codec change"); + goto unmap_and_error; + } + + picture = gst_vp8_picture_new (); + picture->frame_hdr = frame_hdr; + picture->pts = GST_BUFFER_PTS (in_buf); + picture->data = map.data; + picture->size = map.size; + picture->system_frame_number = frame->system_frame_number; + + if (klass->new_picture) { + if (!klass->new_picture (self, picture)) { + GST_ERROR_OBJECT (self, "subclass cannot handle new picture"); + goto unmap_and_error; + } + } + + if (klass->start_picture) { + if (!klass->start_picture (self, picture)) { + GST_ERROR_OBJECT (self, "subclass cannot handle start picture"); + goto unmap_and_error; + } + } + + if (klass->decode_picture) { + if (!klass->decode_picture (self, picture, &priv->parser)) { + GST_ERROR_OBJECT (self, "subclass cannot decode current picture"); + goto unmap_and_error; + } + } + + if (klass->end_picture) { + if (!klass->end_picture (self, picture)) { + GST_ERROR_OBJECT (self, "subclass cannot handle end picture"); + goto unmap_and_error; + } + } + + gst_buffer_unmap (in_buf, &map); + + gst_video_codec_frame_set_user_data (frame, gst_vp8_picture_ref (picture), + (GDestroyNotify) gst_vp8_picture_unref); + gst_video_codec_frame_unref (frame); + + /* transfer ownership of picture */ + gst_vp8_decoder_update_reference (self, picture); + + g_assert (klass->output_picture); + return klass->output_picture (self, picture); + +unmap_and_error: + { + gst_buffer_unmap (in_buf, &map); + goto error; + } + +error: + { + GstFlowReturn ret; + + if (picture) + gst_vp8_picture_unref (picture); + + gst_video_decoder_drop_frame (decoder, frame); + GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE, + ("Failed to decode data"), (NULL), ret); + + return ret; + } +} diff --git a/gst-libs/gst/codecs/gstvp8decoder.h b/gst-libs/gst/codecs/gstvp8decoder.h new file mode 100644 index 0000000000..c229f4d723 --- /dev/null +++ b/gst-libs/gst/codecs/gstvp8decoder.h @@ -0,0 +1,121 @@ +/* GStreamer + * Copyright (C) 2020 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. + */ + +#ifndef __GST_VP8_DECODER_H__ +#define __GST_VP8_DECODER_H__ + +#include + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VP8_DECODER (gst_vp8_decoder_get_type()) +#define GST_VP8_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VP8_DECODER,GstVp8Decoder)) +#define GST_VP8_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VP8_DECODER,GstVp8DecoderClass)) +#define GST_VP8_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_VP8_DECODER,GstVp8DecoderClass)) +#define GST_IS_VP8_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VP8_DECODER)) +#define GST_IS_VP8_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VP8_DECODER)) +#define GST_VP8_DECODER_CAST(obj) ((GstVP8Decoder*)obj) + +typedef struct _GstVp8Decoder GstVp8Decoder; +typedef struct _GstVp8DecoderClass GstVp8DecoderClass; +typedef struct _GstVp8DecoderPrivate GstVp8DecoderPrivate; + +/** + * GstVp8Decoder: + * + * The opaque #GstVp8Decoder data structure. + */ +struct _GstVp8Decoder +{ + /*< private >*/ + GstVideoDecoder parent; + + /*< protected >*/ + GstVideoCodecState * input_state; + + /* reference frames */ + GstVp8Picture *last_picture; + GstVp8Picture *golden_ref_picture; + GstVp8Picture *alt_ref_picture; + + /*< private >*/ + GstVp8DecoderPrivate *priv; + gpointer padding[GST_PADDING_LARGE]; +}; + +/** + * GstVp8DecoderClass: + * @new_sequence: Notifies subclass of SPS update + * @new_picture: Optional. + * Called whenever new #GstVp8Picture is created. + * Subclass can set implementation specific user data + * on the #GstVp8Picture via gst_vp8_picture_set_user_data() + * @start_picture: Optional. + * Called per one #GstVp8Picture to notify subclass to prepare + * decoding process for the #GstVp8Picture + * @decode_slice: Provides per slice data with parsed slice header and + * required raw bitstream for subclass to decode it + * @end_picture: Optional. + * Called per one #GstVp8Picture to notify subclass to finish + * decoding process for the #GstVp8Picture + * @output_picture: Called with a #GstVp8Picture which is required to be outputted. + * Subclass can retrieve parent #GstVideoCodecFrame by using + * gst_video_decoder_get_frame() with system_frame_number + * and the #GstVideoCodecFrame must be consumed by subclass via + * gst_video_decoder_{finish,drop,release}_frame(). + */ +struct _GstVp8DecoderClass +{ + GstVideoDecoderClass parent_class; + + gboolean (*new_sequence) (GstVp8Decoder * decoder, + const GstVp8FrameHdr * frame_hdr); + + gboolean (*new_picture) (GstVp8Decoder * decoder, + GstVp8Picture * picture); + + gboolean (*start_picture) (GstVp8Decoder * decoder, + GstVp8Picture * picture); + + gboolean (*decode_picture) (GstVp8Decoder * decoder, + GstVp8Picture * picture, + GstVp8Parser * parser); + + gboolean (*end_picture) (GstVp8Decoder * decoder, + GstVp8Picture * picture); + + GstFlowReturn (*output_picture) (GstVp8Decoder * decoder, + GstVp8Picture * picture); + + /*< private >*/ + gpointer padding[GST_PADDING_LARGE]; +}; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVp8Decoder, gst_object_unref) + +GST_CODECS_API +GType gst_vp8_decoder_get_type (void); + +G_END_DECLS + +#endif /* __GST_VP8_DECODER_H__ */ diff --git a/gst-libs/gst/codecs/gstvp8picture.c b/gst-libs/gst/codecs/gstvp8picture.c new file mode 100644 index 0000000000..b40e207c2e --- /dev/null +++ b/gst-libs/gst/codecs/gstvp8picture.c @@ -0,0 +1,104 @@ +/* GStreamer + * Copyright (C) 2020 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. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gstvp8picture.h" + +GST_DEBUG_CATEGORY_EXTERN (gst_vp8_decoder_debug); +#define GST_CAT_DEFAULT gst_vp8_decoder_debug + +GST_DEFINE_MINI_OBJECT_TYPE (GstVp8Picture, gst_vp8_picture); + +static void +_gst_vp8_picture_free (GstVp8Picture * picture) +{ + GST_TRACE ("Free picture %p", picture); + + if (picture->notify) + picture->notify (picture->user_data); + + g_free (picture); +} + +/** + * gst_vp8_picture_new: + * + * Create new #GstVp8Picture + * + * Returns: a new #GstVp8Picture + */ +GstVp8Picture * +gst_vp8_picture_new (void) +{ + GstVp8Picture *pic; + + pic = g_new0 (GstVp8Picture, 1); + pic->pts = GST_CLOCK_TIME_NONE; + + gst_mini_object_init (GST_MINI_OBJECT_CAST (pic), 0, + GST_TYPE_VP8_PICTURE, NULL, NULL, + (GstMiniObjectFreeFunction) _gst_vp8_picture_free); + + GST_TRACE ("New picture %p", pic); + + return pic; +} + +/** + * gst_vp8_picture_set_user_data: + * @picture: a #GstVp8Picture + * @user_data: private data + * @notify: (closure user_data): a #GDestroyNotify + * + * Sets @user_data on the picture and the #GDestroyNotify that will be called when + * the picture is freed. + * + * If a @user_data was previously set, then the previous set @notify will be called + * before the @user_data is replaced. + */ +void +gst_vp8_picture_set_user_data (GstVp8Picture * picture, gpointer user_data, + GDestroyNotify notify) +{ + g_return_if_fail (GST_IS_VP8_PICTURE (picture)); + + if (picture->notify) + picture->notify (picture->user_data); + + picture->user_data = user_data; + picture->notify = notify; +} + +/** + * gst_vp8_picture_get_user_data: + * @picture: a #GstVp8Picture + * + * Gets private data set on the picture via + * gst_vp8_picture_set_user_data() previously. + * + * Returns: (transfer none): The previously set user_data + */ +gpointer +gst_vp8_picture_get_user_data (GstVp8Picture * picture) +{ + return picture->user_data; +} diff --git a/gst-libs/gst/codecs/gstvp8picture.h b/gst-libs/gst/codecs/gstvp8picture.h new file mode 100644 index 0000000000..5de240b180 --- /dev/null +++ b/gst-libs/gst/codecs/gstvp8picture.h @@ -0,0 +1,98 @@ +/* GStreamer + * Copyright (C) 2020 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. + */ + +#ifndef __GST_VP8_PICTURE_H__ +#define __GST_VP8_PICTURE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VP8_PICTURE (gst_vp8_picture_get_type()) +#define GST_IS_VP8_PICTURE(obj) (GST_IS_MINI_OBJECT_TYPE(obj, GST_TYPE_VP8_PICTURE)) +#define GST_VP8_PICTURE(obj) ((GstVp8Picture *)obj) +#define GST_VP8_PICTURE_CAST(obj) (GST_VP8_PICTURE(obj)) + +typedef struct _GstVp8Picture GstVp8Picture; + +struct _GstVp8Picture +{ + GstMiniObject parent; + + GstClockTime pts; + /* From GstVideoCodecFrame */ + guint32 system_frame_number; + + GstVp8FrameHdr frame_hdr; + + /* raw data and size (does not have ownership) */ + const guint8 * data; + gsize size; + + gpointer user_data; + GDestroyNotify notify; +}; + +GST_CODECS_API +GType gst_vp8_picture_get_type (void); + +GST_CODECS_API +GstVp8Picture * gst_vp8_picture_new (void); + +static inline GstVp8Picture * +gst_vp8_picture_ref (GstVp8Picture * picture) +{ + return (GstVp8Picture *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (picture)); +} + +static inline void +gst_vp8_picture_unref (GstVp8Picture * picture) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (picture)); +} + +static inline gboolean +gst_vp8_picture_replace (GstVp8Picture ** old_picture, + GstVp8Picture * new_picture) +{ + return gst_mini_object_replace ((GstMiniObject **) old_picture, + (GstMiniObject *) new_picture); +} + +static inline void +gst_vp8_picture_clear (GstVp8Picture ** picture) +{ + if (picture && *picture) { + gst_vp8_picture_unref (*picture); + *picture = NULL; + } +} + +GST_CODECS_API +void gst_vp8_picture_set_user_data (GstVp8Picture * picture, + gpointer user_data, + GDestroyNotify notify); + +GST_CODECS_API +gpointer gst_vp8_picture_get_user_data (GstVp8Picture * picture); + +G_END_DECLS + +#endif /* __GST_VP8_PICTURE_H__ */ diff --git a/gst-libs/gst/codecs/meson.build b/gst-libs/gst/codecs/meson.build index 455fafc7ba..147609012c 100644 --- a/gst-libs/gst/codecs/meson.build +++ b/gst-libs/gst/codecs/meson.build @@ -5,6 +5,8 @@ codecs_sources = files([ 'gsth265picture.c', 'gstvp9decoder.c', 'gstvp9picture.c', + 'gstvp8decoder.c', + 'gstvp8picture.c', ]) codecs_headers = [ @@ -14,6 +16,8 @@ codecs_headers = [ 'gsth265picture.h', 'gstvp9decoder.h', 'gstvp9picture.h', + 'gstvp8decoder.h', + 'gstvp8picture.h', ] cp_args = [ @@ -46,7 +50,9 @@ if build_gir extra_args : gir_init_section + ['-DGST_USE_UNSTABLE_API'] + ['--c-include=gst/codecs/gsth264decoder.h', '--c-include=gst/codecs/gsth265decoder.h', - '--c-include=gst/codecs/gstvp9decoder.h', ], + '--c-include=gst/codecs/gstvp9decoder.h', + '--c-include=gst/codecs/gstvp8decoder.h', + ], dependencies : [gstvideo_dep, gstcodecparsers_dep] ) endif -- 2.34.1