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