mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	unify code that fixes up buffering metrics
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2302 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
		
							parent
							
								
									af03dd4e4f
								
							
						
					
					
						commit
						ed0af46e69
					
				
					 1 changed files with 188 additions and 157 deletions
				
			
		| 
						 | 
					@ -470,11 +470,65 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fix_record_buffer_attr_pre(record_stream *s, pa_bool_t adjust_latency, uint32_t *maxlength, uint32_t *fragsize) {
 | 
				
			||||||
 | 
					    pa_assert(s);
 | 
				
			||||||
 | 
					    pa_assert(maxlength);
 | 
				
			||||||
 | 
					    pa_assert(fragsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
				
			||||||
 | 
					        *maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*fragsize <= 0)
 | 
				
			||||||
 | 
					        *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (adjust_latency) {
 | 
				
			||||||
 | 
					        pa_usec_t fragsize_usec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* So, the user asked us to adjust the latency according to
 | 
				
			||||||
 | 
					         * the what the source can provide. Half the latency will be
 | 
				
			||||||
 | 
					         * spent on the hw buffer, half of it in the async buffer
 | 
				
			||||||
 | 
					         * queue we maintain for each client. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fragsize_usec = pa_bytes_to_usec(*fragsize, &s->source_output->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        s->source_latency = pa_source_output_set_requested_latency(s->source_output, fragsize_usec/2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (fragsize_usec >= s->source_latency*2)
 | 
				
			||||||
 | 
					            fragsize_usec -= s->source_latency;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            fragsize_usec = s->source_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *fragsize = pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fix_record_buffer_attr_post(record_stream *s, uint32_t *maxlength, uint32_t *fragsize) {
 | 
				
			||||||
 | 
					    size_t base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(s);
 | 
				
			||||||
 | 
					    pa_assert(maxlength);
 | 
				
			||||||
 | 
					    pa_assert(fragsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *maxlength = pa_memblockq_get_maxlength(s->memblockq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    base = pa_frame_size(&s->source_output->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->fragment_size = (*fragsize/base)*base;
 | 
				
			||||||
 | 
					    if (s->fragment_size <= 0)
 | 
				
			||||||
 | 
					        s->fragment_size = base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s->fragment_size > *maxlength)
 | 
				
			||||||
 | 
					        s->fragment_size = *maxlength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *fragsize = s->fragment_size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static record_stream* record_stream_new(
 | 
					static record_stream* record_stream_new(
 | 
				
			||||||
        connection *c,
 | 
					        connection *c,
 | 
				
			||||||
        pa_source *source,
 | 
					        pa_source *source,
 | 
				
			||||||
        pa_sample_spec *ss,
 | 
					        pa_sample_spec *ss,
 | 
				
			||||||
        pa_channel_map *map,
 | 
					        pa_channel_map *map,
 | 
				
			||||||
 | 
					        pa_bool_t peak_detect,
 | 
				
			||||||
        uint32_t *maxlength,
 | 
					        uint32_t *maxlength,
 | 
				
			||||||
        uint32_t *fragsize,
 | 
					        uint32_t *fragsize,
 | 
				
			||||||
        pa_source_output_flags_t flags,
 | 
					        pa_source_output_flags_t flags,
 | 
				
			||||||
| 
						 | 
					@ -501,6 +555,8 @@ static record_stream* record_stream_new(
 | 
				
			||||||
    data.source = source;
 | 
					    data.source = source;
 | 
				
			||||||
    pa_source_output_new_data_set_sample_spec(&data, ss);
 | 
					    pa_source_output_new_data_set_sample_spec(&data, ss);
 | 
				
			||||||
    pa_source_output_new_data_set_channel_map(&data, map);
 | 
					    pa_source_output_new_data_set_channel_map(&data, map);
 | 
				
			||||||
 | 
					    if (peak_detect)
 | 
				
			||||||
 | 
					        data.resample_method = PA_RESAMPLER_PEAKS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    source_output = pa_source_output_new(c->protocol->core, &data, flags);
 | 
					    source_output = pa_source_output_new(c->protocol->core, &data, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -522,30 +578,7 @@ static record_stream* record_stream_new(
 | 
				
			||||||
    s->source_output->suspend = source_output_suspend_cb;
 | 
					    s->source_output->suspend = source_output_suspend_cb;
 | 
				
			||||||
    s->source_output->userdata = s;
 | 
					    s->source_output->userdata = s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
					    fix_record_buffer_attr_pre(s, adjust_latency, maxlength, fragsize);
 | 
				
			||||||
        *maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
					 | 
				
			||||||
    if (*fragsize <= 0)
 | 
					 | 
				
			||||||
        *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &source_output->sample_spec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (adjust_latency) {
 | 
					 | 
				
			||||||
        pa_usec_t fragsize_usec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* So, the user asked us to adjust the latency according to
 | 
					 | 
				
			||||||
         * the what the source can provide. Half the latency will be
 | 
					 | 
				
			||||||
         * spent on the hw buffer, half of it in the async buffer
 | 
					 | 
				
			||||||
         * queue we maintain for each client. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fragsize_usec = pa_bytes_to_usec(*fragsize, &source_output->sample_spec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        s->source_latency = pa_source_output_set_requested_latency(source_output, fragsize_usec/2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (fragsize_usec >= s->source_latency*2)
 | 
					 | 
				
			||||||
            fragsize_usec -= s->source_latency;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            fragsize_usec = s->source_latency;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        *fragsize = pa_usec_to_bytes(fragsize_usec, &source_output->sample_spec);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->memblockq = pa_memblockq_new(
 | 
					    s->memblockq = pa_memblockq_new(
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
| 
						 | 
					@ -557,16 +590,7 @@ static record_stream* record_stream_new(
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
            NULL);
 | 
					            NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *maxlength = pa_memblockq_get_maxlength(s->memblockq);
 | 
					    fix_record_buffer_attr_post(s, maxlength, fragsize);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    s->fragment_size = (*fragsize/base)*base;
 | 
					 | 
				
			||||||
    if (s->fragment_size <= 0)
 | 
					 | 
				
			||||||
        s->fragment_size = base;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (s->fragment_size > *maxlength)
 | 
					 | 
				
			||||||
        s->fragment_size = *maxlength;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    *fragsize = s->fragment_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *ss = s->source_output->sample_spec;
 | 
					    *ss = s->source_output->sample_spec;
 | 
				
			||||||
    *map = s->source_output->channel_map;
 | 
					    *map = s->source_output->channel_map;
 | 
				
			||||||
| 
						 | 
					@ -674,6 +698,114 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_latency, uint32_t *maxlength, uint32_t *tlength, uint32_t* prebuf, uint32_t* minreq) {
 | 
				
			||||||
 | 
					    size_t frame_size;
 | 
				
			||||||
 | 
					    pa_usec_t tlength_usec, minreq_usec, sink_usec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(s);
 | 
				
			||||||
 | 
					    pa_assert(maxlength);
 | 
				
			||||||
 | 
					    pa_assert(tlength);
 | 
				
			||||||
 | 
					    pa_assert(prebuf);
 | 
				
			||||||
 | 
					    pa_assert(minreq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
				
			||||||
 | 
					        *maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
				
			||||||
 | 
					    if (*tlength <= 0)
 | 
				
			||||||
 | 
					        *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
 | 
				
			||||||
 | 
					    if (*minreq <= 0)
 | 
				
			||||||
 | 
					        *minreq = pa_usec_to_bytes(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    frame_size = pa_frame_size(&s->sink_input->sample_spec);
 | 
				
			||||||
 | 
					    if (*minreq <= 0)
 | 
				
			||||||
 | 
					        *minreq = frame_size;
 | 
				
			||||||
 | 
					    if (*tlength < *minreq+frame_size)
 | 
				
			||||||
 | 
					        *tlength = *minreq+frame_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tlength_usec = pa_bytes_to_usec(*tlength, &s->sink_input->sample_spec);
 | 
				
			||||||
 | 
					    minreq_usec = pa_bytes_to_usec(*minreq, &s->sink_input->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
 | 
				
			||||||
 | 
					                (double) tlength_usec / PA_USEC_PER_MSEC,
 | 
				
			||||||
 | 
					                (double) minreq_usec / PA_USEC_PER_MSEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (adjust_latency) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* So, the user asked us to adjust the latency of the stream
 | 
				
			||||||
 | 
					         * buffer according to the what the sink can provide. The
 | 
				
			||||||
 | 
					         * tlength passed in shall be the overall latency. Roughly
 | 
				
			||||||
 | 
					         * half the latency will be spent on the hw buffer, the other
 | 
				
			||||||
 | 
					         * half of it in the async buffer queue we maintain for each
 | 
				
			||||||
 | 
					         * client. In between we'll have a safety space of size
 | 
				
			||||||
 | 
					         * 2*minreq. Why the 2*minreq? When the hw buffer is completey
 | 
				
			||||||
 | 
					         * empty and needs to be filled, then our buffer must have
 | 
				
			||||||
 | 
					         * enough data to fulfill this request immediatly and thus
 | 
				
			||||||
 | 
					         * have at least the same tlength as the size of the hw
 | 
				
			||||||
 | 
					         * buffer. It additionally needs space for 2 times minreq
 | 
				
			||||||
 | 
					         * because if the buffer ran empty and a partial fillup
 | 
				
			||||||
 | 
					         * happens immediately on the next iteration we need to be
 | 
				
			||||||
 | 
					         * able to fulfill it and give the application also minreq
 | 
				
			||||||
 | 
					         * time to fill it up again for the next request Makes 2 times
 | 
				
			||||||
 | 
					         * minreq in plus.. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (tlength_usec > minreq_usec*2)
 | 
				
			||||||
 | 
					            sink_usec = (tlength_usec - minreq_usec*2)/2;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            sink_usec = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Ok, the user didn't ask us to adjust the latency, but we
 | 
				
			||||||
 | 
					         * still need to make sure that the parameters from the user
 | 
				
			||||||
 | 
					         * do make sense. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (tlength_usec > minreq_usec*2)
 | 
				
			||||||
 | 
					            sink_usec = (tlength_usec - minreq_usec*2);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            sink_usec = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (adjust_latency) {
 | 
				
			||||||
 | 
					        /* Ok, we didn't necessarily get what we were asking for, so
 | 
				
			||||||
 | 
					         * let's subtract from what we asked for for the remaining
 | 
				
			||||||
 | 
					         * buffer space */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (tlength_usec >= s->sink_latency)
 | 
				
			||||||
 | 
					            tlength_usec -= s->sink_latency;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (tlength_usec < s->sink_latency + 2*minreq_usec)
 | 
				
			||||||
 | 
					        tlength_usec = s->sink_latency + 2*minreq_usec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *tlength = pa_usec_to_bytes(tlength_usec, &s->sink_input->sample_spec);
 | 
				
			||||||
 | 
					    *minreq = pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*minreq <= 0) {
 | 
				
			||||||
 | 
					        *minreq += frame_size;
 | 
				
			||||||
 | 
					        *tlength += frame_size*2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*tlength <= *minreq)
 | 
				
			||||||
 | 
					        *tlength =  *minreq*2 + frame_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*prebuf <= 0)
 | 
				
			||||||
 | 
					        *prebuf = *tlength;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fix_playback_buffer_attr_post(playback_stream *s, uint32_t *maxlength, uint32_t *tlength, uint32_t* prebuf, uint32_t* minreq) {
 | 
				
			||||||
 | 
					    pa_assert(s);
 | 
				
			||||||
 | 
					    pa_assert(maxlength);
 | 
				
			||||||
 | 
					    pa_assert(tlength);
 | 
				
			||||||
 | 
					    pa_assert(prebuf);
 | 
				
			||||||
 | 
					    pa_assert(minreq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
 | 
				
			||||||
 | 
					    *tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq);
 | 
				
			||||||
 | 
					    *prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq);
 | 
				
			||||||
 | 
					    *minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static playback_stream* playback_stream_new(
 | 
					static playback_stream* playback_stream_new(
 | 
				
			||||||
        connection *c,
 | 
					        connection *c,
 | 
				
			||||||
        pa_sink *sink,
 | 
					        pa_sink *sink,
 | 
				
			||||||
| 
						 | 
					@ -697,8 +829,6 @@ static playback_stream* playback_stream_new(
 | 
				
			||||||
    uint32_t idx;
 | 
					    uint32_t idx;
 | 
				
			||||||
    int64_t start_index;
 | 
					    int64_t start_index;
 | 
				
			||||||
    pa_sink_input_new_data data;
 | 
					    pa_sink_input_new_data data;
 | 
				
			||||||
    pa_usec_t tlength_usec, minreq_usec, sink_usec;
 | 
					 | 
				
			||||||
    size_t frame_size;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(c);
 | 
					    pa_assert(c);
 | 
				
			||||||
    pa_assert(ss);
 | 
					    pa_assert(ss);
 | 
				
			||||||
| 
						 | 
					@ -769,90 +899,7 @@ static playback_stream* playback_stream_new(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
 | 
					    start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
					    fix_playback_buffer_attr_pre(s, adjust_latency, maxlength, tlength, prebuf, minreq);
 | 
				
			||||||
        *maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
					 | 
				
			||||||
    if (*tlength <= 0)
 | 
					 | 
				
			||||||
        *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &sink_input->sample_spec);
 | 
					 | 
				
			||||||
    if (*minreq <= 0)
 | 
					 | 
				
			||||||
        *minreq = pa_usec_to_bytes(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &sink_input->sample_spec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    frame_size = pa_frame_size(&sink_input->sample_spec);
 | 
					 | 
				
			||||||
    if (*minreq <= 0)
 | 
					 | 
				
			||||||
        *minreq = frame_size;
 | 
					 | 
				
			||||||
    if (*tlength < *minreq+frame_size)
 | 
					 | 
				
			||||||
        *tlength = *minreq+frame_size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
 | 
					 | 
				
			||||||
    minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
 | 
					 | 
				
			||||||
                (double) tlength_usec / PA_USEC_PER_MSEC,
 | 
					 | 
				
			||||||
                (double) minreq_usec / PA_USEC_PER_MSEC);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (adjust_latency) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* So, the user asked us to adjust the latency of the stream
 | 
					 | 
				
			||||||
         * buffer according to the what the sink can provide. The
 | 
					 | 
				
			||||||
         * tlength passed in shall be the overall latency. Roughly
 | 
					 | 
				
			||||||
         * half the latency will be spent on the hw buffer, the other
 | 
					 | 
				
			||||||
         * half of it in the async buffer queue we maintain for each
 | 
					 | 
				
			||||||
         * client. In between we'll have a safety space of size
 | 
					 | 
				
			||||||
         * 2*minreq. Why the 2*minreq? When the hw buffer is completey
 | 
					 | 
				
			||||||
         * empty and needs to be filled, then our buffer must have
 | 
					 | 
				
			||||||
         * enough data to fulfill this request immediatly and thus
 | 
					 | 
				
			||||||
         * have at least the same tlength as the size of the hw
 | 
					 | 
				
			||||||
         * buffer. It additionally needs space for 2 times minreq
 | 
					 | 
				
			||||||
         * because if the buffer ran empty and a partial fillup
 | 
					 | 
				
			||||||
         * happens immediately on the next iteration we need to be
 | 
					 | 
				
			||||||
         * able to fulfill it and give the application also minreq
 | 
					 | 
				
			||||||
         * time to fill it up again for the next request Makes 2 times
 | 
					 | 
				
			||||||
         * minreq in plus.. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (tlength_usec > minreq_usec*2)
 | 
					 | 
				
			||||||
            sink_usec = (tlength_usec - minreq_usec*2)/2;
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            sink_usec = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Ok, the user didn't ask us to adjust the latency, but we
 | 
					 | 
				
			||||||
         * still need to make sure that the parameters from the user
 | 
					 | 
				
			||||||
         * do make sense. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (tlength_usec > minreq_usec*2)
 | 
					 | 
				
			||||||
            sink_usec = (tlength_usec - minreq_usec*2);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            sink_usec = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    s->sink_latency = pa_sink_input_set_requested_latency(sink_input, sink_usec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (adjust_latency) {
 | 
					 | 
				
			||||||
        /* Ok, we didn't necessarily get what we were asking for, so
 | 
					 | 
				
			||||||
         * let's subtract from what we asked for for the remaining
 | 
					 | 
				
			||||||
         * buffer space */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (tlength_usec >= s->sink_latency)
 | 
					 | 
				
			||||||
            tlength_usec -= s->sink_latency;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (tlength_usec < s->sink_latency + 2*minreq_usec)
 | 
					 | 
				
			||||||
        tlength_usec = s->sink_latency + 2*minreq_usec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
 | 
					 | 
				
			||||||
    *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (*minreq <= 0) {
 | 
					 | 
				
			||||||
        *minreq += frame_size;
 | 
					 | 
				
			||||||
        *tlength += frame_size*2;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (*tlength <= *minreq)
 | 
					 | 
				
			||||||
        *tlength =  *minreq*2 + frame_size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (*prebuf <= 0)
 | 
					 | 
				
			||||||
        *prebuf = *tlength;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pa_sink_input_get_silence(sink_input, &silence);
 | 
					    pa_sink_input_get_silence(sink_input, &silence);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->memblockq = pa_memblockq_new(
 | 
					    s->memblockq = pa_memblockq_new(
 | 
				
			||||||
| 
						 | 
					@ -866,17 +913,14 @@ static playback_stream* playback_stream_new(
 | 
				
			||||||
            &silence);
 | 
					            &silence);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_memblock_unref(silence.memblock);
 | 
					    pa_memblock_unref(silence.memblock);
 | 
				
			||||||
 | 
					    fix_playback_buffer_attr_post(s, maxlength, tlength, prebuf, minreq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
 | 
					 | 
				
			||||||
    *tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq);
 | 
					 | 
				
			||||||
    *prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq);
 | 
					 | 
				
			||||||
    *minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq);
 | 
					 | 
				
			||||||
    *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
 | 
					    *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *ss = s->sink_input->sample_spec;
 | 
					    *ss = s->sink_input->sample_spec;
 | 
				
			||||||
    *map = s->sink_input->channel_map;
 | 
					    *map = s->sink_input->channel_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->minreq = pa_memblockq_get_minreq(s->memblockq);
 | 
					    s->minreq = *minreq;
 | 
				
			||||||
    pa_atomic_store(&s->missing, 0);
 | 
					    pa_atomic_store(&s->missing, 0);
 | 
				
			||||||
    s->drain_request = FALSE;
 | 
					    s->drain_request = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1671,7 +1715,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 | 
				
			||||||
        fix_channels = FALSE,
 | 
					        fix_channels = FALSE,
 | 
				
			||||||
        no_move = FALSE,
 | 
					        no_move = FALSE,
 | 
				
			||||||
        variable_rate = FALSE,
 | 
					        variable_rate = FALSE,
 | 
				
			||||||
        adjust_latency = FALSE;
 | 
					        adjust_latency = FALSE,
 | 
				
			||||||
 | 
					        peak_detect = FALSE;
 | 
				
			||||||
    pa_source_output_flags_t flags = 0;
 | 
					    pa_source_output_flags_t flags = 0;
 | 
				
			||||||
    pa_proplist *p;
 | 
					    pa_proplist *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1720,7 +1765,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c->version >= 13) {
 | 
					    if (c->version >= 13) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
 | 
					        if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
 | 
				
			||||||
 | 
					            pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
 | 
				
			||||||
            pa_tagstruct_get_proplist(t, p) < 0) {
 | 
					            pa_tagstruct_get_proplist(t, p) < 0) {
 | 
				
			||||||
            protocol_error(c);
 | 
					            protocol_error(c);
 | 
				
			||||||
            pa_proplist_free(p);
 | 
					            pa_proplist_free(p);
 | 
				
			||||||
| 
						 | 
					@ -1761,7 +1807,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 | 
				
			||||||
        (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
 | 
					        (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
 | 
				
			||||||
        (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
 | 
					        (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = record_stream_new(c, source, &ss, &map, &maxlength, &fragment_size, flags, p, adjust_latency);
 | 
					    s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency);
 | 
				
			||||||
    pa_proplist_free(p);
 | 
					    pa_proplist_free(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 | 
				
			||||||
| 
						 | 
					@ -2940,6 +2986,7 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
 | 
					    if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
 | 
				
			||||||
        playback_stream *s;
 | 
					        playback_stream *s;
 | 
				
			||||||
 | 
					        pa_bool_t adjust_latency = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s = pa_idxset_get_by_index(c->output_streams, idx);
 | 
					        s = pa_idxset_get_by_index(c->output_streams, idx);
 | 
				
			||||||
        CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
 | 
					        CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
 | 
				
			||||||
| 
						 | 
					@ -2952,34 +2999,28 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
 | 
				
			||||||
                    PA_TAG_U32, &prebuf,
 | 
					                    PA_TAG_U32, &prebuf,
 | 
				
			||||||
                    PA_TAG_U32, &minreq,
 | 
					                    PA_TAG_U32, &minreq,
 | 
				
			||||||
                    PA_TAG_INVALID) < 0 ||
 | 
					                    PA_TAG_INVALID) < 0 ||
 | 
				
			||||||
 | 
					            (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
 | 
				
			||||||
            !pa_tagstruct_eof(t)) {
 | 
					            !pa_tagstruct_eof(t)) {
 | 
				
			||||||
            protocol_error(c);
 | 
					            protocol_error(c);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
					        fix_playback_buffer_attr_pre(s, adjust_latency, &maxlength, &tlength, &prebuf, &minreq);
 | 
				
			||||||
            maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
					 | 
				
			||||||
        if (tlength <= 0)
 | 
					 | 
				
			||||||
            tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*1000, &s->sink_input->sample_spec);
 | 
					 | 
				
			||||||
        if (minreq <= 0)
 | 
					 | 
				
			||||||
            minreq = (tlength*9)/10;
 | 
					 | 
				
			||||||
        if (prebuf <= 0)
 | 
					 | 
				
			||||||
            prebuf = tlength;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        pa_memblockq_set_maxlength(s->memblockq, maxlength);
 | 
					        pa_memblockq_set_maxlength(s->memblockq, maxlength);
 | 
				
			||||||
        pa_memblockq_set_tlength(s->memblockq, tlength);
 | 
					        pa_memblockq_set_tlength(s->memblockq, tlength);
 | 
				
			||||||
        pa_memblockq_set_prebuf(s->memblockq, prebuf);
 | 
					        pa_memblockq_set_prebuf(s->memblockq, prebuf);
 | 
				
			||||||
        pa_memblockq_set_minreq(s->memblockq, minreq);
 | 
					        pa_memblockq_set_minreq(s->memblockq, minreq);
 | 
				
			||||||
 | 
					        fix_playback_buffer_attr_post(s, &maxlength, &tlength, &prebuf, &minreq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        reply = reply_new(tag);
 | 
					        reply = reply_new(tag);
 | 
				
			||||||
        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
 | 
					        pa_tagstruct_putu32(reply, maxlength);
 | 
				
			||||||
        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_tlength(s->memblockq));
 | 
					        pa_tagstruct_putu32(reply, tlength);
 | 
				
			||||||
        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq));
 | 
					        pa_tagstruct_putu32(reply, prebuf);
 | 
				
			||||||
        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq));
 | 
					        pa_tagstruct_putu32(reply, minreq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        record_stream *s;
 | 
					        record_stream *s;
 | 
				
			||||||
        size_t base;
 | 
					        pa_bool_t adjust_latency = FALSE;
 | 
				
			||||||
        pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
 | 
					        pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s = pa_idxset_get_by_index(c->record_streams, idx);
 | 
					        s = pa_idxset_get_by_index(c->record_streams, idx);
 | 
				
			||||||
| 
						 | 
					@ -2990,29 +3031,19 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
 | 
				
			||||||
                    PA_TAG_U32, &maxlength,
 | 
					                    PA_TAG_U32, &maxlength,
 | 
				
			||||||
                    PA_TAG_U32, &fragsize,
 | 
					                    PA_TAG_U32, &fragsize,
 | 
				
			||||||
                    PA_TAG_INVALID) < 0 ||
 | 
					                    PA_TAG_INVALID) < 0 ||
 | 
				
			||||||
 | 
					            (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
 | 
				
			||||||
            !pa_tagstruct_eof(t)) {
 | 
					            !pa_tagstruct_eof(t)) {
 | 
				
			||||||
            protocol_error(c);
 | 
					            protocol_error(c);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
					        fix_record_buffer_attr_pre(s, adjust_latency, &maxlength, &fragsize);
 | 
				
			||||||
            maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
					 | 
				
			||||||
        if (fragsize <= 0)
 | 
					 | 
				
			||||||
            fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &s->source_output->sample_spec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        pa_memblockq_set_maxlength(s->memblockq, maxlength);
 | 
					        pa_memblockq_set_maxlength(s->memblockq, maxlength);
 | 
				
			||||||
 | 
					        fix_record_buffer_attr_post(s, &maxlength, &fragsize);
 | 
				
			||||||
        base = pa_frame_size(&s->source_output->sample_spec);
 | 
					 | 
				
			||||||
        s->fragment_size = (fragsize/base)*base;
 | 
					 | 
				
			||||||
        if (s->fragment_size <= 0)
 | 
					 | 
				
			||||||
            s->fragment_size = base;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (s->fragment_size > pa_memblockq_get_maxlength(s->memblockq))
 | 
					 | 
				
			||||||
            s->fragment_size = pa_memblockq_get_maxlength(s->memblockq);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        reply = reply_new(tag);
 | 
					        reply = reply_new(tag);
 | 
				
			||||||
        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
 | 
					        pa_tagstruct_putu32(reply, maxlength);
 | 
				
			||||||
        pa_tagstruct_putu32(reply, s->fragment_size);
 | 
					        pa_tagstruct_putu32(reply, fragsize);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_pstream_send_tagstruct(c->pstream, reply);
 | 
					    pa_pstream_send_tagstruct(c->pstream, reply);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue