mirror of https://github.com/mpv-player/mpv
af_scaletempo2: migrate to internals to talloc
Fixes corrupted audio after resize_input_buffer; realloc_2d did not move data to new location. Rather than reimplementing more allocator logic, migrate internals to use talloc and grow buffer with realloc.
This commit is contained in:
parent
190b15c827
commit
773c5e2ae0
|
@ -8,7 +8,7 @@
|
|||
#include "options/m_option.h"
|
||||
|
||||
struct priv {
|
||||
struct mp_scaletempo2 data;
|
||||
struct mp_scaletempo2 *data;
|
||||
struct mp_pin *in_pin;
|
||||
struct mp_aframe *cur_format;
|
||||
struct mp_aframe_pool *out_pool;
|
||||
|
@ -29,7 +29,7 @@ static void af_scaletempo2_process(struct mp_filter *f)
|
|||
return;
|
||||
|
||||
while (!p->initialized || !p->pending ||
|
||||
!mp_scaletempo2_frames_available(&p->data, p->speed))
|
||||
!mp_scaletempo2_frames_available(p->data, p->speed))
|
||||
{
|
||||
bool eof = false;
|
||||
if (!p->pending || !mp_aframe_get_size(p->pending)) {
|
||||
|
@ -64,16 +64,16 @@ static void af_scaletempo2_process(struct mp_filter *f)
|
|||
if (p->pending && !format_change && !p->sent_final) {
|
||||
int frame_size = mp_aframe_get_size(p->pending);
|
||||
uint8_t **planes = mp_aframe_get_data_ro(p->pending);
|
||||
int read = mp_scaletempo2_fill_input_buffer(&p->data,
|
||||
int read = mp_scaletempo2_fill_input_buffer(p->data,
|
||||
planes, frame_size, p->speed);
|
||||
mp_aframe_skip_samples(p->pending, read);
|
||||
}
|
||||
if (final && p->pending && !p->sent_final) {
|
||||
mp_scaletempo2_set_final(&p->data);
|
||||
mp_scaletempo2_set_final(p->data);
|
||||
p->sent_final = true;
|
||||
}
|
||||
|
||||
if (mp_scaletempo2_frames_available(&p->data, p->speed)) {
|
||||
if (mp_scaletempo2_frames_available(p->data, p->speed)) {
|
||||
if (eof) {
|
||||
mp_pin_out_repeat_eof(p->in_pin); // drain more next time
|
||||
}
|
||||
|
@ -89,9 +89,9 @@ static void af_scaletempo2_process(struct mp_filter *f)
|
|||
}
|
||||
|
||||
assert(p->pending);
|
||||
if (mp_scaletempo2_frames_available(&p->data, p->speed)) {
|
||||
if (mp_scaletempo2_frames_available(p->data, p->speed)) {
|
||||
struct mp_aframe *out = mp_aframe_new_ref(p->cur_format);
|
||||
int out_samples = p->data.ola_hop_size;
|
||||
int out_samples = p->data->ola_hop_size;
|
||||
if (mp_aframe_pool_allocate(p->out_pool, out, out_samples) < 0) {
|
||||
talloc_free(out);
|
||||
goto error;
|
||||
|
@ -101,14 +101,14 @@ static void af_scaletempo2_process(struct mp_filter *f)
|
|||
|
||||
uint8_t **planes = mp_aframe_get_data_rw(out);
|
||||
assert(planes);
|
||||
assert(mp_aframe_get_planes(out) == p->data.channels);
|
||||
assert(mp_aframe_get_planes(out) == p->data->channels);
|
||||
|
||||
out_samples = mp_scaletempo2_fill_buffer(&p->data,
|
||||
out_samples = mp_scaletempo2_fill_buffer(p->data,
|
||||
(float**)planes, out_samples, p->speed);
|
||||
|
||||
double pts = mp_aframe_get_pts(p->pending);
|
||||
if (pts != MP_NOPTS_VALUE) {
|
||||
double frame_delay = mp_scaletempo2_get_latency(&p->data, p->speed)
|
||||
double frame_delay = mp_scaletempo2_get_latency(p->data, p->speed)
|
||||
+ out_samples * p->speed;
|
||||
mp_aframe_set_pts(out, pts - frame_delay / mp_aframe_get_effective_rate(out));
|
||||
|
||||
|
@ -122,7 +122,7 @@ static void af_scaletempo2_process(struct mp_filter *f)
|
|||
|
||||
// reset the filter to ensure it stops generating audio
|
||||
// and mp_scaletempo2_frames_available returns false
|
||||
mp_scaletempo2_reset(&p->data);
|
||||
mp_scaletempo2_reset(p->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ static bool init_scaletempo2(struct mp_filter *f)
|
|||
p->sent_final = false;
|
||||
mp_aframe_config_copy(p->cur_format, p->pending);
|
||||
|
||||
mp_scaletempo2_init(&p->data, mp_aframe_get_channels(p->pending),
|
||||
mp_scaletempo2_init(p->data, mp_aframe_get_channels(p->pending),
|
||||
mp_aframe_get_rate(p->pending));
|
||||
|
||||
return true;
|
||||
|
@ -172,7 +172,7 @@ static bool af_scaletempo2_command(struct mp_filter *f, struct mp_filter_command
|
|||
static void af_scaletempo2_reset(struct mp_filter *f)
|
||||
{
|
||||
struct priv *p = f->priv;
|
||||
mp_scaletempo2_reset(&p->data);
|
||||
mp_scaletempo2_reset(p->data);
|
||||
p->initialized = false;
|
||||
TA_FREEP(&p->pending);
|
||||
}
|
||||
|
@ -180,8 +180,8 @@ static void af_scaletempo2_reset(struct mp_filter *f)
|
|||
static void af_scaletempo2_destroy(struct mp_filter *f)
|
||||
{
|
||||
struct priv *p = f->priv;
|
||||
mp_scaletempo2_destroy(&p->data);
|
||||
talloc_free(p->pending);
|
||||
TA_FREEP(&p->data);
|
||||
TA_FREEP(&p->pending);
|
||||
}
|
||||
|
||||
static const struct mp_filter_info af_scaletempo2_filter = {
|
||||
|
@ -206,7 +206,8 @@ static struct mp_filter *af_scaletempo2_create(
|
|||
mp_filter_add_pin(f, MP_PIN_OUT, "out");
|
||||
|
||||
struct priv *p = f->priv;
|
||||
p->data.opts = talloc_steal(p, options);
|
||||
p->data = talloc_zero(p, struct mp_scaletempo2);
|
||||
p->data->opts = talloc_steal(p, options);
|
||||
p->speed = 1.0;
|
||||
p->cur_format = talloc_steal(p, mp_aframe_create());
|
||||
p->out_pool = mp_aframe_pool_create(p);
|
||||
|
|
|
@ -41,14 +41,15 @@ static bool in_interval(int n, struct interval q)
|
|||
return n >= q.lo && n <= q.hi;
|
||||
}
|
||||
|
||||
static float **realloc_2d(float **p, int x, int y)
|
||||
static void alloc_sample_buffer(struct mp_scaletempo2 *p, float ***ptr, size_t size)
|
||||
{
|
||||
float **array = realloc(p, sizeof(float*) * x + sizeof(float) * x * y);
|
||||
float* data = (float*) (array + x);
|
||||
for (int i = 0; i < x; ++i) {
|
||||
array[i] = data + i * y;
|
||||
talloc_free(*ptr);
|
||||
|
||||
float **buff = talloc_array(p, float*, p->channels);
|
||||
for (int i = 0; i < p->channels; ++i) {
|
||||
buff[i] = talloc_array(buff, float, size);
|
||||
}
|
||||
return array;
|
||||
*ptr = buff;
|
||||
}
|
||||
|
||||
static void zero_2d_partial(float **a, int x, int y)
|
||||
|
@ -475,12 +476,6 @@ static bool can_perform_wsola(struct mp_scaletempo2 *p, double playback_rate)
|
|||
return frames_needed(p, playback_rate) <= 0;
|
||||
}
|
||||
|
||||
static void resize_input_buffer(struct mp_scaletempo2 *p, int size)
|
||||
{
|
||||
p->input_buffer_size = size;
|
||||
p->input_buffer = realloc_2d(p->input_buffer, p->channels, size);
|
||||
}
|
||||
|
||||
// pad end with silence until a wsola iteration can be performed
|
||||
static void add_input_buffer_final_silence(struct mp_scaletempo2 *p, double playback_rate)
|
||||
{
|
||||
|
@ -488,11 +483,9 @@ static void add_input_buffer_final_silence(struct mp_scaletempo2 *p, double play
|
|||
if (needed <= 0)
|
||||
return; // no silence needed for iteration
|
||||
|
||||
int required_size = needed + p->input_buffer_frames;
|
||||
if (required_size > p->input_buffer_size)
|
||||
resize_input_buffer(p, required_size);
|
||||
|
||||
int last_index = needed + p->input_buffer_frames - 1;
|
||||
for (int i = 0; i < p->channels; ++i) {
|
||||
MP_TARRAY_GROW(p, p->input_buffer[i], last_index);
|
||||
float *ch_input = p->input_buffer[i];
|
||||
for (int j = 0; j < needed; ++j) {
|
||||
ch_input[p->input_buffer_frames + j] = 0.0f;
|
||||
|
@ -518,11 +511,9 @@ int mp_scaletempo2_fill_input_buffer(struct mp_scaletempo2 *p,
|
|||
if (read == 0)
|
||||
return 0;
|
||||
|
||||
int required_size = read + p->input_buffer_frames;
|
||||
if (required_size > p->input_buffer_size)
|
||||
resize_input_buffer(p, required_size);
|
||||
|
||||
int last_index = read + p->input_buffer_frames - 1;
|
||||
for (int i = 0; i < p->channels; ++i) {
|
||||
MP_TARRAY_GROW(p, p->input_buffer[i], last_index);
|
||||
memcpy(p->input_buffer[i] + p->input_buffer_frames,
|
||||
planes[i], read * sizeof(float));
|
||||
}
|
||||
|
@ -766,18 +757,6 @@ bool mp_scaletempo2_frames_available(struct mp_scaletempo2 *p, double playback_r
|
|||
|| p->num_complete_frames > 0;
|
||||
}
|
||||
|
||||
void mp_scaletempo2_destroy(struct mp_scaletempo2 *p)
|
||||
{
|
||||
free(p->ola_window);
|
||||
free(p->transition_window);
|
||||
free(p->wsola_output);
|
||||
free(p->optimal_block);
|
||||
free(p->search_block);
|
||||
free(p->target_block);
|
||||
free(p->input_buffer);
|
||||
free(p->energy_candidate_blocks);
|
||||
}
|
||||
|
||||
void mp_scaletempo2_reset(struct mp_scaletempo2 *p)
|
||||
{
|
||||
p->input_buffer_frames = 0;
|
||||
|
@ -840,26 +819,26 @@ void mp_scaletempo2_init(struct mp_scaletempo2 *p, int channels, int rate)
|
|||
// 1, ... |num_candidate_blocks|
|
||||
p->search_block_center_offset = p->num_candidate_blocks / 2
|
||||
+ (p->ola_window_size / 2 - 1);
|
||||
p->ola_window = realloc(p->ola_window, sizeof(float) * p->ola_window_size);
|
||||
MP_RESIZE_ARRAY(p, p->ola_window, p->ola_window_size);
|
||||
get_symmetric_hanning_window(p->ola_window_size, p->ola_window);
|
||||
p->transition_window = realloc(p->transition_window,
|
||||
sizeof(float) * p->ola_window_size * 2);
|
||||
MP_RESIZE_ARRAY(p, p->transition_window, p->ola_window_size * 2);
|
||||
get_symmetric_hanning_window(2 * p->ola_window_size, p->transition_window);
|
||||
|
||||
p->wsola_output_size = p->ola_window_size + p->ola_hop_size;
|
||||
p->wsola_output = realloc_2d(p->wsola_output, p->channels, p->wsola_output_size);
|
||||
alloc_sample_buffer(p, &p->wsola_output, p->wsola_output_size);
|
||||
|
||||
// Auxiliary containers.
|
||||
p->optimal_block = realloc_2d(p->optimal_block, p->channels, p->ola_window_size);
|
||||
alloc_sample_buffer(p, &p->optimal_block, p->ola_window_size);
|
||||
p->search_block_size = p->num_candidate_blocks + (p->ola_window_size - 1);
|
||||
p->search_block = realloc_2d(p->search_block, p->channels, p->search_block_size);
|
||||
p->target_block = realloc_2d(p->target_block, p->channels, p->ola_window_size);
|
||||
alloc_sample_buffer(p, &p->search_block, p->search_block_size);
|
||||
alloc_sample_buffer(p, &p->target_block, p->ola_window_size);
|
||||
|
||||
resize_input_buffer(p, 4 * MPMAX(p->ola_window_size, p->search_block_size));
|
||||
p->input_buffer_frames = 0;
|
||||
p->input_buffer_final_frames = 0;
|
||||
p->input_buffer_added_silence = 0;
|
||||
size_t initial_size = 4 * MPMAX(p->ola_window_size, p->search_block_size);
|
||||
alloc_sample_buffer(p, &p->input_buffer, initial_size);
|
||||
|
||||
p->energy_candidate_blocks = realloc(p->energy_candidate_blocks,
|
||||
sizeof(float) * p->channels * p->num_candidate_blocks);
|
||||
MP_RESIZE_ARRAY(p, p->energy_candidate_blocks,
|
||||
p->channels * p->num_candidate_blocks);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,6 @@ struct mp_scaletempo2 {
|
|||
float **target_block;
|
||||
// Buffered audio data.
|
||||
float **input_buffer;
|
||||
int input_buffer_size;
|
||||
int input_buffer_frames;
|
||||
// How many frames in |input_buffer| need to be flushed by padding with
|
||||
// silence to process the final packet. While this is nonzero, the filter
|
||||
|
|
Loading…
Reference in New Issue