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: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/689>
This commit is contained in:
Sanchayan Maity 2022-02-19 12:10:33 +05:30
parent 4b996e2a7b
commit 9f0a18b290

View file

@ -46,13 +46,6 @@ static bool can_be_supported(bool for_encoding) {
} }
gst_object_unref(element_factory); 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; 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 *gst_init_ldac(struct gst_info *info, pa_sample_spec *ss, bool for_encoding) {
GstElement *bin; GstElement *bin;
GstElement *rtpldacpay;
GstElement *enc; GstElement *enc;
GstPad *pad; GstPad *pad;
@ -270,28 +262,16 @@ GstElement *gst_init_ldac(struct gst_info *info, pa_sample_spec *ss, bool for_en
goto fail; 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"); bin = gst_bin_new("ldac_enc_bin");
pa_assert(bin); pa_assert(bin);
gst_bin_add_many(GST_BIN(bin), enc, rtpldacpay, NULL); gst_bin_add_many(GST_BIN(bin), enc, 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;
}
pad = gst_element_get_static_pad(enc, "sink"); pad = gst_element_get_static_pad(enc, "sink");
pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad))); pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad)));
gst_object_unref(GST_OBJECT(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))); pa_assert_se(gst_element_add_pad(bin, gst_ghost_pad_new("src", pad)));
gst_object_unref(GST_OBJECT(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) { 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; 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)) if (PA_UNLIKELY(*processed != input_size))
pa_log_error("LDAC encoding error"); 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; return written;
} }