mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	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:
		
							parent
							
								
									4b996e2a7b
								
							
						
					
					
						commit
						9f0a18b290
					
				
					 1 changed files with 24 additions and 23 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue