From cdbb73f9ade5fed84f818aeacfc75295b86b6896 Mon Sep 17 00:00:00 2001 From: Sanchayan Maity Date: Tue, 5 Jan 2021 15:57:06 +0530 Subject: [PATCH] bluetooth: Move codec specific bits to their own respective files We move the codec specific bits to their own respective files and now make the codec specific initialisation use a GstBin, which the generic GStreamer module now uses in the pipeline. It is job of the codec specific function to add elements in the GstBin and link the added elements in the bin. It should also set up the ghost pads as a GstBin has no pads of it's own and without which the bin cannot be linked to the appsrc/appsink. Also, we now only initialise either the encoding or the decoding pipeline and not both. The codec init API already gets passed the for_encoding flag. We pass and use the same to codec specific init functions. Part-of: --- src/modules/bluetooth/a2dp-codec-aptx-gst.c | 206 +++++++++++++++++++- src/modules/bluetooth/a2dp-codec-gst.c | 153 +++++---------- src/modules/bluetooth/a2dp-codec-gst.h | 9 +- src/modules/bluetooth/a2dp-codec-ldac-gst.c | 153 ++++++++++++++- 4 files changed, 408 insertions(+), 113 deletions(-) diff --git a/src/modules/bluetooth/a2dp-codec-aptx-gst.c b/src/modules/bluetooth/a2dp-codec-aptx-gst.c index a1e8b474d..d04880326 100644 --- a/src/modules/bluetooth/a2dp-codec-aptx-gst.c +++ b/src/modules/bluetooth/a2dp-codec-aptx-gst.c @@ -266,12 +266,214 @@ static uint8_t fill_preferred_configuration_hd(const pa_sample_spec *default_sam return sizeof(*config); } +bool gst_init_aptx(struct gst_info *info, pa_sample_spec *ss, bool for_encoding) { + GstElement *enc, *dec; + GstCaps *caps; + GstPad *pad; + const char *aptx_codec_media_type; + + ss->format = PA_SAMPLE_S24LE; + + if (info->codec_type == APTX_HD) { + switch (info->a2dp_codec_t.aptx_hd_config->aptx.frequency) { + case APTX_SAMPLING_FREQ_16000: + ss->rate = 16000u; + break; + case APTX_SAMPLING_FREQ_32000: + ss->rate = 32000u; + break; + case APTX_SAMPLING_FREQ_44100: + ss->rate = 44100u; + break; + case APTX_SAMPLING_FREQ_48000: + ss->rate = 48000u; + break; + default: + pa_log_error("aptX HD invalid frequency %d", info->a2dp_codec_t.aptx_hd_config->aptx.frequency); + goto fail; + } + + switch (info->a2dp_codec_t.aptx_hd_config->aptx.channel_mode) { + case APTX_CHANNEL_MODE_STEREO: + ss->channels = 2; + break; + default: + pa_log_error("aptX HD invalid channel mode %d", info->a2dp_codec_t.aptx_hd_config->aptx.frequency); + goto fail; + } + } else { + switch (info->a2dp_codec_t.aptx_config->frequency) { + case APTX_SAMPLING_FREQ_16000: + ss->rate = 16000u; + break; + case APTX_SAMPLING_FREQ_32000: + ss->rate = 32000u; + break; + case APTX_SAMPLING_FREQ_44100: + ss->rate = 44100u; + break; + case APTX_SAMPLING_FREQ_48000: + ss->rate = 48000u; + break; + default: + pa_log_error("aptX invalid frequency %d", info->a2dp_codec_t.aptx_config->frequency); + goto fail; + } + + switch (info->a2dp_codec_t.aptx_config->channel_mode) { + case APTX_CHANNEL_MODE_STEREO: + ss->channels = 2; + break; + default: + pa_log_error("aptX invalid channel mode %d", info->a2dp_codec_t.aptx_config->frequency); + goto fail; + } + } + + aptx_codec_media_type = info->codec_type == APTX_HD ? "audio/aptx-hd" : "audio/aptx"; + + if (for_encoding) { + enc = gst_element_factory_make("openaptxenc", "aptx_encoder"); + + if (enc == NULL) { + pa_log_error("Could not create aptX encoder element"); + goto fail; + } + + caps = gst_caps_new_simple("audio/x-raw", + "format", G_TYPE_STRING, "S24LE", + "rate", G_TYPE_INT, (int) ss->rate, + "channels", G_TYPE_INT, (int) ss->channels, + "channel-mask", G_TYPE_INT, 0, + "layout", G_TYPE_STRING, "interleaved", + NULL); + g_object_set(info->enc_src, "caps", caps, NULL); + gst_caps_unref(caps); + + caps = gst_caps_new_simple(aptx_codec_media_type, + "rate", G_TYPE_INT, (int) ss->rate, + "channels", G_TYPE_INT, (int) ss->channels, + NULL); + g_object_set(info->enc_sink, "caps", caps, NULL); + gst_caps_unref(caps); + + info->enc_bin = gst_bin_new("aptx_enc_bin"); + pa_assert(info->enc_bin); + + gst_bin_add(GST_BIN(info->enc_bin), enc); + + pad = gst_element_get_static_pad(enc, "sink"); + gst_element_add_pad(info->enc_bin, gst_ghost_pad_new("sink", pad)); + gst_object_unref(GST_OBJECT(pad)); + + pad = gst_element_get_static_pad(enc, "src"); + gst_element_add_pad(info->enc_bin, gst_ghost_pad_new("src", pad)); + gst_object_unref(GST_OBJECT(pad)); + } else { + dec = gst_element_factory_make("openaptxdec", "aptx_decoder"); + + if (dec == NULL) { + pa_log_error("Could not create aptX decoder element"); + goto fail; + } + + caps = gst_caps_new_simple(aptx_codec_media_type, + "rate", G_TYPE_INT, (int) ss->rate, + "channels", G_TYPE_INT, (int) ss->channels, + NULL); + g_object_set(info->dec_src, "caps", caps, NULL); + gst_caps_unref(caps); + + caps = gst_caps_new_simple("audio/x-raw", + "format", G_TYPE_STRING, "S24LE", + "rate", G_TYPE_INT, (int) ss->rate, + "channels", G_TYPE_INT, (int) ss->channels, + "layout", G_TYPE_STRING, "interleaved", + NULL); + g_object_set(info->dec_sink, "caps", caps, NULL); + gst_caps_unref(caps); + + info->dec_bin = gst_bin_new("aptx_dec_bin"); + pa_assert(info->dec_bin); + + gst_bin_add(GST_BIN(info->dec_bin), dec); + + pad = gst_element_get_static_pad(dec, "sink"); + gst_element_add_pad(info->dec_bin, gst_ghost_pad_new("sink", pad)); + gst_object_unref(GST_OBJECT(pad)); + + pad = gst_element_get_static_pad(dec, "src"); + gst_element_add_pad(info->dec_bin, gst_ghost_pad_new("src", pad)); + gst_object_unref(GST_OBJECT(pad)); + } + + return true; + +fail: + pa_log_error("aptX initialisation failed"); + return false; +} + +static void *init_common(enum a2dp_codec_type codec_type, bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) { + struct gst_info *info = NULL; + + info = pa_xnew0(struct gst_info, 1); + pa_assert(info); + + info->core = core; + info->ss = sample_spec; + + if (codec_type == APTX) { + info->codec_type = APTX; + info->a2dp_codec_t.aptx_config = (const a2dp_aptx_t *) config_buffer; + pa_assert(config_size == sizeof(*(info->a2dp_codec_t.aptx_config))); + } else if (codec_type == APTX_HD) { + info->codec_type = APTX_HD; + info->a2dp_codec_t.aptx_hd_config = (const a2dp_aptx_hd_t *) config_buffer; + pa_assert(config_size == sizeof(*(info->a2dp_codec_t.aptx_hd_config))); + } else + pa_assert_not_reached(); + + /* + * The common encoder/decoder initialisation functions need to be called + * before the codec specific ones, as the codec specific initialisation + * function needs to set the caps specific property appropriately on the + * appsrc and appsink as per the sample spec and the codec. + */ + if (for_encoding) { + if (!gst_init_enc_common(info)) + goto fail; + } else { + if (!gst_init_dec_common(info)) + goto fail; + } + + if (!gst_init_aptx(info, sample_spec, for_encoding)) + goto enc_dec_fail; + + if (!gst_codec_init(info, for_encoding)) + goto enc_dec_fail; + + return info; + +enc_dec_fail: + if (for_encoding) + gst_deinit_enc_common(info); + else + gst_deinit_dec_common(info); +fail: + if (info) + pa_xfree(info); + + return NULL; +} + static void *init(bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) { - return gst_codec_init(APTX, config_buffer, config_size, sample_spec, core); + return init_common(APTX, for_encoding, for_backchannel, config_buffer, config_size, sample_spec, core); } static void *init_hd(bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) { - return gst_codec_init(APTX_HD, config_buffer, config_size, sample_spec, core); + return init_common(APTX_HD, for_encoding, for_backchannel, config_buffer, config_size, sample_spec, core); } static void deinit(void *codec_info) { diff --git a/src/modules/bluetooth/a2dp-codec-gst.c b/src/modules/bluetooth/a2dp-codec-gst.c index bb0632e21..930484ee3 100644 --- a/src/modules/bluetooth/a2dp-codec-gst.c +++ b/src/modules/bluetooth/a2dp-codec-gst.c @@ -82,15 +82,13 @@ static GstFlowReturn dec_sink_new_sample(GstAppSink *appsink, gpointer userdata) return GST_FLOW_OK; } -static void gst_deinit_enc_common(struct gst_info *info) { +void gst_deinit_enc_common(struct gst_info *info) { if (!info) return; if (info->enc_fdsem) pa_fdsem_free(info->enc_fdsem); if (info->enc_src) gst_object_unref(info->enc_src); - if (info->gst_enc) - gst_object_unref(info->gst_enc); if (info->enc_sink) gst_object_unref(info->enc_sink); if (info->enc_adapter) @@ -99,15 +97,13 @@ static void gst_deinit_enc_common(struct gst_info *info) { gst_object_unref(info->enc_pipeline); } -static void gst_deinit_dec_common(struct gst_info *info) { +void gst_deinit_dec_common(struct gst_info *info) { if (!info) return; if (info->dec_fdsem) pa_fdsem_free(info->dec_fdsem); if (info->dec_src) gst_object_unref(info->dec_src); - if (info->gst_dec) - gst_object_unref(info->gst_dec); if (info->dec_sink) gst_object_unref(info->dec_sink); if (info->dec_adapter) @@ -146,7 +142,7 @@ static GstBusSyncReply sync_bus_handler (GstBus *bus, GstMessage *message, struc return GST_BUS_PASS; } -static bool gst_init_enc_common(struct gst_info *info, pa_sample_spec *ss) { +bool gst_init_enc_common(struct gst_info *info) { GstElement *pipeline = NULL; GstElement *appsrc = NULL, *appsink = NULL; GstAdapter *adapter; @@ -190,12 +186,15 @@ static bool gst_init_enc_common(struct gst_info *info, pa_sample_spec *ss) { return true; fail: - gst_deinit_enc_common(info); + if (appsrc) + gst_object_unref(appsrc); + if (appsink) + gst_object_unref(appsink); return false; } -static bool gst_init_dec_common(struct gst_info *info, pa_sample_spec *ss) { +bool gst_init_dec_common(struct gst_info *info) { GstElement *pipeline = NULL; GstElement *appsrc = NULL, *appsink = NULL; GstAdapter *adapter; @@ -239,7 +238,10 @@ static bool gst_init_dec_common(struct gst_info *info, pa_sample_spec *ss) { return true; fail: - gst_deinit_dec_common(info); + if (appsrc) + gst_object_unref(appsrc); + if (appsink) + gst_object_unref(appsink); return false; } @@ -304,123 +306,64 @@ static GstPadProbeReturn gst_decoder_buffer_probe(GstPad *pad, GstPadProbeInfo * return GST_PAD_PROBE_OK; } -static bool gst_init_common(struct gst_info *info, pa_sample_spec *ss) { +bool gst_codec_init(struct gst_info *info, bool for_encoding) { GstPad *pad; info->seq_num = 0; - if (!gst_init_enc_common(info, ss)) - goto fail; + /* In case if we ever have a codec which supports decoding but not encoding */ + if (for_encoding && info->enc_bin) { + gst_bin_add_many(GST_BIN(info->enc_pipeline), info->enc_src, info->enc_bin, info->enc_sink, NULL); - switch (info->codec_type) { - case AAC: - goto fail; - break; - case APTX: - case APTX_HD: - if (!gst_init_dec_common(info, ss)) - goto enc_fail; + if (!gst_element_link_many(info->enc_src, info->enc_bin, info->enc_sink, NULL)) { + pa_log_error("Failed to link encoder elements"); + goto enc_dec_fail; + } - if (!gst_init_aptx(info, ss)) - goto dec_fail; - break; - case LDAC_EQMID_HQ: - case LDAC_EQMID_SQ: - case LDAC_EQMID_MQ: - if (!gst_init_ldac(info, ss)) - goto dec_fail; - break; - default: - goto fail; - } + if (gst_element_set_state(info->enc_pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + pa_log_error("Could not start encoder pipeline"); + goto enc_dec_fail; + } - /* See the comment on buffer probe functions */ - if (info->gst_enc) { - pad = gst_element_get_static_pad(info->gst_enc, "sink"); + /* See the comment on buffer probe functions */ + pad = gst_element_get_static_pad(info->enc_bin, "sink"); gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, gst_encoder_buffer_probe, info, NULL); gst_object_unref(pad); - } + } else if (!for_encoding && info->dec_bin) { + gst_bin_add_many(GST_BIN(info->dec_pipeline), info->dec_src, info->dec_bin, info->dec_sink, NULL); - if (info->gst_dec) { - pad = gst_element_get_static_pad(info->gst_dec, "sink"); + if (!gst_element_link_many(info->dec_src, info->dec_bin, info->dec_sink, NULL)) { + pa_log_error("Failed to link decoder elements"); + goto enc_dec_fail; + } + + if (gst_element_set_state(info->dec_pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + pa_log_error("Could not start decoder pipeline"); + goto enc_dec_fail; + } + + /* See the comment on buffer probe functions */ + pad = gst_element_get_static_pad(info->dec_bin, "sink"); gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, gst_decoder_buffer_probe, info, NULL); gst_object_unref(pad); - } + } else + pa_assert_not_reached(); pa_log_info("Gstreamer pipeline initialisation succeeded"); return true; -dec_fail: - if (info->dec_pipeline) { - gst_element_set_state(info->dec_pipeline, GST_STATE_NULL); - gst_object_unref(info->dec_pipeline); - } -enc_fail: - if (info->enc_pipeline) { - gst_element_set_state(info->enc_pipeline, GST_STATE_NULL); - gst_object_unref(info->enc_pipeline); - } -fail: +enc_dec_fail: + if (for_encoding) + gst_deinit_enc_common(info); + else + gst_deinit_dec_common(info); + pa_log_error("Gstreamer pipeline initialisation failed"); return false; } -void *gst_codec_init(enum a2dp_codec_type codec_type, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *ss, pa_core *core) { - struct gst_info *info = NULL; - bool ret; - - info = pa_xnew0(struct gst_info, 1); - pa_assert(info); - - info->core = core; - - switch (codec_type) { - case AAC: - info->codec_type = AAC; - info->a2dp_codec_t.aac_config = (const a2dp_aac_t *) config_buffer; - pa_assert(config_size == sizeof(*(info->a2dp_codec_t.aac_config))); - break; - case APTX: - info->codec_type = APTX; - info->a2dp_codec_t.aptx_config = (const a2dp_aptx_t *) config_buffer; - pa_assert(config_size == sizeof(*(info->a2dp_codec_t.aptx_config))); - break; - case APTX_HD: - info->codec_type = APTX_HD; - info->a2dp_codec_t.aptx_hd_config = (const a2dp_aptx_hd_t *) config_buffer; - pa_assert(config_size == sizeof(*(info->a2dp_codec_t.aptx_hd_config))); - break; - case LDAC_EQMID_HQ: - case LDAC_EQMID_SQ: - case LDAC_EQMID_MQ: - info->codec_type = codec_type; - info->a2dp_codec_t.ldac_config = (const a2dp_ldac_t *) config_buffer; - pa_assert(config_size == sizeof(*(info->a2dp_codec_t.ldac_config))); - break; - default: - pa_log_error("Unsupported bluetooth codec"); - goto fail; - } - - ret = gst_init_common(info, ss); - if (!ret) - goto fail; - - info->ss = ss; - - pa_log_info("Rate: %d Channels: %d Format: %d", ss->rate, ss->channels, ss->format); - - return info; - -fail: - if (info) - pa_xfree(info); - - return NULL; -} - size_t gst_encode_buffer(void *codec_info, uint32_t timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed) { struct gst_info *info = (struct gst_info *) codec_info; gsize available, encoded; diff --git a/src/modules/bluetooth/a2dp-codec-gst.h b/src/modules/bluetooth/a2dp-codec-gst.h index 6fa97abce..562c012a6 100644 --- a/src/modules/bluetooth/a2dp-codec-gst.h +++ b/src/modules/bluetooth/a2dp-codec-gst.h @@ -43,7 +43,7 @@ struct gst_info { const a2dp_ldac_t *ldac_config; } a2dp_codec_t; - GstElement *gst_enc, *gst_dec; + GstElement *enc_bin, *dec_bin; GstElement *enc_src, *enc_sink; GstElement *dec_src, *dec_sink; GstElement *enc_pipeline, *dec_pipeline; @@ -55,7 +55,12 @@ struct gst_info { uint16_t seq_num; }; -void *gst_codec_init(enum a2dp_codec_type codec_type, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *ss, pa_core *core); +bool gst_codec_init(struct gst_info *info, bool for_encoding); size_t gst_encode_buffer(void *codec_info, uint32_t timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed); size_t gst_decode_buffer(void *codec_info, const uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size, size_t *processed); void gst_codec_deinit(void *codec_info); + +bool gst_init_enc_common(struct gst_info *info); +bool gst_init_dec_common(struct gst_info *info); +void gst_deinit_enc_common(struct gst_info *info); +void gst_deinit_dec_common(struct gst_info *info); diff --git a/src/modules/bluetooth/a2dp-codec-ldac-gst.c b/src/modules/bluetooth/a2dp-codec-ldac-gst.c index 6c0f05a3b..70f38d208 100644 --- a/src/modules/bluetooth/a2dp-codec-ldac-gst.c +++ b/src/modules/bluetooth/a2dp-codec-ldac-gst.c @@ -195,16 +195,162 @@ static uint8_t fill_preferred_configuration(const pa_sample_spec *default_sample return sizeof(*config); } +bool gst_init_ldac(struct gst_info *info, pa_sample_spec *ss, bool for_encoding) { + GstElement *rtpldacpay; + GstElement *enc; + GstCaps *caps; + GstPad *pad; + + if (!for_encoding) { + pa_log_error("LDAC does not support decoding"); + return false; + } + + ss->format = PA_SAMPLE_S32LE; + + switch (info->a2dp_codec_t.ldac_config->frequency) { + case LDAC_SAMPLING_FREQ_44100: + ss->rate = 44100u; + break; + case LDAC_SAMPLING_FREQ_48000: + ss->rate = 48000u; + break; + case LDAC_SAMPLING_FREQ_88200: + ss->rate = 88200; + break; + case LDAC_SAMPLING_FREQ_96000: + ss->rate = 96000; + break; + default: + pa_log_error("LDAC invalid frequency %d", info->a2dp_codec_t.ldac_config->frequency); + goto fail; + } + + switch (info->a2dp_codec_t.ldac_config->channel_mode) { + case LDAC_CHANNEL_MODE_STEREO: + ss->channels = 2; + break; + case LDAC_CHANNEL_MODE_MONO: + ss->channels = 1; + break; + case LDAC_CHANNEL_MODE_DUAL: + ss->channels = 1; + break; + default: + pa_log_error("LDAC invalid channel mode %d", info->a2dp_codec_t.ldac_config->channel_mode); + goto fail; + } + + enc = gst_element_factory_make("ldacenc", "ldac_enc"); + if (!enc) { + pa_log_error("Could not create LDAC encoder element"); + goto fail; + } + + switch (info->codec_type) { + case LDAC_EQMID_HQ: + g_object_set(enc, "eqmid", 0, NULL); + break; + case LDAC_EQMID_SQ: + g_object_set(enc, "eqmid", 1, NULL); + break; + case LDAC_EQMID_MQ: + g_object_set(enc, "eqmid", 2, NULL); + break; + default: + goto fail; + } + + caps = gst_caps_new_simple("audio/x-raw", + "format", G_TYPE_STRING, "S32LE", + "rate", G_TYPE_INT, (int) ss->rate, + "channels", G_TYPE_INT, (int) ss->channels, + "channel-mask", G_TYPE_INT, 0, + "layout", G_TYPE_STRING, "interleaved", + NULL); + g_object_set(info->enc_src, "caps", caps, NULL); + gst_caps_unref(caps); + + rtpldacpay = gst_element_factory_make("rtpldacpay", "rtp_ldac_pay"); + if (!rtpldacpay) { + pa_log_error("Could not create RTP LDAC payloader element"); + goto fail; + } + + info->enc_bin = gst_bin_new("ldac_enc_bin"); + pa_assert(info->enc_bin); + + gst_bin_add_many(GST_BIN(info->enc_bin), enc, rtpldacpay, NULL); + + if (!gst_element_link(enc, rtpldacpay)) { + pa_log_error("Failed to link LDAC encoder to LDAC RTP payloader"); + return false; + } + + pad = gst_element_get_static_pad(enc, "sink"); + gst_element_add_pad(info->enc_bin, gst_ghost_pad_new("sink", pad)); + gst_object_unref(GST_OBJECT(pad)); + + pad = gst_element_get_static_pad(rtpldacpay, "src"); + gst_element_add_pad(info->enc_bin, gst_ghost_pad_new("src", pad)); + gst_object_unref(GST_OBJECT(pad)); + + return true; + +fail: + pa_log_error("LDAC encoder initialisation failed"); + return false; +} + +static void *init_common(enum a2dp_codec_type codec_type, bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) { + struct gst_info *info = NULL; + + info = pa_xnew0(struct gst_info, 1); + pa_assert(info); + + info->core = core; + info->ss = sample_spec; + + info->codec_type = codec_type; + info->a2dp_codec_t.ldac_config = (const a2dp_ldac_t *) config_buffer; + pa_assert(config_size == sizeof(*(info->a2dp_codec_t.ldac_config))); + + /* + * The common encoder/decoder initialisation functions need to be called + * before the codec specific ones, as the codec specific initialisation + * function needs to set the caps specific property appropriately on the + * appsrc and appsink as per the sample spec and the codec. + */ + if (!gst_init_enc_common(info)) + goto fail; + + if (!gst_init_ldac(info, sample_spec, for_encoding)) + goto enc_fail; + + if (!gst_codec_init(info, for_encoding)) + goto enc_fail; + + return info; + +enc_fail: + gst_deinit_enc_common(info); +fail: + if (info) + pa_xfree(info); + + return NULL; +} + static void *init_hq(bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) { - return gst_codec_init(LDAC_EQMID_HQ, config_buffer, config_size, sample_spec, core); + return init_common(LDAC_EQMID_HQ, for_encoding, for_backchannel, config_buffer, config_size, sample_spec, core); } static void *init_sq(bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) { - return gst_codec_init(LDAC_EQMID_SQ, config_buffer, config_size, sample_spec, core); + return init_common(LDAC_EQMID_SQ, for_encoding, for_backchannel, config_buffer, config_size, sample_spec, core); } static void *init_mq(bool for_encoding, bool for_backchannel, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *sample_spec, pa_core *core) { - return gst_codec_init(LDAC_EQMID_MQ, config_buffer, config_size, sample_spec, core); + return init_common(LDAC_EQMID_MQ, for_encoding, for_backchannel, config_buffer, config_size, sample_spec, core); } static void deinit(void *codec_info) { @@ -281,7 +427,6 @@ static size_t encode_buffer(void *codec_info, uint32_t timestamp, const uint8_t if (PA_UNLIKELY(*processed != input_size)) pa_log_error("LDAC encoding error"); - return written; }