From 9f0a18b290de3e93812fbb7666f6377acf1e96e7 Mon Sep 17 00:00:00 2001 From: Sanchayan Maity Date: Sat, 19 Feb 2022 12:10:33 +0530 Subject: [PATCH] bluetooth: ldac: Fix RTP payloading of encoded packet Drop rtpldacpay and payload the LDAC encoded output manually in the RTP header. The RTP payload seems to be required as it carries the frame count information. Right now, rtpldacpay does not add this so construct the RTP header and payload manually. Strangely some devices like Shanling MP4 and Sony XM3 would still work without this while some like the Sony XM4 does not. Part-of: --- src/modules/bluetooth/a2dp-codec-ldac-gst.c | 47 +++++++++++---------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/modules/bluetooth/a2dp-codec-ldac-gst.c b/src/modules/bluetooth/a2dp-codec-ldac-gst.c index 749cfbe14..836ae37e9 100644 --- a/src/modules/bluetooth/a2dp-codec-ldac-gst.c +++ b/src/modules/bluetooth/a2dp-codec-ldac-gst.c @@ -46,13 +46,6 @@ static bool can_be_supported(bool for_encoding) { } gst_object_unref(element_factory); - element_factory = gst_element_factory_find("rtpldacpay"); - if (element_factory == NULL) { - pa_log_info("LDAC RTP payloader element `rtpldacpay` not found"); - return false; - } - gst_object_unref(element_factory); - return true; } @@ -206,7 +199,6 @@ static uint8_t fill_preferred_configuration(const pa_sample_spec *default_sample GstElement *gst_init_ldac(struct gst_info *info, pa_sample_spec *ss, bool for_encoding) { GstElement *bin; - GstElement *rtpldacpay; GstElement *enc; GstPad *pad; @@ -270,28 +262,16 @@ GstElement *gst_init_ldac(struct gst_info *info, pa_sample_spec *ss, bool for_en goto fail; } - rtpldacpay = gst_element_factory_make("rtpldacpay", "rtp_ldac_pay"); - if (!rtpldacpay) { - pa_log_error("Could not create RTP LDAC payloader element"); - goto fail; - } - bin = gst_bin_new("ldac_enc_bin"); pa_assert(bin); - gst_bin_add_many(GST_BIN(bin), enc, rtpldacpay, NULL); - - if (!gst_element_link(enc, rtpldacpay)) { - pa_log_error("Failed to link LDAC encoder to LDAC RTP payloader"); - gst_object_unref(bin); - return NULL; - } + gst_bin_add_many(GST_BIN(bin), enc, NULL); pad = gst_element_get_static_pad(enc, "sink"); pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad))); gst_object_unref(GST_OBJECT(pad)); - pad = gst_element_get_static_pad(rtpldacpay, "src"); + pad = gst_element_get_static_pad(enc, "src"); pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("src", pad))); gst_object_unref(GST_OBJECT(pad)); @@ -421,12 +401,33 @@ static size_t reduce_encoder_bitrate(void *codec_info, size_t write_link_mtu) { } static size_t 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; + struct rtp_header *header; + struct rtp_sbc_payload *payload; size_t written; - written = gst_transcode_buffer(codec_info, input_buffer, input_size, output_buffer, output_size, processed); + if (PA_UNLIKELY(output_size < sizeof(*header) + sizeof(*payload))) { + *processed = 0; + return 0; + } + + written = gst_transcode_buffer(codec_info, input_buffer, input_size, output_buffer + sizeof(*header) + sizeof(*payload), output_size - sizeof(*header) - sizeof(*payload), processed); if (PA_UNLIKELY(*processed != input_size)) pa_log_error("LDAC encoding error"); + if (PA_LIKELY(written > 0)) { + header = (struct rtp_header *) output_buffer; + pa_zero(*header); + header->v = 2; + header->pt = 96; + header->sequence_number = htons(info->seq_num++); + header->timestamp = htonl(timestamp); + header->ssrc = htonl(1); + payload = (struct rtp_sbc_payload*) (output_buffer + sizeof(*header)); + payload->frame_count = get_ldac_num_frames(codec_info, info->codec_type); + written += sizeof(*header) + sizeof(*payload); + } + return written; }