• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "config.h"
17 #include "gst_codec_bin.h"
18 #include <gst/gst.h>
19 #include "dumper.h"
20 
21 enum {
22     PROP_0,
23     PROP_TYPE,
24     PROP_USE_SOFTWARE,
25     PROP_CODER_NAME,
26     PROP_SRC,
27     PROP_SINK,
28     PROP_SRC_CONVERT,
29     PROP_SINK_CONVERT,
30     PROP_PARSER,
31     PROP_REQUEST_I_FRAME,
32     PROP_BITRATE,
33     PROP_VENDOR,
34     PROP_USE_SURFACE_INPUT,
35     PROP_USE_SURFACE_OUTPUT,
36     PROP_BITRATE_MODE,
37     PROP_CODEC_QUALITY,
38     PROP_I_FRAME_INTREVAL,
39     PROP_CODEC_PROFILE,
40 };
41 
42 #define gst_codec_bin_parent_class parent_class
43 G_DEFINE_TYPE(GstCodecBin, gst_codec_bin, GST_TYPE_BIN);
44 
45 static void gst_codec_bin_finalize(GObject *object);
46 static void gst_codec_bin_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *param_spec);
47 static void gst_codec_bin_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *param_spec);
48 static GstStateChangeReturn gst_codec_bin_change_state(GstElement *element, GstStateChange transition);
49 static void gst_codec_bin_init_config(GObjectClass *gobject_class);
50 
51 #define GST_TYPE_CODEC_BIN_TYPE (gst_codec_bin_type_get_type())
gst_codec_bin_type_get_type(void)52 static GType gst_codec_bin_type_get_type(void)
53 {
54     static GType codec_bin_type = 0;
55     static const GEnumValue bin_types[] = {
56         {CODEC_BIN_TYPE_VIDEO_DECODER, "video decoder", "video decoder"},
57         {CODEC_BIN_TYPE_VIDEO_ENCODER, "video encoder", "video encoder"},
58         {CODEC_BIN_TYPE_AUDIO_DECODER, "audio decoder", "audio decoder"},
59         {CODEC_BIN_TYPE_AUDIO_ENCODER, "audio encoder", "audio encoder"},
60         {CODEC_BIN_TYPE_UNKNOWN, "unknown", "unknown"},
61         {0, nullptr, nullptr}
62     };
63     if (!codec_bin_type) {
64         codec_bin_type = g_enum_register_static("CodecBinType", bin_types);
65     }
66     return codec_bin_type;
67 }
68 
gst_codec_bin_class_init(GstCodecBinClass * klass)69 static void gst_codec_bin_class_init(GstCodecBinClass *klass)
70 {
71     GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
72     GstElementClass *gstelement_class = GST_ELEMENT_CLASS(klass);
73     GstBinClass *gstbin_class = GST_BIN_CLASS(klass);
74 
75     g_return_if_fail(gobject_class != nullptr && gstelement_class != nullptr && gstbin_class != nullptr);
76 
77     gobject_class->finalize = gst_codec_bin_finalize;
78     gobject_class->set_property = gst_codec_bin_set_property;
79     gobject_class->get_property = gst_codec_bin_get_property;
80 
81     g_object_class_install_property(gobject_class, PROP_TYPE,
82         g_param_spec_enum("type", "CodecBin type", "Type of CodecBin",
83             GST_TYPE_CODEC_BIN_TYPE, CODEC_BIN_TYPE_UNKNOWN,
84             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
85 
86     g_object_class_install_property(gobject_class, PROP_USE_SOFTWARE,
87         g_param_spec_boolean("use-software", "Use software coder plugin", "Use software coder plugin",
88             TRUE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
89 
90     g_object_class_install_property(gobject_class, PROP_CODER_NAME,
91         g_param_spec_string("coder-name", "Name of coder", "Name of the coder plugin",
92             nullptr, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
93 
94     g_object_class_install_property(gobject_class, PROP_SRC,
95         g_param_spec_pointer("src", "Src plugin-in", "Src plugin-in",
96             (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
97 
98     g_object_class_install_property(gobject_class, PROP_SINK,
99         g_param_spec_pointer("sink", "Sink plugin-in", "Sink plugin-in",
100             (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
101 
102     g_object_class_install_property(gobject_class, PROP_SRC_CONVERT,
103         g_param_spec_boolean("src-convert", "Need src convert", "Need convert for input data",
104             FALSE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
105 
106     g_object_class_install_property(gobject_class, PROP_SINK_CONVERT,
107         g_param_spec_boolean("sink-convert", "Need sink convert", "Need convert for output data",
108             FALSE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
109 
110     g_object_class_install_property(gobject_class, PROP_PARSER,
111         g_param_spec_boolean("parser", "Need parser", "Need parser",
112             FALSE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
113 
114     g_object_class_install_property(gobject_class, PROP_REQUEST_I_FRAME,
115         g_param_spec_uint("req-i-frame", "Request I frame", "Request I frame for video encoder",
116             0, G_MAXUINT32, 0, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
117 
118     g_object_class_install_property(gobject_class, PROP_BITRATE,
119         g_param_spec_uint("bitrate", "Bitrate", "Dynamic bitrate for video encoder",
120             0, G_MAXUINT32, 0, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
121 
122     g_object_class_install_property(gobject_class, PROP_VENDOR,
123         g_param_spec_pointer("vendor", "Vendor property", "Vendor property",
124             (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
125 
126     gst_codec_bin_init_config(gobject_class);
127 
128     gst_element_class_set_static_metadata(gstelement_class,
129         "Codec Bin", "Bin/Decoder&Encoder", "Auto construct codec pipeline", "OpenHarmony");
130 
131     gstelement_class->change_state = gst_codec_bin_change_state;
132 }
133 
gst_codec_bin_init_config(GObjectClass * gobject_class)134 static void gst_codec_bin_init_config(GObjectClass *gobject_class)
135 {
136     g_object_class_install_property(gobject_class, PROP_USE_SURFACE_INPUT,
137         g_param_spec_boolean("use-surface-input", "use surface input", "The source is surface",
138             FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
139 
140     g_object_class_install_property(gobject_class, PROP_USE_SURFACE_OUTPUT,
141         g_param_spec_boolean("use-surface-output", "use surface output", "The sink is surface",
142             FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
143 
144     g_object_class_install_property(gobject_class, PROP_BITRATE_MODE,
145         g_param_spec_int("bitrate-mode", "Bitrate mode", "bitrate mode for video encoder",
146             0, G_MAXINT32, 0, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
147 
148     g_object_class_install_property(gobject_class, PROP_CODEC_QUALITY,
149         g_param_spec_int("codec-quality", "Codec quality", "Codec quality for video encoder",
150             0, G_MAXINT32, 0, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
151 
152     g_object_class_install_property(gobject_class, PROP_I_FRAME_INTREVAL,
153         g_param_spec_int("i-frame-interval", "I frame interval", "I frame interval for video encoder",
154             0, G_MAXINT32, 0, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
155 
156     g_object_class_install_property(gobject_class, PROP_CODEC_PROFILE,
157         g_param_spec_int("codec-profile", "Codec profile", "Codec profile for video encoder",
158             0, G_MAXINT32, 0, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
159 }
160 
gst_codec_bin_init(GstCodecBin * bin)161 static void gst_codec_bin_init(GstCodecBin *bin)
162 {
163     g_return_if_fail(bin != nullptr);
164     GST_INFO_OBJECT(bin, "gst_codec_bin_init");
165     bin->src = nullptr;
166     bin->parser = nullptr;
167     bin->src_convert = nullptr;
168     bin->coder = nullptr;
169     bin->sink_convert = nullptr;
170     bin->sink = nullptr;
171     bin->type = CODEC_BIN_TYPE_UNKNOWN;
172     bin->is_start = FALSE;
173     bin->use_software = FALSE;
174     bin->coder_name = nullptr;
175     bin->need_src_convert = FALSE;
176     bin->need_sink_convert = FALSE;
177     bin->need_parser = FALSE;
178     bin->is_input_surface = FALSE;
179     bin->is_output_surface = FALSE;
180     bin->bitrate_mode = -1;
181     bin->codec_quality = -1;
182     bin->i_frame_interval = -1;
183     bin->bitrate = 0;
184 }
185 
gst_codec_bin_finalize(GObject * object)186 static void gst_codec_bin_finalize(GObject *object)
187 {
188     GstCodecBin *bin = GST_CODEC_BIN(object);
189     GST_INFO_OBJECT(bin, "gst_codec_bin_finalize");
190     g_return_if_fail(bin != nullptr);
191     if (bin->coder_name != nullptr) {
192         g_free(bin->coder_name);
193         bin->coder_name = nullptr;
194     }
195     G_OBJECT_CLASS(parent_class)->finalize(object);
196 }
197 
gst_codec_bin_set_property_next(GObject * object,guint prop_id,const GValue * value,GParamSpec * param_spec)198 static void gst_codec_bin_set_property_next(GObject *object, guint prop_id,
199     const GValue *value, GParamSpec *param_spec)
200 {
201     (void)param_spec;
202     GstCodecBin *bin = GST_CODEC_BIN(object);
203     g_return_if_fail(bin != nullptr);
204     switch (prop_id) {
205         case PROP_BITRATE_MODE:
206             bin->bitrate_mode = g_value_get_int(value);
207             break;
208         case PROP_CODEC_QUALITY:
209             bin->codec_quality = g_value_get_int(value);
210             break;
211         case PROP_I_FRAME_INTREVAL:
212             bin->i_frame_interval = g_value_get_int(value);
213             break;
214         case PROP_CODEC_PROFILE:
215             bin->codec_profile = g_value_get_int(value);
216             break;
217         default:
218             break;
219     }
220 }
221 
gst_codec_bin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * param_spec)222 static void gst_codec_bin_set_property(GObject *object, guint prop_id,
223     const GValue *value, GParamSpec *param_spec)
224 {
225     GstCodecBin *bin = GST_CODEC_BIN(object);
226     g_return_if_fail(bin != nullptr);
227     switch (prop_id) {
228         case PROP_TYPE:
229             bin->type = static_cast<CodecBinType>(g_value_get_enum(value));
230             break;
231         case PROP_USE_SOFTWARE:
232             bin->use_software = g_value_get_boolean(value);
233             break;
234         case PROP_CODER_NAME:
235             bin->coder_name = g_strdup(g_value_get_string(value));
236             break;
237         case PROP_SRC:
238             bin->src = static_cast<GstElement *>(g_value_get_pointer(value));
239             break;
240         case PROP_SINK:
241             bin->sink = static_cast<GstElement *>(g_value_get_pointer(value));
242             break;
243         case PROP_SRC_CONVERT:
244             bin->need_src_convert = g_value_get_boolean(value);
245             break;
246         case PROP_SINK_CONVERT:
247             bin->need_sink_convert = g_value_get_boolean(value);
248             break;
249         case PROP_PARSER:
250             bin->need_parser = g_value_get_boolean(value);
251             break;
252         case PROP_REQUEST_I_FRAME:
253             g_return_if_fail(bin->coder != nullptr);
254             g_object_set(bin->coder, "req-i-frame", g_value_get_uint(value), nullptr);
255             break;
256         case PROP_BITRATE:
257             bin->bitrate = g_value_get_uint(value);
258             g_return_if_fail(bin->coder != nullptr);
259             g_object_set(bin->coder, "bitrate", g_value_get_uint(value), nullptr);
260             break;
261         case PROP_VENDOR:
262             g_return_if_fail(bin->coder != nullptr);
263             g_object_set(bin->coder, "vendor", g_value_get_pointer(value), nullptr);
264             break;
265         case PROP_USE_SURFACE_INPUT:
266             bin->is_input_surface = g_value_get_boolean(value);
267             break;
268         case PROP_USE_SURFACE_OUTPUT:
269             bin->is_output_surface = g_value_get_boolean(value);
270             break;
271         default:
272             break;
273     }
274     gst_codec_bin_set_property_next(object, prop_id, value, param_spec);
275 }
276 
gst_codec_bin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * param_spec)277 static void gst_codec_bin_get_property(GObject *object, guint prop_id,
278     GValue *value, GParamSpec *param_spec)
279 {
280     (void)param_spec;
281     GstCodecBin *bin = GST_CODEC_BIN(object);
282     g_return_if_fail(bin != nullptr);
283     switch (prop_id) {
284         case PROP_TYPE:
285             g_value_set_enum(value, bin->type);
286             break;
287         case PROP_USE_SOFTWARE:
288             g_value_set_boolean(value, bin->use_software);
289             break;
290         case PROP_CODER_NAME:
291             g_value_set_string(value, bin->coder_name);
292             break;
293         case PROP_SRC_CONVERT:
294             g_value_set_boolean(value, bin->need_src_convert);
295             break;
296         case PROP_SINK_CONVERT:
297             g_value_set_boolean(value, bin->need_sink_convert);
298             break;
299         default:
300             break;
301     }
302 }
303 
create_coder(GstCodecBin * bin)304 static gboolean create_coder(GstCodecBin *bin)
305 {
306     g_return_val_if_fail(bin != nullptr, FALSE);
307     g_return_val_if_fail(bin->coder_name != nullptr, FALSE);
308     g_return_val_if_fail(bin->type != CODEC_BIN_TYPE_UNKNOWN, FALSE);
309     bin->coder = gst_element_factory_make(bin->coder_name, "coder");
310     g_return_val_if_fail(bin->coder != nullptr, FALSE);
311     return TRUE;
312 }
313 
add_dump_probe(GstCodecBin * bin)314 static void add_dump_probe(GstCodecBin *bin)
315 {
316     if (!OHOS::Media::Dumper::IsEnableDumpGstBuffer()) {
317         return;
318     }
319 
320     if (bin->parser != nullptr) {
321         OHOS::Media::Dumper::AddDumpGstBufferProbe(bin->parser, "src");
322         OHOS::Media::Dumper::AddDumpGstBufferProbe(bin->parser, "sink");
323     }
324 
325     if (bin->src != nullptr) {
326         OHOS::Media::Dumper::AddDumpGstBufferProbe(bin->src, "src");
327     }
328     if (bin->sink_convert != nullptr) {
329         OHOS::Media::Dumper::AddDumpGstBufferProbe(bin->sink_convert, "src");
330         OHOS::Media::Dumper::AddDumpGstBufferProbe(bin->sink_convert, "sink");
331     }
332     if (bin->sink != nullptr) {
333         OHOS::Media::Dumper::AddDumpGstBufferProbe(bin->sink, "sink");
334     }
335 }
336 
connect_element(GstCodecBin * bin)337 static gboolean connect_element(GstCodecBin *bin)
338 {
339     g_return_val_if_fail(bin != nullptr && bin->src != nullptr, FALSE);
340     g_return_val_if_fail(bin->coder != nullptr && bin->sink != nullptr, FALSE);
341 
342     gboolean ret = FALSE;
343     if (bin->src_convert != nullptr) {
344         ret = gst_element_link_pads_full(bin->src, "src", bin->src_convert, "sink", GST_PAD_LINK_CHECK_NOTHING);
345         g_return_val_if_fail(ret == TRUE, FALSE);
346         ret = gst_element_link_pads_full(bin->src_convert, "src", bin->coder, "sink", GST_PAD_LINK_CHECK_NOTHING);
347         g_return_val_if_fail(ret == TRUE, FALSE);
348     } else if (bin->parser != nullptr) {
349         ret = gst_element_link_pads_full(bin->src, "src", bin->parser, "sink", GST_PAD_LINK_CHECK_NOTHING);
350         g_return_val_if_fail(ret == TRUE, FALSE);
351         ret = gst_element_link_pads_full(bin->parser, "src", bin->coder, "sink", GST_PAD_LINK_CHECK_NOTHING);
352         g_return_val_if_fail(ret == TRUE, FALSE);
353     } else {
354         ret = gst_element_link_pads_full(bin->src, "src", bin->coder, "sink", GST_PAD_LINK_CHECK_NOTHING);
355         g_return_val_if_fail(ret == TRUE, FALSE);
356     }
357 
358     if (bin->sink_convert != nullptr) {
359         ret = gst_element_link_pads_full(bin->coder, "src", bin->sink_convert, "sink", GST_PAD_LINK_CHECK_NOTHING);
360         g_return_val_if_fail(ret == TRUE, FALSE);
361         ret = gst_element_link_pads_full(bin->sink_convert, "src", bin->sink, "sink", GST_PAD_LINK_CHECK_NOTHING);
362         g_return_val_if_fail(ret == TRUE, FALSE);
363     } else {
364         ret = gst_element_link_pads_full(bin->coder, "src", bin->sink, "sink", GST_PAD_LINK_CHECK_NOTHING);
365         g_return_val_if_fail(ret == TRUE, FALSE);
366     }
367     GST_INFO_OBJECT(bin, "connect_element success");
368 
369     add_dump_probe(bin);
370     return TRUE;
371 }
372 
add_parser(GstCodecBin * bin)373 static gboolean add_parser(GstCodecBin *bin)
374 {
375     g_return_val_if_fail(bin != nullptr, FALSE);
376     bin->parser = gst_element_factory_make("flacparse", "parser");
377     g_return_val_if_fail(bin->parser != nullptr, FALSE);
378     return gst_bin_add(GST_BIN_CAST(bin), bin->parser);
379 }
380 
add_src_convert(GstCodecBin * bin)381 static gboolean add_src_convert(GstCodecBin *bin)
382 {
383     g_return_val_if_fail(bin != nullptr, FALSE);
384     gboolean isVideo = (bin->type == CODEC_BIN_TYPE_VIDEO_DECODER ||
385         bin->type == CODEC_BIN_TYPE_VIDEO_ENCODER) ? TRUE : FALSE;
386     if (isVideo) {
387         bin->src_convert = gst_element_factory_make("videoconvert", "src_convert");
388     } else {
389         bin->src_convert = gst_element_factory_make("audioconvert", "src_convert");
390     }
391     g_return_val_if_fail(bin->src_convert != nullptr, FALSE);
392     return gst_bin_add(GST_BIN_CAST(bin), bin->src_convert);
393 }
394 
add_sink_convert(GstCodecBin * bin)395 static gboolean add_sink_convert(GstCodecBin *bin)
396 {
397     g_return_val_if_fail(bin != nullptr, FALSE);
398     gboolean isVideo = (bin->type == CODEC_BIN_TYPE_VIDEO_DECODER ||
399         bin->type == CODEC_BIN_TYPE_VIDEO_ENCODER) ? TRUE : FALSE;
400     if (isVideo) {
401         bin->sink_convert = gst_element_factory_make("videoconvert", "sink_convert");
402     } else {
403         bin->sink_convert = gst_element_factory_make("audioconvert", "sink_convert");
404     }
405     g_return_val_if_fail(bin->sink_convert != nullptr, FALSE);
406     return gst_bin_add(GST_BIN_CAST(bin), bin->sink_convert);
407 }
408 
add_parser_if_necessary(GstCodecBin * bin)409 static gboolean add_parser_if_necessary(GstCodecBin *bin)
410 {
411     g_return_val_if_fail(bin != nullptr, FALSE);
412     if (bin->need_parser && add_parser(bin) == FALSE) {
413         GST_ERROR_OBJECT(bin, "Failed to add_parser");
414         return FALSE;
415     }
416     return TRUE;
417 }
418 
add_convert_if_necessary(GstCodecBin * bin)419 static gboolean add_convert_if_necessary(GstCodecBin *bin)
420 {
421     g_return_val_if_fail(bin != nullptr, FALSE);
422     if (bin->need_src_convert && add_src_convert(bin) == FALSE) {
423         GST_ERROR_OBJECT(bin, "Failed to add_src_convert");
424         return FALSE;
425     }
426     if (bin->need_sink_convert && add_sink_convert(bin) == FALSE) {
427         GST_ERROR_OBJECT(bin, "Failed to add_sink_convert");
428         return FALSE;
429     }
430     return TRUE;
431 }
432 
add_element_to_bin(GstCodecBin * bin)433 static gboolean add_element_to_bin(GstCodecBin *bin)
434 {
435     g_return_val_if_fail(bin != nullptr, FALSE);
436     g_return_val_if_fail(bin->src != nullptr && bin->coder != nullptr && bin->sink != nullptr, FALSE);
437 
438     gboolean ret = gst_bin_add(GST_BIN_CAST(bin), bin->src);
439     g_return_val_if_fail(ret == TRUE, FALSE);
440 
441     ret = add_parser_if_necessary(bin);
442     g_return_val_if_fail(ret == TRUE, FALSE);
443 
444     ret = add_convert_if_necessary(bin);
445     g_return_val_if_fail(ret == TRUE, FALSE);
446 
447     ret = gst_bin_add(GST_BIN_CAST(bin), bin->coder);
448     g_return_val_if_fail(ret == TRUE, FALSE);
449 
450     return gst_bin_add(GST_BIN_CAST(bin), bin->sink);
451 }
452 
operate_element(GstCodecBin * bin)453 static gboolean operate_element(GstCodecBin *bin)
454 {
455     g_return_val_if_fail(bin != nullptr, FALSE);
456     g_return_val_if_fail(bin->sink != nullptr, FALSE);
457     g_object_set(bin->sink, "sync", FALSE, nullptr);
458     if (bin->type == CODEC_BIN_TYPE_VIDEO_DECODER && bin->use_software == FALSE && bin->is_output_surface) {
459         g_object_set(bin->coder, "performance-mode", TRUE, nullptr);
460         g_object_set(bin->sink, "performance-mode", TRUE, nullptr);
461         GstCaps *caps;
462         g_object_get(bin->sink, "caps", &caps, nullptr);
463         g_object_set(bin->coder, "sink-caps", caps, nullptr);
464         gst_caps_unref(caps);
465         GstBufferPool *pool;
466         g_object_get(bin->sink, "surface-pool", &pool, nullptr);
467         g_object_set(bin->coder, "surface-pool", pool, nullptr);
468     }
469     if (bin->type == CODEC_BIN_TYPE_VIDEO_ENCODER && bin->use_software == FALSE) {
470         g_object_set(bin->coder, "enable-surface", bin->is_input_surface, nullptr);
471         g_object_set(bin->coder, "bitrate-mode", bin->bitrate_mode, nullptr);
472         g_object_set(bin->coder, "codec-quality", bin->codec_quality, nullptr);
473         g_object_set(bin->coder, "i-frame-interval-new", bin->i_frame_interval, nullptr);
474         g_object_set(bin->coder, "codec-profile", bin->codec_profile, nullptr);
475         g_object_set(bin->coder, "bitrate", bin->bitrate, nullptr);
476     }
477     return TRUE;
478 }
479 
gst_codec_bin_change_state(GstElement * element,GstStateChange transition)480 static GstStateChangeReturn gst_codec_bin_change_state(GstElement *element, GstStateChange transition)
481 {
482     GstCodecBin *bin = GST_CODEC_BIN(element);
483     g_return_val_if_fail(bin != nullptr && bin->type != CODEC_BIN_TYPE_UNKNOWN, GST_STATE_CHANGE_FAILURE);
484 
485     switch (transition) {
486         case GST_STATE_CHANGE_NULL_TO_READY:
487             if (create_coder(bin) == FALSE) {
488                 GST_ERROR_OBJECT(bin, "Failed to create_coder");
489                 return GST_STATE_CHANGE_FAILURE;
490             }
491             break;
492         case GST_STATE_CHANGE_READY_TO_PAUSED:
493             if (bin->is_start == FALSE) {
494                 if (add_element_to_bin(bin) == FALSE) {
495                     GST_ERROR_OBJECT(bin, "Failed to add_element_to_bin");
496                     return GST_STATE_CHANGE_FAILURE;
497                 }
498                 if (operate_element(bin) == FALSE) {
499                     GST_ERROR_OBJECT(bin, "Failed to operate_element");
500                     return GST_STATE_CHANGE_FAILURE;
501                 }
502                 if (connect_element(bin) == FALSE) {
503                     GST_ERROR_OBJECT(bin, "Failed to connect_element");
504                     return GST_STATE_CHANGE_FAILURE;
505                 }
506                 bin->is_start = TRUE;
507             }
508             break;
509         default:
510             break;
511     }
512     return GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
513 }
514 
plugin_init(GstPlugin * plugin)515 static gboolean plugin_init(GstPlugin *plugin)
516 {
517     g_return_val_if_fail(plugin != nullptr, FALSE);
518     return gst_element_register(plugin, "codecbin", GST_RANK_PRIMARY, GST_TYPE_CODEC_BIN);
519 }
520 
521 GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
522     GST_VERSION_MINOR,
523     _codec_bin,
524     "GStreamer Codec Bin",
525     plugin_init,
526     PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
527