• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2021> Collabora Ltd.
3  *   Author: Daniel Almeida <daniel.almeida@collabora.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <gst/pbutils/pbutils.h>
26 
27 #include "gstv4l2codecalphadecodebin.h"
28 #include "gstv4l2decoder.h"
29 
30 GST_DEBUG_CATEGORY_STATIC (v4l2_codecalphadecodebin_debug);
31 #define GST_CAT_DEFAULT (v4l2_codecalphadecodebin_debug)
32 
33 typedef struct
34 {
35   GstBin parent;
36 
37   gboolean constructed;
38   const gchar *missing_element;
39 } GstV4l2CodecAlphaDecodeBinPrivate;
40 
41 #define gst_v4l2_codec_alpha_decode_bin_parent_class parent_class
42 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstV4l2CodecAlphaDecodeBin,
43     gst_v4l2_codec_alpha_decode_bin, GST_TYPE_BIN,
44     G_ADD_PRIVATE (GstV4l2CodecAlphaDecodeBin);
45     GST_DEBUG_CATEGORY_INIT (v4l2_codecalphadecodebin_debug,
46         "v4l2codecs-alphadecodebin", 0, "V4L2 stateless alpha decode bin"));
47 
48 
49 static GstStaticPadTemplate gst_alpha_decode_bin_src_template =
50 GST_STATIC_PAD_TEMPLATE ("src",
51     GST_PAD_SRC,
52     GST_PAD_ALWAYS,
53     GST_STATIC_CAPS ("ANY")
54     );
55 
56 static gboolean
gst_v4l2_codec_alpha_decode_bin_open(GstV4l2CodecAlphaDecodeBin * self)57 gst_v4l2_codec_alpha_decode_bin_open (GstV4l2CodecAlphaDecodeBin * self)
58 {
59   GstV4l2CodecAlphaDecodeBinPrivate *priv =
60       gst_v4l2_codec_alpha_decode_bin_get_instance_private (self);
61 
62   if (priv->missing_element) {
63     gst_element_post_message (GST_ELEMENT (self),
64         gst_missing_element_message_new (GST_ELEMENT (self),
65             priv->missing_element));
66   } else if (!priv->constructed) {
67     GST_ELEMENT_ERROR (self, CORE, FAILED,
68         ("Failed to construct alpha decoder pipeline."), (NULL));
69   }
70 
71   return priv->constructed;
72 }
73 
74 static GstStateChangeReturn
gst_v4l2_codec_alpha_decode_bin_change_state(GstElement * element,GstStateChange transition)75 gst_v4l2_codec_alpha_decode_bin_change_state (GstElement * element,
76     GstStateChange transition)
77 {
78   GstV4l2CodecAlphaDecodeBin *self = GST_V4L2_CODEC_ALPHA_DECODE_BIN (element);
79 
80   switch (transition) {
81     case GST_STATE_CHANGE_NULL_TO_READY:
82       if (!gst_v4l2_codec_alpha_decode_bin_open (self))
83         return GST_STATE_CHANGE_FAILURE;
84       break;
85     default:
86       break;
87   }
88 
89   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
90 }
91 
92 static void
gst_v4l2_codec_alpha_decode_bin_constructed(GObject * obj)93 gst_v4l2_codec_alpha_decode_bin_constructed (GObject * obj)
94 {
95   GstV4l2CodecAlphaDecodeBin *self = GST_V4L2_CODEC_ALPHA_DECODE_BIN (obj);
96   GstV4l2CodecAlphaDecodeBinPrivate *priv =
97       gst_v4l2_codec_alpha_decode_bin_get_instance_private (self);
98   GstV4l2CodecAlphaDecodeBinClass *klass =
99       GST_V4L2_CODEC_ALPHA_DECODE_BIN_GET_CLASS (self);
100   GstPad *src_gpad, *sink_gpad;
101   GstPad *src_pad = NULL, *sink_pad = NULL;
102   GstElement *alphademux = NULL;
103   GstElement *queue = NULL;
104   GstElement *alpha_queue = NULL;
105   GstElement *decoder = NULL;
106   GstElement *alpha_decoder = NULL;
107   GstElement *alphacombine = NULL;
108 
109   /* setup ghost pads */
110   sink_gpad = gst_ghost_pad_new_no_target_from_template ("sink",
111       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink"));
112   gst_element_add_pad (GST_ELEMENT (self), sink_gpad);
113 
114   src_gpad = gst_ghost_pad_new_no_target_from_template ("src",
115       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src"));
116   gst_element_add_pad (GST_ELEMENT (self), src_gpad);
117 
118   /* create elements */
119   alphademux = gst_element_factory_make ("codecalphademux", NULL);
120   if (!alphademux) {
121     priv->missing_element = "codecalphademux";
122     goto cleanup;
123   }
124 
125   queue = gst_element_factory_make ("queue", NULL);
126   alpha_queue = gst_element_factory_make ("queue", NULL);
127   if (!queue || !alpha_queue) {
128     priv->missing_element = "queue";
129     goto cleanup;
130   }
131 
132   decoder = gst_element_factory_make (klass->decoder_name, "maindec");
133   if (!decoder) {
134     priv->missing_element = klass->decoder_name;
135     goto cleanup;
136   }
137 
138   alpha_decoder = gst_element_factory_make (klass->decoder_name, "alphadec");
139   if (!alpha_decoder) {
140     priv->missing_element = klass->decoder_name;
141     goto cleanup;
142   }
143 
144   /* We disable QoS on decoders because we need to maintain frame pairing in
145    * order for alphacombine to work. */
146   g_object_set (decoder, "qos", FALSE, NULL);
147   g_object_set (alpha_decoder, "qos", FALSE, NULL);
148 
149   alphacombine = gst_element_factory_make ("alphacombine", NULL);
150   if (!alphacombine) {
151     priv->missing_element = "alphacombine";
152     goto cleanup;
153   }
154 
155   gst_bin_add_many (GST_BIN (self), alphademux, queue, alpha_queue, decoder,
156       alpha_decoder, alphacombine, NULL);
157 
158   /* link elements */
159   sink_pad = gst_element_get_static_pad (alphademux, "sink");
160   gst_ghost_pad_set_target (GST_GHOST_PAD (sink_gpad), sink_pad);
161   gst_clear_object (&sink_pad);
162 
163   gst_element_link_pads (alphademux, "src", queue, "sink");
164   gst_element_link_pads (queue, "src", decoder, "sink");
165   gst_element_link_pads (decoder, "src", alphacombine, "sink");
166 
167   gst_element_link_pads (alphademux, "alpha", alpha_queue, "sink");
168   gst_element_link_pads (alpha_queue, "src", alpha_decoder, "sink");
169   gst_element_link_pads (alpha_decoder, "src", alphacombine, "alpha");
170 
171   src_pad = gst_element_get_static_pad (alphacombine, "src");
172   gst_ghost_pad_set_target (GST_GHOST_PAD (src_gpad), src_pad);
173   gst_object_unref (src_pad);
174 
175   g_object_set (queue, "max-size-bytes", 0, "max-size-time", 0,
176       "max-size-buffers", 1, NULL);
177   g_object_set (alpha_queue, "max-size-bytes", 0, "max-size-time", 0,
178       "max-size-buffers", 1, NULL);
179 
180   /* signal success, we will handle this in NULL->READY transition */
181   priv->constructed = TRUE;
182   return;
183 
184 cleanup:
185   gst_clear_object (&alphademux);
186   gst_clear_object (&queue);
187   gst_clear_object (&alpha_queue);
188   gst_clear_object (&decoder);
189   gst_clear_object (&alpha_decoder);
190   gst_clear_object (&alphacombine);
191 
192   G_OBJECT_CLASS (parent_class)->constructed (obj);
193 }
194 
195 static void
gst_v4l2_codec_alpha_decode_bin_class_init(GstV4l2CodecAlphaDecodeBinClass * klass)196 gst_v4l2_codec_alpha_decode_bin_class_init (GstV4l2CodecAlphaDecodeBinClass *
197     klass)
198 {
199   GstElementClass *element_class = (GstElementClass *) klass;
200   GObjectClass *obj_class = (GObjectClass *) klass;
201 
202   /* This is needed to access the subclass class instance, otherwise we cannot
203    * read the class parameters */
204   obj_class->constructed = gst_v4l2_codec_alpha_decode_bin_constructed;
205 
206   gst_element_class_add_static_pad_template (element_class,
207       &gst_alpha_decode_bin_src_template);
208   element_class->change_state =
209       GST_DEBUG_FUNCPTR (gst_v4l2_codec_alpha_decode_bin_change_state);
210 
211   /* let's make the doc generator happy */
212   gst_type_mark_as_plugin_api (GST_TYPE_V4L2_CODEC_ALPHA_DECODE_BIN, 0);
213 }
214 
215 static void
gst_v4l2_codec_alpha_decode_bin_init(GstV4l2CodecAlphaDecodeBin * self)216 gst_v4l2_codec_alpha_decode_bin_init (GstV4l2CodecAlphaDecodeBin * self)
217 {
218 }
219 
220 void
gst_v4l2_codec_alpha_decode_bin_register(GstPlugin * plugin,GClassInitFunc class_init,gconstpointer class_data,const gchar * element_name_tmpl,GstV4l2CodecDevice * device,guint rank)221 gst_v4l2_codec_alpha_decode_bin_register (GstPlugin * plugin,
222     GClassInitFunc class_init, gconstpointer class_data,
223     const gchar * element_name_tmpl, GstV4l2CodecDevice * device, guint rank)
224 {
225   /* TODO check that we have compatible src format */
226 
227   gst_v4l2_decoder_register (plugin,
228       GST_TYPE_V4L2_CODEC_ALPHA_DECODE_BIN, class_init, class_data, NULL,
229       element_name_tmpl, device,
230       rank + GST_V4L2_CODEC_ALPHA_DECODE_BIN_RANK_OFFSET, NULL);
231 }
232