From: Jaechul Lee Date: Mon, 18 Dec 2023 06:18:44 +0000 (+0900) Subject: preprocessor: Fix omitting source-output memchunks sometimes X-Git-Tag: accepted/tizen/unified/20240104.012441^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=07f7fd200abe1e080f957df67f8ec08883bd3abf;p=platform%2Fcore%2Fmultimedia%2Fpulseaudio-modules-tizen.git preprocessor: Fix omitting source-output memchunks sometimes A memchunk from the source-ouput sometimes got lost because reference blocks were not buffered enough. therefore, it tries to wait for reference memblocks while keeping source memblocks. [Version] 15.0.74 [Issue Type] Update Change-Id: Iab7ff2c5b7a609f4631e56d4ff889bf6a7388511 Signed-off-by: Jaechul Lee --- diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 67a39ed..658a2df 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.73 +Version: 15.0.74 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/preprocessor/processor.c b/src/preprocessor/processor.c index 4441f54..c2bdce8 100644 --- a/src/preprocessor/processor.c +++ b/src/preprocessor/processor.c @@ -35,7 +35,7 @@ #include "processor.h" #include "processor-def.h" -#ifdef __DEBUG__ +#ifdef __PROCESSOR_DEBUG__ #include #include #include @@ -45,18 +45,18 @@ #define MEMBLOCKQ_MAXLENGTH (16 * 1024 * 1024) -#ifdef __DEBUG__ -static void debug_open_file(pa_processor *processor); -static void debug_timestamp_begin(pa_processor *processor); -static void debug_timestamp_end(pa_processor *processor); -static void debug_write_file(pa_processor *processor, int8_t *rec, int8_t *ref, int8_t *out); -static void debug_close_file(pa_processor *processor); +#ifdef __PROCESSOR_DEBUG__ +static void pa_processor_debug_open(pa_processor *processor); +static void pa_processor_debug_write(pa_processor *processor, int8_t *rec, int8_t *ref, int8_t *out); +static void pa_processor_debug_close(pa_processor *processor); +static void pa_processor_debug_timestamp_begin(pa_processor *processor); +static void pa_processor_debug_timestamp_end(pa_processor *processor); #else -#define debug_open_file(x) -#define debug_timestamp_begin(x) -#define debug_timestamp_end(x) -#define debug_write_file(x, a, b, c) -#define debug_close_file(x) +#define pa_processor_debug_open(x) +#define pa_processor_debug_write(x, a, b, c) +#define pa_processor_debug_close(x) +#define pa_processor_debug_timestamp_begin(x) +#define pa_processor_debug_timestamp_end(x) #endif struct method_info { @@ -210,7 +210,7 @@ pa_processor *pa_processor_new(pa_core *core, pa_usec_to_bytes(processor->process_usec, &processor->ss), pa_processor_method_str(method)); - debug_open_file(processor); + pa_processor_debug_open(processor); return processor; @@ -232,7 +232,7 @@ void pa_processor_free(pa_processor *processor) { if (processor->reference) pa_processor_reference_free(processor->reference); - debug_close_file(processor); + pa_processor_debug_close(processor); pa_xfree(processor); } @@ -249,6 +249,19 @@ pa_usec_t pa_processor_get_process_usec(pa_processor *p) { return p->process_usec; } +bool pa_processor_is_available(pa_processor *processor) { + pa_assert(processor); + + if (!processor->reference) + return true; + + /* processor will use a silence memblock when bypass is set. */ + if (pa_processor_reference_get_bypass(processor->reference)) + return true; + + return pa_processor_reference_is_available(processor->reference); +} + /* Do not touch chunk value */ int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) { int8_t *recording = NULL; @@ -256,6 +269,7 @@ int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) { int8_t *output = NULL; pa_memchunk rchunk, ochunk; + bool use_silence = false; pa_assert(processor); pa_assert(processor->result_memblockq); @@ -264,17 +278,11 @@ int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) { if (processor->reference) { if (pa_processor_reference_get_bypass(processor->reference)) { - if (pa_memblockq_push(processor->result_memblockq, chunk) < 0) - pa_log_error("Bypass failed to push out chunk to result memblockq"); - - pa_log_debug("Bypass method(%d:%s). because reference sink isn't working now", - processor->method, pa_processor_method_str(processor->method)); - return 0; - } - - if (pa_processor_reference_pull(processor->reference, &rchunk) < 0) { - pa_log_debug("Underrun the reference memblock during a fall duplex situation. Buffering more reference memblocks."); - return -PROCESSOR_ERR_BUFFERING; + /* use silence memblock */ + use_silence = true; + pa_processor_reference_pull_silence(processor->reference, &rchunk); + } else { + pa_assert(pa_processor_reference_pull(processor->reference, &rchunk) == 0); } reference = pa_memblock_acquire_chunk(&rchunk); @@ -287,15 +295,15 @@ int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) { recording = (int8_t *)pa_memblock_acquire_chunk(chunk); output = (int8_t *)pa_memblock_acquire_chunk(&ochunk); - debug_timestamp_begin(processor); + pa_processor_debug_timestamp_begin(processor); if (audio_effect_process_reference(processor->audio_effect, recording, reference, output) < 0) { pa_log_warn("Failed to process memchunk"); goto fail; } - debug_timestamp_end(processor); - debug_write_file(processor, recording, reference, output); + pa_processor_debug_timestamp_end(processor); + pa_processor_debug_write(processor, recording, reference, output); pa_memblock_release(chunk->memblock); pa_memblock_release(ochunk.memblock); @@ -321,7 +329,7 @@ int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) { if (processor->reference) { pa_memblock_release(rchunk.memblock); - pa_processor_reference_drop(processor->reference, &rchunk); + pa_processor_reference_drop(processor->reference, &rchunk, use_silence); } /* Keep this memchunk for next processor */ @@ -339,7 +347,7 @@ fail: if (processor->reference) { pa_memblock_release(rchunk.memblock); - pa_processor_reference_drop(processor->reference, &rchunk); + pa_processor_reference_drop(processor->reference, &rchunk, use_silence); } pa_memblock_unref(ochunk.memblock); @@ -396,64 +404,82 @@ pa_processor_reference *pa_processor_get_reference(pa_processor *processor) { return processor->reference; } -#ifdef __DEBUG__ -static void debug_open_file(pa_processor *processor) { - static int n = 1; +#ifdef __PROCESSOR_DEBUG__ +static void pa_processor_debug_open(pa_processor *processor) { char rec[64], ref[64], out[64]; const char *method = pa_processor_method_str(processor->method); + int flags = O_CREAT | O_WRONLY | O_TRUNC; - snprintf(rec, sizeof(rec), "/tmp/processor-%s-rec-%d.raw", method, n); - snprintf(ref, sizeof(ref), "/tmp/processor-%s-ref-%d.raw", method, n); - snprintf(out, sizeof(out), "/tmp/processor-%s-out-%d.raw", method, n); - n += 1; + snprintf(rec, sizeof(rec), "/tmp/processor-%s-rec.raw", method); + snprintf(ref, sizeof(ref), "/tmp/processor-%s-ref.raw", method); + snprintf(out, sizeof(out), "/tmp/processor-%s-out.raw", method); unlink(rec); unlink(ref); unlink(out); - processor->fdrec = open(rec, O_RDWR | O_CREAT | O_TRUNC, 777); - processor->fdref = open(ref, O_RDWR | O_CREAT | O_TRUNC, 777); - processor->fdout = open(out, O_RDWR | O_CREAT | O_TRUNC, 777); -} - -static void debug_timestamp_begin(pa_processor *processor) { - gettimeofday(&processor->before, NULL); -} + processor->fd_rec = open(rec, flags, 777); + if (processor->fd_rec < 0) { + pa_log_error("Failed to open an rec dump file"); + return; + } -static void debug_timestamp_end(pa_processor *processor) { - gettimeofday(&processor->after, NULL); + processor->fd_ref = open(ref, flags, 777); + if (processor->fd_ref < 0) { + pa_log_error("Failed to open an ref dump file"); + return; + } - pa_log_debug("It takes time (%ld)ms.", - 1000 * (processor->after.tv_sec - processor->before.tv_sec) - + (processor->after.tv_usec - processor->before.tv_usec) / 1000); + processor->fd_out = open(out, flags, 777); + if (processor->fd_out < 0) { + pa_log_error("Failed to open an out dump file"); + return; + } } -static void debug_write_file(pa_processor *processor, int8_t *rec, int8_t *ref, int8_t *out) { - if (rec && write(processor->fdrec, rec, processor->process_bytes) <= 0) +static void pa_processor_debug_write(pa_processor *processor, int8_t *rec, int8_t *ref, int8_t *out) { + pa_assert(processor); + pa_assert(rec); + pa_assert(out); + + if (write(processor->fd_rec, rec, processor->process_bytes) <= 0) pa_log_error("Failed to write recording buffer"); - if (ref && write(processor->fdref, ref, pa_processor_reference_process_usec_to_bytes(processor->reference)) <= 0) + if (ref && write(processor->fd_ref, ref, pa_processor_reference_process_usec_to_bytes(processor->reference)) <= 0) pa_log_error("Failed to write reference buffer"); - if (out && write(processor->fdout, out, processor->process_bytes) <= 0) + if (write(processor->fd_out, out, processor->process_bytes) <= 0) pa_log_error("Failed to write ref buffer"); } -static void debug_close_file(pa_processor *processor) { - if (processor->fdrec) { - close(processor->fdrec); - processor->fdrec = -1; +static void pa_processor_debug_close(pa_processor *processor) { + if (processor->fd_rec) { + close(processor->fd_rec); + processor->fd_rec = -1; } - if (processor->fdref) { - close(processor->fdref); - processor->fdref = -1; + if (processor->fd_ref) { + close(processor->fd_ref); + processor->fd_ref = -1; } - if (processor->fdout) { - close(processor->fdout); - processor->fdout = -1; + if (processor->fd_out) { + close(processor->fd_out); + processor->fd_out = -1; } } + +static void pa_processor_debug_timestamp_begin(pa_processor *processor) { + gettimeofday(&processor->before, NULL); +} + +static void pa_processor_debug_timestamp_end(pa_processor *processor) { + gettimeofday(&processor->after, NULL); + + pa_log_debug("It takes time (%ld)ms.", + 1000 * (processor->after.tv_sec - processor->before.tv_sec) + + (processor->after.tv_usec - processor->before.tv_usec) / 1000); +} + #endif diff --git a/src/preprocessor/processor.h b/src/preprocessor/processor.h index a4f7152..6e66e65 100644 --- a/src/preprocessor/processor.h +++ b/src/preprocessor/processor.h @@ -50,8 +50,10 @@ typedef struct pa_processor { pa_processor_method_t method; pa_processor_reference *reference; -#ifdef __DEBUG__ - int fdrec, fdref, fdout; +#ifdef __PROCESSOR_DEBUG__ + int fd_rec; + int fd_ref; + int fd_out; struct timeval before, after; #endif } pa_processor; @@ -68,6 +70,8 @@ pa_memblockq *pa_processor_get_result_memblockq(pa_processor *processor); size_t pa_processor_get_process_bytes(pa_processor *p); pa_usec_t pa_processor_get_process_usec(pa_processor *p); +bool pa_processor_is_available(pa_processor *processor); + /* reference */ void pa_processor_attach_reference(pa_processor *processor, pa_processor_reference *reference); pa_processor_reference *pa_processor_get_reference(pa_processor *processor); diff --git a/src/preprocessor/processor_holder.c b/src/preprocessor/processor_holder.c index 177e9bd..1b83afc 100644 --- a/src/preprocessor/processor_holder.c +++ b/src/preprocessor/processor_holder.c @@ -36,6 +36,39 @@ #define MEMBLOCKQ_MAXLENGTH (16*1024*1024) #define DEFAULT_PREBUFFER_MSEC (50) +#ifdef __PROCESSOR_HOLDER_DEBUG__ +#include +#include +#include +#include +#include + +enum debug_target { + PA_PROCESSOR_HOLDER_DEBUG_INPUT_BUFFER, + PA_PROCESSOR_HOLDER_DEBUG_OUTPUT_BUFFER, + PA_PROCESSOR_HOLDER_DEBUG_REFERENCE_BUFFER, + PA_PROCESSOR_HOLDER_DEBUG_BUFFER_MAX +}; + +static void pa_processor_holder_debug_open_file(pa_processor_holder *holder); +static void pa_processor_holder_debug_write_buffer(pa_processor_holder *holder, int target, pa_memchunk *chunk); +static void pa_processor_holder_debug_close_fd(pa_processor_holder *holder); + +#define pa_processor_holder_debug_write_input_buffer(x, y) \ + pa_processor_holder_debug_write_buffer(x, PA_PROCESSOR_HOLDER_DEBUG_INPUT_BUFFER, y) +#define pa_processor_holder_debug_write_output_buffer(x, y) \ + pa_processor_holder_debug_write_buffer(x, PA_PROCESSOR_HOLDER_DEBUG_OUTPUT_BUFFER, y) +#define pa_processor_holder_debug_write_reference_buffer(x, y) \ + pa_processor_holder_debug_write_buffer(x, PA_PROCESSOR_HOLDER_DEBUG_REFERENCE_BUFFER, y) + +#else +#define pa_processor_holder_debug_open_file(x) +#define pa_processor_holder_debug_write_input_buffer(x, y) +#define pa_processor_holder_debug_write_output_buffer(x, y) +#define pa_processor_holder_debug_write_reference_buffer(x, y) +#define pa_processor_holder_debug_close_fd(x) +#endif + pa_processor_holder *pa_processor_holder_new(pa_core *core, pa_sample_spec *ss) { pa_processor_holder *holder; pa_memchunk silence; @@ -68,6 +101,8 @@ pa_processor_holder *pa_processor_holder_new(pa_core *core, pa_sample_spec *ss) pa_memblock_unref(silence.memblock); + pa_processor_holder_debug_open_file(holder); + return holder; } @@ -103,6 +138,8 @@ int pa_processor_holder_push_data(pa_processor_holder *holder, pa_memchunk *chun ret = pa_memblockq_push(holder->input, chunk); + pa_processor_holder_debug_write_input_buffer(holder, chunk); + pa_log_debug("push data to the input queue. chunk length(%zu), memblockq length(%zu)", chunk->length, pa_memblockq_get_length(holder->input)); @@ -114,6 +151,8 @@ int pa_processor_holder_push_reference_data(pa_processor_holder *holder, pa_memc pa_assert(chunk); pa_assert(holder->reference); + pa_processor_holder_debug_write_reference_buffer(holder, chunk); + return pa_processor_reference_push(holder->reference, chunk); } @@ -129,6 +168,8 @@ int pa_processor_holder_pull_data(pa_processor_holder *holder, pa_memchunk *chun if ((r = pa_memblockq_peek_fixed_size(holder->output, length, chunk)) < 0) pa_log_error("Failed to get memblock from output memblockq"); + pa_processor_holder_debug_write_output_buffer(holder, chunk); + /* chunk ref count must be one after dropping */ pa_memblockq_drop(holder->output, chunk->length); @@ -169,17 +210,18 @@ int pa_processor_holder_pump(pa_processor_holder *holder) { } while (length >= process_size) { + /* the length of the reference must be checked before calling by pa_processor_reference_is_available */ + if (!pa_processor_is_available(p)) { + pa_log_error("reference need to be pushed"); + return -PROCESSOR_ERR_BUFFERING; + } + ret = pa_memblockq_peek_fixed_size(pull_queue, process_size, &chunk); pa_assert(!ret); if ((ret = pa_processor_process(p, &chunk)) < 0) { pa_memblock_unref(chunk.memblock); - pa_memblockq_drop(pull_queue, chunk.length); - if (ret == -PROCESSOR_ERR_BUFFERING) - pa_log_debug("Buffering reference memblocks."); - else - pa_log_warn("Failed to process memblock. ret(%d)", ret); - + pa_log_warn("Failed to process memblock. ret(%d)", ret); return ret; } @@ -289,3 +331,83 @@ void pa_processor_holder_dump(pa_processor_holder *holder) { pa_memblockq_get_write_index(pull_queue), pa_memblockq_get_write_index(pull_queue)); } + +#ifdef __PROCESSOR_HOLDER_DEBUG__ +static void pa_processor_holder_debug_open_file(pa_processor_holder *holder) { + pa_assert(holder); + + char filename[64]; + int flags = O_CREAT | O_WRONLY | O_TRUNC; + + snprintf(filename, sizeof(filename), "/tmp/processor-holder-in-buffer.raw"); + unlink(filename); + holder->fd_in = open(filename, flags, 777); + if (holder->fd_in < 0) { + pa_log_error("Failed to open an input buffer debug file"); + return; + } + + snprintf(filename, sizeof(filename), "/tmp/processor-holder-out-buffer.raw"); + unlink(filename); + holder->fd_out = open(filename, flags, 777); + if (holder->fd_out < 0) { + pa_log_error("Failed to open an output buffer debug file"); + return; + } + + snprintf(filename, sizeof(filename), "/tmp/processor-holder-ref-buffer.raw"); + unlink(filename); + holder->fd_ref = open(filename, flags, 777); + if (holder->fd_ref < 0) { + pa_log_error("Failed to open an reference buffer debug file"); + return; + } +} + +static void pa_processor_holder_debug_write_buffer(pa_processor_holder *holder, int target, pa_memchunk *chunk) { + int8_t *p; + int fd; + + pa_assert(holder); + pa_assert(chunk); + + switch (target) { + case PA_PROCESSOR_HOLDER_DEBUG_INPUT_BUFFER: + fd = holder->fd_in; + break; + case PA_PROCESSOR_HOLDER_DEBUG_OUTPUT_BUFFER: + fd = holder->fd_out; + break; + case PA_PROCESSOR_HOLDER_DEBUG_REFERENCE_BUFFER: + fd = holder->fd_ref; + break; + default: + pa_assert_not_reached(); + } + + p = (int8_t *)pa_memblock_acquire_chunk(chunk); + + if (write(fd, p, chunk->length) < 0) + pa_log_error("Failed to write debug buffer. fd(%d), target(%d)", fd, target); + + pa_memblock_release(chunk->memblock); +} + +static void pa_processor_holder_debug_close_fd(pa_processor_holder *holder) { + if (holder->fd_in > 0) { + close(holder->fd_in); + holder->fd_in = -1; + } + + if (holder->fd_out > 0) { + close(holder->fd_out); + holder->fd_out = -1; + } + + if (holder->fd_ref > 0) { + close(holder->fd_ref); + holder->fd_ref = -1; + } +} +#endif + diff --git a/src/preprocessor/processor_holder.h b/src/preprocessor/processor_holder.h index 7ba0275..6dde8e2 100644 --- a/src/preprocessor/processor_holder.h +++ b/src/preprocessor/processor_holder.h @@ -41,6 +41,11 @@ typedef struct pa_processor_holder { bool enable; void *data1; void *data2; +#ifdef __PROCESSOR_HOLDER_DEBUG__ + int fd_in; + int fd_out; + int fd_ref; +#endif } pa_processor_holder; pa_processor_holder *pa_processor_holder_new(pa_core *core, pa_sample_spec *ss); diff --git a/src/preprocessor/processor_reference.c b/src/preprocessor/processor_reference.c index a4fc660..22a6076 100644 --- a/src/preprocessor/processor_reference.c +++ b/src/preprocessor/processor_reference.c @@ -207,10 +207,19 @@ int pa_processor_reference_push(pa_processor_reference *reference, pa_memchunk * return r; } +void pa_processor_reference_pull_silence(pa_processor_reference *reference, pa_memchunk *chunk) { + pa_assert(reference); + pa_assert(chunk); + + pa_silence_memchunk_get(&reference->core->silence_cache, + reference->core->mempool, chunk, + &reference->ss, + pa_usec_to_bytes(reference->process_usec, &reference->ss)); +} + int pa_processor_reference_pull(pa_processor_reference *reference, pa_memchunk *chunk) { int r; size_t length; - size_t memblock_length; pa_assert(reference); pa_assert(chunk); @@ -241,11 +250,8 @@ int pa_processor_reference_pull(pa_processor_reference *reference, pa_memchunk * } exit: - memblock_length = pa_memblockq_get_length(reference->memblockq); - - /* Needs to gather more reference memblocks */ - if (memblock_length < length) - return -1; + /* memblockq must have 1 block at least */ + pa_assert(pa_memblockq_get_length(reference->memblockq) >= length); if ((r = pa_memblockq_peek_fixed_size(reference->memblockq, length, chunk)) < 0) { pa_log_error("Failed to get memblock from reference memblockq"); @@ -288,11 +294,15 @@ void pa_processor_reference_add_latency_padding(pa_processor_reference *referenc read_index, pa_memblockq_get_read_index(reference->memblockq)); } -void pa_processor_reference_drop(pa_processor_reference *reference, pa_memchunk *chunk) { +void pa_processor_reference_drop(pa_processor_reference *reference, pa_memchunk *chunk, bool is_silence) { pa_assert(reference); pa_assert(chunk); pa_memblock_unref(chunk->memblock); + + if (is_silence) + return; + pa_memblockq_drop(reference->memblockq, chunk->length); } @@ -367,3 +377,9 @@ pa_processor_reference_method_t pa_processor_reference_method_enum(const char *m return m; } + +bool pa_processor_reference_is_available(pa_processor_reference *reference) { + pa_assert(reference); + + return pa_memblockq_get_length(reference->memblockq) >= reference->process_bytes; +} diff --git a/src/preprocessor/processor_reference.h b/src/preprocessor/processor_reference.h index b126aa9..08ad04a 100644 --- a/src/preprocessor/processor_reference.h +++ b/src/preprocessor/processor_reference.h @@ -49,16 +49,21 @@ void pa_processor_reference_free(pa_processor_reference *reference); void pa_processor_reference_reset(pa_processor_reference *reference); int pa_processor_reference_push(pa_processor_reference *reference, pa_memchunk *chunk); int pa_processor_reference_pull(pa_processor_reference *reference, pa_memchunk *chunk); +void pa_processor_reference_pull_silence(pa_processor_reference *reference, pa_memchunk *chunk); void pa_processor_reference_add_latency_padding(pa_processor_reference *reference, pa_usec_t latency); -void pa_processor_reference_drop(pa_processor_reference *reference, pa_memchunk *chunk); +void pa_processor_reference_drop(pa_processor_reference *reference, pa_memchunk *chunk, bool is_silence); + unsigned pa_processor_reference_get_nblocks(pa_processor_reference *reference); pa_usec_t pa_processor_reference_chunk_to_usec(pa_processor_reference *reference, pa_memchunk *chunk); size_t pa_processor_reference_process_usec_to_bytes(pa_processor_reference *reference); char *pa_processor_reference_dump_index(pa_processor_reference *reference); + void pa_processor_reference_set_bypass(pa_processor_reference *reference, bool bypass); bool pa_processor_reference_get_bypass(pa_processor_reference *reference); pa_sink *pa_processor_reference_get_sink(pa_processor_reference *reference); pa_processor_reference_method_t pa_processor_reference_method_enum(const char *method); +bool pa_processor_reference_is_available(pa_processor_reference *reference); + #endif