preprocessor: Add bypass functionality 63/301663/4 accepted/tizen/unified/20231122.172550 accepted/tizen/unified/riscv/20231215.050530
authorJaechul Lee <jcsing.lee@samsung.com>
Tue, 21 Nov 2023 07:48:30 +0000 (16:48 +0900)
committerJaechul Lee <jcsing.lee@samsung.com>
Wed, 22 Nov 2023 01:00:50 +0000 (10:00 +0900)
A source-output is stuck when the sink doesn't feed reference data enough.
So, bypass mode was added in case there wasn't sink-inputs.

[Version] 15.0.69
[Issue Type] Update

Change-Id: I1e2a58723d6f2facada2d578bb35c51c9821eb40
Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
packaging/pulseaudio-modules-tizen.spec
src/module-tizenaudio-sink.c
src/preprocessor/module-tizenaudio-preprocessor.c
src/preprocessor/processor-def.h
src/preprocessor/processor.c
src/preprocessor/processor_holder.c
src/preprocessor/processor_reference.c
src/preprocessor/processor_reference.h
src/tizenaudio-sink2.c

index 8d6e842788fb80bbb41d568e8b39f5e1c5becc62..8736ad12ce8aba695b6c3edbb2de843a8c1c6e75 100644 (file)
@@ -2,7 +2,7 @@
 
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          15.0.68
+Version:          15.0.69
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 010f64fb4356b9cf78a2c9f1db7545fbb5801cf6..e91aafd3c5a94a6d48a19802e5e50f8116e3e17a 100644 (file)
@@ -349,7 +349,11 @@ static int sink_process_msg(
                 u->preprocess_on = true;
                 pa_asyncmsgq_post(u->preprocessor_asyncmsgq, u->preprocessor,
                                     PA_SOURCE_MESSAGE_PREPROCESSOR_RESET_REFERENCE, (void *)true, 0, NULL, NULL);
+                pa_asyncmsgq_post(u->preprocessor_asyncmsgq, u->preprocessor,
+                                    PA_SOURCE_MESSAGE_PREPROCESSOR_REFERENCE_BYPASS, u->holder, (int64_t)false, NULL, NULL);
             } else {
+                pa_asyncmsgq_post(u->preprocessor_asyncmsgq, u->preprocessor,
+                                    PA_SOURCE_MESSAGE_PREPROCESSOR_REFERENCE_BYPASS, u->holder, (int64_t)true, NULL, NULL);
                 u->preprocess_on = false;
             }
 
index 5b64cfbd8f6ba9337f71657c9e49fbcbd81f2e40..f8527a01150b8ee2e59cb3f2c18a650fffc5500c 100644 (file)
@@ -511,7 +511,7 @@ static int process_msg(
             if (u->reset_lazy_reference) {
                 pa_processor_reference_reset(reference);
                 pa_processor_reference_add_latency_padding(reference, get_round_trip_latency(source, sink));
-
+                pa_processor_reference_set_bypass(reference, false);
                 u->reset_lazy_reference = false;
             }
 
@@ -528,6 +528,21 @@ static int process_msg(
                 u->reset_lazy_reference = true;
 
             break;
+        case PA_SOURCE_MESSAGE_PREPROCESSOR_REFERENCE_BYPASS: {
+            pa_processor_holder *holder = (pa_processor_holder *)data;
+            pa_processor_reference *reference = NULL;
+            bool bypass = !!offset;
+
+            reference = pa_processor_holder_get_connected_processor_reference(holder);
+            if (!holder || !reference) {
+                pa_log_error("holder(%p), reference(%p) aren't set", holder, reference);
+                break;
+            }
+
+            pa_processor_reference_set_bypass(reference, bypass);
+
+            break;
+        }
         case PA_SOURCE_MESSAGE_PREPROCESSOR_DESTROY: {
             pa_source_output *output;
 
index bf24164ecda88f3b1c57203a5075994737868952..2234c7d6724cd6ecd7c9829aaeabc26c1260456b 100644 (file)
@@ -41,6 +41,7 @@ enum {
     PA_SOURCE_MESSAGE_PREPROCESSOR_PUSH_DATA,
     PA_SOURCE_MESSAGE_PREPROCESSOR_PUSH_REFERENCE,
     PA_SOURCE_MESSAGE_PREPROCESSOR_RESET_REFERENCE,
+    PA_SOURCE_MESSAGE_PREPROCESSOR_REFERENCE_BYPASS,
     PA_SOURCE_MESSAGE_PREPROCESSOR_DESTROY,
     PA_SOURCE_MESSAGE_PREPROCESSOR_TERMINATE,
 };
index 889801ff86357572e86b7a3aeea5e3b29df1a530..4441f5475ad25e344afea1ab0f0375dbf1495c40 100644 (file)
@@ -251,7 +251,6 @@ pa_usec_t pa_processor_get_process_usec(pa_processor *p) {
 
 /* Do not touch chunk value */
 int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) {
-    int r = -1;
     int8_t *recording = NULL;
     int8_t *reference = NULL;
     int8_t *output = NULL;
@@ -264,8 +263,17 @@ int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) {
     pa_assert(chunk);
 
     if (processor->reference) {
-        if ((r = pa_processor_reference_pull(processor->reference, &rchunk)) < 0) {
-            pa_log_warn("Failed to get memblock from reference memblockq. ret(%d)", r);
+        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;
         }
 
@@ -281,8 +289,7 @@ int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) {
 
     debug_timestamp_begin(processor);
 
-    r = audio_effect_process_reference(processor->audio_effect, recording, reference, output);
-    if (r < 0) {
+    if (audio_effect_process_reference(processor->audio_effect, recording, reference, output) < 0) {
         pa_log_warn("Failed to process memchunk");
         goto fail;
     }
@@ -324,7 +331,7 @@ int pa_processor_process(pa_processor *processor, pa_memchunk *chunk) {
     /* The memchunk in the result memblockq's refcount must be one */
     pa_memblock_unref(ochunk.memblock);
 
-    return r;
+    return 0;
 
 fail:
     pa_memblock_release(chunk->memblock);
@@ -337,7 +344,7 @@ fail:
 
     pa_memblock_unref(ochunk.memblock);
 
-    return r;
+    return -1;
 }
 
 pa_memblockq *pa_processor_get_result_memblockq(pa_processor *processor) {
index 31f4a7d001ae44b27951a3d417ca31c8f51ce0d3..177e9bd984a4cdb18578434f22a5ffbb6709945c 100644 (file)
@@ -34,7 +34,7 @@
 #include "processor_holder.h"
 
 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
-#define DEFAULT_PREBUFFER_MSEC (300)
+#define DEFAULT_PREBUFFER_MSEC (50)
 
 pa_processor_holder *pa_processor_holder_new(pa_core *core, pa_sample_spec *ss) {
     pa_processor_holder *holder;
@@ -175,7 +175,11 @@ int pa_processor_holder_pump(pa_processor_holder *holder) {
             if ((ret = pa_processor_process(p, &chunk)) < 0) {
                 pa_memblock_unref(chunk.memblock);
                 pa_memblockq_drop(pull_queue, chunk.length);
-                pa_log_error("Failed to process");
+                if (ret == -PROCESSOR_ERR_BUFFERING)
+                    pa_log_debug("Buffering reference memblocks.");
+                else
+                    pa_log_warn("Failed to process memblock. ret(%d)", ret);
+
                 return ret;
             }
 
index b41ca99125909a683f125091b1dc3a7fa02889d4..a4fc6602253d5f4306e29ab2fd2bace1511e6354 100644 (file)
@@ -38,6 +38,7 @@ typedef struct pa_processor_reference {
     pa_usec_t process_usec;
     size_t process_bytes;
     pa_sample_spec ss;
+    bool bypass;
 
     /* only for pull mode (audio-share) */
     void *priv;
@@ -106,6 +107,7 @@ pa_processor_reference *pa_processor_reference_new(pa_core *core,
     reference->ss = *request_ss;
     reference->process_bytes = pa_usec_to_bytes(reference->process_usec, &reference->ss);
     reference->sink = sink;
+    reference->bypass = true;
 
     pa_silence_memchunk_get(&core->silence_cache, core->mempool, &silence, request_ss, 0);
     reference->memblockq = pa_memblockq_new("reference memblockq",
@@ -240,12 +242,10 @@ int pa_processor_reference_pull(pa_processor_reference *reference, pa_memchunk *
 
 exit:
     memblock_length = pa_memblockq_get_length(reference->memblockq);
-    if (memblock_length < length) {
-        pa_log_info("reference memblockq has less memblocks. memblock_length(%zu), length(%zu)",
-                        memblock_length, length);
 
+    /* Needs to gather more reference memblocks */
+    if (memblock_length < length)
         return -1;
-    }
 
     if ((r = pa_memblockq_peek_fixed_size(reference->memblockq, length, chunk)) < 0) {
         pa_log_error("Failed to get memblock from reference memblockq");
@@ -316,6 +316,25 @@ size_t pa_processor_reference_process_usec_to_bytes(pa_processor_reference *refe
 
 }
 
+void pa_processor_reference_set_bypass(pa_processor_reference *reference, bool bypass) {
+    pa_assert(reference);
+
+    if (reference->bypass == bypass)
+        return;
+
+    reference->bypass = bypass;
+
+    pa_log_info("set reference bypass(%d)", reference->bypass);
+}
+
+bool pa_processor_reference_get_bypass(pa_processor_reference *reference) {
+    pa_assert(reference);
+
+    pa_log_debug("get reference bypass(%d)", reference->bypass);
+
+    return reference->bypass;
+}
+
 char *pa_processor_reference_dump_index(pa_processor_reference *reference) {
     int64_t windex, rindex;
 
index cacd5f5382816eabac95f683236a4eb60be271d1..b126aa968bf82e731f9c57e14082df6ae9a648db 100644 (file)
@@ -55,6 +55,8 @@ 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);
index 9b03df79ca1547e171c6c46bee72808b86270eeb..73a91fd949f46c7bef6a95a825539c227ef1d391 100644 (file)
@@ -322,7 +322,11 @@ static int sink_process_msg(
                 u->preprocess_on = true;
                 pa_asyncmsgq_post(u->preprocessor_asyncmsgq, u->preprocessor,
                                     PA_SOURCE_MESSAGE_PREPROCESSOR_RESET_REFERENCE, (void *)true, 0, NULL, NULL);
+                pa_asyncmsgq_post(u->preprocessor_asyncmsgq, u->preprocessor,
+                                    PA_SOURCE_MESSAGE_PREPROCESSOR_REFERENCE_BYPASS, u->holder, (int64_t)false, NULL, NULL);
             } else {
+                pa_asyncmsgq_post(u->preprocessor_asyncmsgq, u->preprocessor,
+                                    PA_SOURCE_MESSAGE_PREPROCESSOR_REFERENCE_BYPASS, u->holder, (int64_t)true, NULL, NULL);
                 u->preprocess_on = false;
             }