mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	spa-resample: don't flush too much
Also clamp the amount of input samples we push when flushing. do several rounds of zero pushing until we have flushed enough. Handle the cases where no input is needed or no output is generated. Fixes crashes when downsampling from 96000 to 1000 Hz or so.
This commit is contained in:
		
							parent
							
								
									0c24d66dc3
								
							
						
					
					
						commit
						e82145aeae
					
				
					 1 changed files with 30 additions and 25 deletions
				
			
		| 
						 | 
					@ -185,14 +185,14 @@ static int do_conversion(struct data *d)
 | 
				
			||||||
	float out[MAX_SAMPLES * channels];
 | 
						float out[MAX_SAMPLES * channels];
 | 
				
			||||||
	float ibuf[MAX_SAMPLES * channels];
 | 
						float ibuf[MAX_SAMPLES * channels];
 | 
				
			||||||
	float obuf[MAX_SAMPLES * channels];
 | 
						float obuf[MAX_SAMPLES * channels];
 | 
				
			||||||
	uint32_t in_len, out_len;
 | 
						uint32_t in_len, out_len, queued;
 | 
				
			||||||
	uint32_t pin_len, pout_len;
 | 
						uint32_t pin_len, pout_len;
 | 
				
			||||||
	size_t read, written;
 | 
						size_t read, written;
 | 
				
			||||||
	const void *src[channels];
 | 
						const void *src[channels];
 | 
				
			||||||
	void *dst[channels];
 | 
						void *dst[channels];
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
	int res, j, k, queued;
 | 
						int res, j, k;
 | 
				
			||||||
	bool flushing = false;
 | 
						uint32_t flushing = UINT32_MAX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_zero(r);
 | 
						spa_zero(r);
 | 
				
			||||||
	r.cpu_flags = d->cpu_flags;
 | 
						r.cpu_flags = d->cpu_flags;
 | 
				
			||||||
| 
						 | 
					@ -206,7 +206,6 @@ static int do_conversion(struct data *d)
 | 
				
			||||||
		return res;
 | 
							return res;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (j = 0; j < channels; j++)
 | 
						for (j = 0; j < channels; j++)
 | 
				
			||||||
		src[j] = &in[MAX_SAMPLES * j];
 | 
							src[j] = &in[MAX_SAMPLES * j];
 | 
				
			||||||
	for (j = 0; j < channels; j++)
 | 
						for (j = 0; j < channels; j++)
 | 
				
			||||||
| 
						 | 
					@ -215,25 +214,29 @@ static int do_conversion(struct data *d)
 | 
				
			||||||
	read = written = queued = 0;
 | 
						read = written = queued = 0;
 | 
				
			||||||
	while (true) {
 | 
						while (true) {
 | 
				
			||||||
		pout_len = out_len = MAX_SAMPLES;
 | 
							pout_len = out_len = MAX_SAMPLES;
 | 
				
			||||||
                in_len = SPA_MIN(MAX_SAMPLES, resample_in_len(&r, out_len)) - queued;
 | 
							in_len = SPA_MIN(MAX_SAMPLES, resample_in_len(&r, out_len));
 | 
				
			||||||
 | 
							in_len -= SPA_MIN(queued, in_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (in_len > 0) {
 | 
				
			||||||
			pin_len = in_len = sf_readf_float(d->ifile, &ibuf[queued * channels], in_len);
 | 
								pin_len = in_len = sf_readf_float(d->ifile, &ibuf[queued * channels], in_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			read += pin_len;
 | 
								read += pin_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (pin_len == 0) {
 | 
								if (pin_len == 0) {
 | 
				
			||||||
			if (flushing)
 | 
									if (flushing == 0)
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
 | 
									if (flushing == UINT32_MAX)
 | 
				
			||||||
 | 
										flushing = resample_delay(&r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			flushing = true;
 | 
									pin_len = in_len = SPA_MIN(MAX_SAMPLES, flushing);
 | 
				
			||||||
			pin_len = in_len = resample_delay(&r);
 | 
									flushing -= in_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for (k = 0, i = 0; i < pin_len; i++) {
 | 
									for (k = 0, i = 0; i < pin_len; i++) {
 | 
				
			||||||
					for (j = 0; j < channels; j++)
 | 
										for (j = 0; j < channels; j++)
 | 
				
			||||||
						ibuf[k++] = 0.0;
 | 
											ibuf[k++] = 0.0;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		in_len += queued;
 | 
							in_len += queued;
 | 
				
			||||||
		pin_len = in_len;
 | 
							pin_len = in_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -248,6 +251,7 @@ static int do_conversion(struct data *d)
 | 
				
			||||||
		if (queued)
 | 
							if (queued)
 | 
				
			||||||
			memmove(ibuf, &ibuf[pin_len * channels], queued * channels * sizeof(float));
 | 
								memmove(ibuf, &ibuf[pin_len * channels], queued * channels * sizeof(float));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (pout_len > 0) {
 | 
				
			||||||
			for (k = 0, i = 0; i < pout_len; i++) {
 | 
								for (k = 0, i = 0; i < pout_len; i++) {
 | 
				
			||||||
				for (j = 0; j < channels; j++) {
 | 
									for (j = 0; j < channels; j++) {
 | 
				
			||||||
					obuf[k++] = out[MAX_SAMPLES * j + i];
 | 
										obuf[k++] = out[MAX_SAMPLES * j + i];
 | 
				
			||||||
| 
						 | 
					@ -257,9 +261,10 @@ static int do_conversion(struct data *d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			written += pout_len;
 | 
								written += pout_len;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	if (d->verbose) {
 | 
					 | 
				
			||||||
		fprintf(stdout, "read %zu samples, wrote %zu samples\n", read, written);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (d->verbose)
 | 
				
			||||||
 | 
							fprintf(stdout, "read %zu samples, wrote %zu samples\n", read, written);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue