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