• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2021> Collabora Ltd.
3  *   Author: Nicolas Dufresne <nicolas.dufresne@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 "gstalphadecodebin.h"
28 
29 GST_DEBUG_CATEGORY_STATIC (alphadecodebin_debug);
30 #define GST_CAT_DEFAULT (alphadecodebin_debug)
31 
32 typedef struct
33 {
34   GstBin parent;
35 
36   gboolean constructed;
37   const gchar *missing_element;
38 } GstAlphaDecodeBinPrivate;
39 
40 #define gst_alpha_decode_bin_parent_class parent_class
41 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstAlphaDecodeBin, gst_alpha_decode_bin,
42     GST_TYPE_BIN,
43     G_ADD_PRIVATE (GstAlphaDecodeBin);
44     GST_DEBUG_CATEGORY_INIT (alphadecodebin_debug, "alphadecodebin", 0,
45         "alphadecodebin"));
46 
47 static GstStaticPadTemplate gst_alpha_decode_bin_src_template =
48 GST_STATIC_PAD_TEMPLATE ("src",
49     GST_PAD_SRC,
50     GST_PAD_ALWAYS,
51     GST_STATIC_CAPS ("ANY")
52     );
53 
54 static gboolean
gst_alpha_decode_bin_open(GstAlphaDecodeBin * self)55 gst_alpha_decode_bin_open (GstAlphaDecodeBin * self)
56 {
57   GstAlphaDecodeBinPrivate *priv =
58       gst_alpha_decode_bin_get_instance_private (self);
59 
60   if (priv->missing_element) {
61     gst_element_post_message (GST_ELEMENT (self),
62         gst_missing_element_message_new (GST_ELEMENT (self),
63             priv->missing_element));
64   } else if (!priv->constructed) {
65     GST_ELEMENT_ERROR (self, CORE, FAILED,
66         ("Failed to construct alpha decoder pipeline."), (NULL));
67   }
68 
69   return priv->constructed;
70 }
71 
72 static GstStateChangeReturn
gst_alpha_decode_bin_change_state(GstElement * element,GstStateChange transition)73 gst_alpha_decode_bin_change_state (GstElement * element,
74     GstStateChange transition)
75 {
76   GstAlphaDecodeBin *self = GST_ALPHA_DECODE_BIN (element);
77 
78   switch (transition) {
79     case GST_STATE_CHANGE_NULL_TO_READY:
80       if (!gst_alpha_decode_bin_open (self))
81         return GST_STATE_CHANGE_FAILURE;
82       break;
83     default:
84       break;
85   }
86 
87   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
88 }
89 
90 static void
gst_alpha_decode_bin_constructed(GObject * obj)91 gst_alpha_decode_bin_constructed (GObject * obj)
92 {
93   GstAlphaDecodeBin *self = GST_ALPHA_DECODE_BIN (obj);
94   GstAlphaDecodeBinPrivate *priv =
95       gst_alpha_decode_bin_get_instance_private (self);
96   GstAlphaDecodeBinClass *klass = GST_ALPHA_DECODE_BIN_GET_CLASS (self);
97   GstPad *src_gpad, *sink_gpad;
98   GstPad *src_pad = NULL, *sink_pad = NULL;
99   GstElement *alphademux = NULL;
100   GstElement *queue = NULL;
101   GstElement *alpha_queue = NULL;
102   GstElement *decoder = NULL;
103   GstElement *alpha_decoder = NULL;
104   GstElement *alphacombine = NULL;
105 
106   /* setup ghost pads */
107   sink_gpad = gst_ghost_pad_new_no_target_from_template ("sink",
108       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink"));
109   gst_element_add_pad (GST_ELEMENT (self), sink_gpad);
110 
111   src_gpad = gst_ghost_pad_new_no_target_from_template ("src",
112       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src"));
113   gst_element_add_pad (GST_ELEMENT (self), src_gpad);
114 
115   /* create elements */
116   alphademux = gst_element_factory_make ("codecalphademux", NULL);
117   if (!alphademux) {
118     priv->missing_element = "codecalphademux";
119     goto cleanup;
120   }
121 
122   queue = gst_element_factory_make ("queue", NULL);
123   alpha_queue = gst_element_factory_make ("queue", NULL);
124   if (!queue || !alpha_queue) {
125     priv->missing_element = "queue";
126     goto cleanup;
127   }
128 
129   decoder = gst_element_factory_make (klass->decoder_name, "maindec");
130   if (!decoder) {
131     priv->missing_element = klass->decoder_name;
132     goto cleanup;
133   }
134 
135   alpha_decoder = gst_element_factory_make (klass->decoder_name, "alphadec");
136   if (!alpha_decoder) {
137     priv->missing_element = klass->decoder_name;
138     goto cleanup;
139   }
140 
141   /* We disable QoS on decoders because we need to maintain frame pairing in
142    * order for alphacombine to work. */
143   g_object_set (decoder, "qos", FALSE, NULL);
144   g_object_set (alpha_decoder, "qos", FALSE, NULL);
145 
146   alphacombine = gst_element_factory_make ("alphacombine", NULL);
147   if (!alphacombine) {
148     priv->missing_element = "alphacombine";
149     goto cleanup;
150   }
151 
152   gst_bin_add_many (GST_BIN (self), alphademux, queue, alpha_queue, decoder,
153       alpha_decoder, alphacombine, NULL);
154 
155   /* link elements */
156   sink_pad = gst_element_get_static_pad (alphademux, "sink");
157   gst_ghost_pad_set_target (GST_GHOST_PAD (sink_gpad), sink_pad);
158   gst_clear_object (&sink_pad);
159 
160   gst_element_link_pads (alphademux, "src", queue, "sink");
161   gst_element_link_pads (queue, "src", decoder, "sink");
162   gst_element_link_pads (decoder, "src", alphacombine, "sink");
163 
164   gst_element_link_pads (alphademux, "alpha", alpha_queue, "sink");
165   gst_element_link_pads (alpha_queue, "src", alpha_decoder, "sink");
166   gst_element_link_pads (alpha_decoder, "src", alphacombine, "alpha");
167 
168   src_pad = gst_element_get_static_pad (alphacombine, "src");
169   gst_ghost_pad_set_target (GST_GHOST_PAD (src_gpad), src_pad);
170   gst_object_unref (src_pad);
171 
172   g_object_set (queue, "max-size-bytes", 0, "max-size-time", 0,
173       "max-size-buffers", 1, NULL);
174   g_object_set (alpha_queue, "max-size-bytes", 0, "max-size-time", 0,
175       "max-size-buffers", 1, NULL);
176 
177   /* signal success, we will handle this in NULL->READY transition */
178   priv->constructed = TRUE;
179   return;
180 
181 cleanup:
182   gst_clear_object (&alphademux);
183   gst_clear_object (&queue);
184   gst_clear_object (&alpha_queue);
185   gst_clear_object (&decoder);
186   gst_clear_object (&alpha_decoder);
187   gst_clear_object (&alphacombine);
188 
189   G_OBJECT_CLASS (parent_class)->constructed (obj);
190 }
191 
192 static void
gst_alpha_decode_bin_class_init(GstAlphaDecodeBinClass * klass)193 gst_alpha_decode_bin_class_init (GstAlphaDecodeBinClass * klass)
194 {
195   GstElementClass *element_class = (GstElementClass *) klass;
196   GObjectClass *obj_class = (GObjectClass *) klass;
197 
198   /* This is needed to access the subclass class instance, otherwise we cannot
199    * read the class parameters */
200   obj_class->constructed = gst_alpha_decode_bin_constructed;
201 
202   gst_element_class_add_static_pad_template (element_class,
203       &gst_alpha_decode_bin_src_template);
204   element_class->change_state =
205       GST_DEBUG_FUNCPTR (gst_alpha_decode_bin_change_state);
206 
207   /* let's make the doc generator happy */
208   gst_type_mark_as_plugin_api (GST_TYPE_ALPHA_DECODE_BIN, 0);
209 }
210 
211 static void
gst_alpha_decode_bin_init(GstAlphaDecodeBin * self)212 gst_alpha_decode_bin_init (GstAlphaDecodeBin * self)
213 {
214 }
215