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