mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-18 20:25:25 +00:00
audioparsers: port to new GstBaseParse in core
This commit is contained in:
parent
de54fa0699
commit
7a2a088c53
13 changed files with 43 additions and 40 deletions
|
@ -6,10 +6,8 @@ libgstaudioparsersbad_la_SOURCES = \
|
||||||
plugin.c
|
plugin.c
|
||||||
|
|
||||||
libgstaudioparsersbad_la_CFLAGS = \
|
libgstaudioparsersbad_la_CFLAGS = \
|
||||||
-I$(top_srcdir)/gst-libs \
|
|
||||||
$(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
|
$(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
|
||||||
libgstaudioparsersbad_la_LIBADD = \
|
libgstaudioparsersbad_la_LIBADD = \
|
||||||
$(top_builddir)/gst-libs/gst/baseparse/libgstbaseparse-$(GST_MAJORMINOR).la \
|
|
||||||
$(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) \
|
$(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) \
|
||||||
-lgstaudio-$(GST_MAJORMINOR) \
|
-lgstaudio-$(GST_MAJORMINOR) \
|
||||||
$(GST_BASE_LIBS) $(GST_LIBS)
|
$(GST_BASE_LIBS) $(GST_LIBS)
|
||||||
|
|
|
@ -267,14 +267,15 @@ gst_aacparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
|
||||||
|
|
||||||
/* arrange for metadata and get out of the way */
|
/* arrange for metadata and get out of the way */
|
||||||
gst_aacparse_set_src_caps (aacparse, caps);
|
gst_aacparse_set_src_caps (aacparse, caps);
|
||||||
gst_base_parse_set_format (parse,
|
gst_base_parse_set_passthrough (parse, TRUE);
|
||||||
GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE);
|
|
||||||
} else
|
} else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* caps info overrides */
|
/* caps info overrides */
|
||||||
gst_structure_get_int (structure, "rate", &aacparse->sample_rate);
|
gst_structure_get_int (structure, "rate", &aacparse->sample_rate);
|
||||||
gst_structure_get_int (structure, "channels", &aacparse->channels);
|
gst_structure_get_int (structure, "channels", &aacparse->channels);
|
||||||
|
} else {
|
||||||
|
gst_base_parse_set_passthrough (parse, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -460,6 +461,8 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
|
||||||
GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d, version %d",
|
GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d, version %d",
|
||||||
rate, channels, aacparse->object_type, aacparse->mpegversion);
|
rate, channels, aacparse->object_type, aacparse->mpegversion);
|
||||||
|
|
||||||
|
gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else if (need_data) {
|
} else if (need_data) {
|
||||||
/* This tells the parent class not to skip any data */
|
/* This tells the parent class not to skip any data */
|
||||||
|
@ -479,10 +482,6 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
|
||||||
aacparse->header_type = DSPAAC_HEADER_ADIF;
|
aacparse->header_type = DSPAAC_HEADER_ADIF;
|
||||||
aacparse->mpegversion = 4;
|
aacparse->mpegversion = 4;
|
||||||
|
|
||||||
/* no way to seek this */
|
|
||||||
gst_base_parse_set_seek (GST_BASE_PARSE (aacparse),
|
|
||||||
GST_BASE_PARSE_SEEK_NONE, 0);
|
|
||||||
|
|
||||||
/* Skip the "ADIF" bytes */
|
/* Skip the "ADIF" bytes */
|
||||||
adif = data + i + 4;
|
adif = data + i + 4;
|
||||||
|
|
||||||
|
@ -543,8 +542,11 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
|
||||||
/* arrange for metadata and get out of the way */
|
/* arrange for metadata and get out of the way */
|
||||||
gst_aacparse_set_src_caps (aacparse,
|
gst_aacparse_set_src_caps (aacparse,
|
||||||
GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse)));
|
GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse)));
|
||||||
gst_base_parse_set_format (GST_BASE_PARSE (aacparse),
|
|
||||||
GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE);
|
/* not syncable, not easily seekable (unless we push data from start */
|
||||||
|
gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), FALSE);
|
||||||
|
gst_base_parse_set_passthrough (GST_BASE_PARSE_CAST (aacparse), TRUE);
|
||||||
|
gst_base_parse_set_average_bitrate (GST_BASE_PARSE_CAST (aacparse), 0);
|
||||||
|
|
||||||
*framesize = avail;
|
*framesize = avail;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -574,14 +576,14 @@ gst_aacparse_check_valid_frame (GstBaseParse * parse,
|
||||||
const guint8 *data;
|
const guint8 *data;
|
||||||
GstAacParse *aacparse;
|
GstAacParse *aacparse;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
gboolean sync;
|
gboolean lost_sync;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
|
||||||
aacparse = GST_AACPARSE (parse);
|
aacparse = GST_AACPARSE (parse);
|
||||||
buffer = frame->buffer;
|
buffer = frame->buffer;
|
||||||
data = GST_BUFFER_DATA (buffer);
|
data = GST_BUFFER_DATA (buffer);
|
||||||
|
|
||||||
sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
|
||||||
|
|
||||||
if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
|
if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
|
||||||
aacparse->header_type == DSPAAC_HEADER_NONE) {
|
aacparse->header_type == DSPAAC_HEADER_NONE) {
|
||||||
|
@ -589,16 +591,16 @@ gst_aacparse_check_valid_frame (GstBaseParse * parse,
|
||||||
*framesize = GST_BUFFER_SIZE (buffer);
|
*framesize = GST_BUFFER_SIZE (buffer);
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
||||||
} else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || sync == FALSE) {
|
} else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
|
||||||
|
|
||||||
ret = gst_aacparse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer),
|
ret = gst_aacparse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer),
|
||||||
GST_BASE_PARSE_FRAME_DRAIN (frame), framesize, skipsize);
|
GST_BASE_PARSE_DRAINING (parse), framesize, skipsize);
|
||||||
|
|
||||||
} else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
} else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
||||||
guint needed_data = 1024;
|
guint needed_data = 1024;
|
||||||
|
|
||||||
ret = gst_aacparse_check_adts_frame (aacparse, data,
|
ret = gst_aacparse_check_adts_frame (aacparse, data,
|
||||||
GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_FRAME_DRAIN (frame),
|
GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_DRAINING (parse),
|
||||||
framesize, &needed_data);
|
framesize, &needed_data);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#define __GST_AACPARSE_H__
|
#define __GST_AACPARSE_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/baseparse/gstbaseparse.h>
|
#include <gst/base/gstbaseparse.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
|
@ -391,7 +391,7 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
GstBuffer *buf = frame->buffer;
|
GstBuffer *buf = frame->buffer;
|
||||||
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||||
gint off;
|
gint off;
|
||||||
gboolean sync, drain;
|
gboolean lost_sync, draining;
|
||||||
|
|
||||||
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
|
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -422,10 +422,10 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
|
|
||||||
GST_LOG_OBJECT (parse, "got frame");
|
GST_LOG_OBJECT (parse, "got frame");
|
||||||
|
|
||||||
sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
|
||||||
drain = GST_BASE_PARSE_FRAME_DRAIN (frame);
|
draining = GST_BASE_PARSE_DRAINING (parse);
|
||||||
|
|
||||||
if (!sync && !drain) {
|
if (lost_sync && !draining) {
|
||||||
guint16 word = 0;
|
guint16 word = 0;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ac3parse, "resyncing; checking next frame syncword");
|
GST_DEBUG_OBJECT (ac3parse, "resyncing; checking next frame syncword");
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#define __GST_AC3_PARSE_H__
|
#define __GST_AC3_PARSE_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/baseparse/gstbaseparse.h>
|
#include <gst/base/gstbaseparse.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
|
@ -308,7 +308,7 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse,
|
||||||
* perform this check)
|
* perform this check)
|
||||||
*/
|
*/
|
||||||
if (fsize &&
|
if (fsize &&
|
||||||
(GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame)
|
(!GST_BASE_PARSE_LOST_SYNC (parse) || GST_BASE_PARSE_DRAINING (parse)
|
||||||
|| (dsize > fsize && (data[fsize] & 0x83) == 0))) {
|
|| (dsize > fsize && (data[fsize] & 0x83) == 0))) {
|
||||||
*framesize = fsize;
|
*framesize = fsize;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#define __GST_AMRPARSE_H__
|
#define __GST_AMRPARSE_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/baseparse/gstbaseparse.h>
|
#include <gst/base/gstbaseparse.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
|
@ -322,7 +322,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16))
|
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
parser_in_sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
parser_in_sync = !GST_BASE_PARSE_LOST_SYNC (parse);
|
||||||
|
|
||||||
if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) {
|
if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) {
|
||||||
off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff,
|
off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff,
|
||||||
|
@ -362,7 +362,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
|
|
||||||
dcaparse->last_sync = sync;
|
dcaparse->last_sync = sync;
|
||||||
|
|
||||||
parser_draining = GST_BASE_PARSE_FRAME_DRAIN (frame);
|
parser_draining = GST_BASE_PARSE_DRAINING (parse);
|
||||||
|
|
||||||
if (!parser_in_sync && !parser_draining) {
|
if (!parser_in_sync && !parser_draining) {
|
||||||
/* check for second frame to be sure */
|
/* check for second frame to be sure */
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#define __GST_DCA_PARSE_H__
|
#define __GST_DCA_PARSE_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/baseparse/gstbaseparse.h>
|
#include <gst/base/gstbaseparse.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
|
@ -326,9 +326,10 @@ gst_flac_parse_start (GstBaseParse * parse)
|
||||||
|
|
||||||
/* "fLaC" marker */
|
/* "fLaC" marker */
|
||||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
|
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
|
||||||
|
|
||||||
/* inform baseclass we can come up with ts, based on counters in packets */
|
/* inform baseclass we can come up with ts, based on counters in packets */
|
||||||
gst_base_parse_set_format (GST_BASE_PARSE (flacparse),
|
gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
|
||||||
GST_BASE_PARSE_FORMAT_HAS_TIME, TRUE);
|
gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -622,7 +623,7 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For the last frame output everything to the end */
|
/* For the last frame output everything to the end */
|
||||||
if (G_UNLIKELY (GST_BASE_PARSE_FRAME_DRAIN (frame))) {
|
if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
|
||||||
if (flacparse->check_frame_checksums) {
|
if (flacparse->check_frame_checksums) {
|
||||||
guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
|
guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
|
||||||
guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
|
guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
|
||||||
|
@ -697,7 +698,7 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else {
|
} else {
|
||||||
/* If we're at EOS and the frame was not valid, drop it! */
|
/* If we're at EOS and the frame was not valid, drop it! */
|
||||||
if (G_UNLIKELY (GST_BASE_PARSE_FRAME_DRAIN (frame))) {
|
if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
|
||||||
GST_WARNING_OBJECT (flacparse, "EOS");
|
GST_WARNING_OBJECT (flacparse, "EOS");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#define __GST_FLAC_PARSE_H__
|
#define __GST_FLAC_PARSE_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/baseparse/gstbaseparse.h>
|
#include <gst/base/gstbaseparse.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
|
@ -489,7 +489,7 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
GstBuffer *buf = frame->buffer;
|
GstBuffer *buf = frame->buffer;
|
||||||
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||||
gint off, bpf;
|
gint off, bpf;
|
||||||
gboolean sync, drain, valid, caps_change;
|
gboolean lost_sync, draining, valid, caps_change;
|
||||||
guint32 header;
|
guint32 header;
|
||||||
guint bitrate, layer, rate, channels, version, mode, crc;
|
guint bitrate, layer, rate, channels, version, mode, crc;
|
||||||
|
|
||||||
|
@ -532,11 +532,11 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
else
|
else
|
||||||
caps_change = FALSE;
|
caps_change = FALSE;
|
||||||
|
|
||||||
sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
|
||||||
drain = GST_BASE_PARSE_FRAME_DRAIN (frame);
|
draining = GST_BASE_PARSE_DRAINING (parse);
|
||||||
|
|
||||||
if (!drain && (!sync || caps_change)) {
|
if (!draining && (lost_sync || caps_change)) {
|
||||||
if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, drain,
|
if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, draining,
|
||||||
&valid)) {
|
&valid)) {
|
||||||
/* not enough data */
|
/* not enough data */
|
||||||
gst_base_parse_set_min_frame_size (parse, valid);
|
gst_base_parse_set_min_frame_size (parse, valid);
|
||||||
|
@ -548,7 +548,7 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (drain && !sync && caps_change) {
|
} else if (draining && lost_sync && caps_change) {
|
||||||
/* avoid caps jitter that we can't be sure of */
|
/* avoid caps jitter that we can't be sure of */
|
||||||
*skipsize = off + 2;
|
*skipsize = off + 2;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -572,7 +572,6 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
|
||||||
GstFormat fmt = GST_FORMAT_BYTES;
|
GstFormat fmt = GST_FORMAT_BYTES;
|
||||||
guint32 read_id;
|
guint32 read_id;
|
||||||
const guint8 *data;
|
const guint8 *data;
|
||||||
GstBaseParseSeekable seekable;
|
|
||||||
guint bitrate;
|
guint bitrate;
|
||||||
|
|
||||||
if (mp3parse->sent_codec_tag)
|
if (mp3parse->sent_codec_tag)
|
||||||
|
@ -926,6 +925,8 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tell baseclass how nicely we can seek, and a bitrate if one found */
|
/* tell baseclass how nicely we can seek, and a bitrate if one found */
|
||||||
|
/* FIXME: fill index with seek table */
|
||||||
|
#if 0
|
||||||
seekable = GST_BASE_PARSE_SEEK_DEFAULT;
|
seekable = GST_BASE_PARSE_SEEK_DEFAULT;
|
||||||
if ((mp3parse->xing_flags & XING_TOC_FLAG) && mp3parse->xing_bytes &&
|
if ((mp3parse->xing_flags & XING_TOC_FLAG) && mp3parse->xing_bytes &&
|
||||||
mp3parse->xing_total_time)
|
mp3parse->xing_total_time)
|
||||||
|
@ -934,6 +935,7 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
|
||||||
if (mp3parse->vbri_seek_table && mp3parse->vbri_bytes &&
|
if (mp3parse->vbri_seek_table && mp3parse->vbri_bytes &&
|
||||||
mp3parse->vbri_total_time)
|
mp3parse->vbri_total_time)
|
||||||
seekable = GST_BASE_PARSE_SEEK_TABLE;
|
seekable = GST_BASE_PARSE_SEEK_TABLE;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mp3parse->xing_bitrate)
|
if (mp3parse->xing_bitrate)
|
||||||
bitrate = mp3parse->xing_bitrate;
|
bitrate = mp3parse->xing_bitrate;
|
||||||
|
@ -942,7 +944,7 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
|
||||||
else
|
else
|
||||||
bitrate = 0;
|
bitrate = 0;
|
||||||
|
|
||||||
gst_base_parse_set_seek (GST_BASE_PARSE (mp3parse), seekable, bitrate);
|
gst_base_parse_set_average_bitrate (GST_BASE_PARSE (mp3parse), bitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#define __GST_MPEG_AUDIO_PARSE_H__
|
#define __GST_MPEG_AUDIO_PARSE_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/baseparse/gstbaseparse.h>
|
#include <gst/base/gstbaseparse.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue