preprocessor: Fix omitting source-output memchunks sometimes 70/302970/17 accepted/tizen/unified/20240104.012441 accepted/tizen/unified/riscv/20240105.060204
authorJaechul Lee <jcsing.lee@samsung.com>
Mon, 18 Dec 2023 06:18:44 +0000 (15:18 +0900)
committerJaechul Lee <jcsing.lee@samsung.com>
Wed, 3 Jan 2024 06:13:16 +0000 (15:13 +0900)
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 <jcsing.lee@samsung.com>
packaging/pulseaudio-modules-tizen.spec
src/preprocessor/processor.c
src/preprocessor/processor.h
src/preprocessor/processor_holder.c
src/preprocessor/processor_holder.h
src/preprocessor/processor_reference.c
src/preprocessor/processor_reference.h

index 67a39ed8123a7c126529e0705ea327d5594d6608..658a2df642ceaf53af6bcee6b4c4fa9fae72784b 100644 (file)
@@ -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+
index 4441f5475ad25e344afea1ab0f0375dbf1495c40..c2bdce8f5e3bdaa1e67267208e579239d34d8db1 100644 (file)
@@ -35,7 +35,7 @@
 #include "processor.h"
 #include "processor-def.h"
 
-#ifdef __DEBUG__
+#ifdef __PROCESSOR_DEBUG__
 #include <stdio.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 
 #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
 
index a4f7152145c8ae308bf82d9649fffb5bd443f03d..6e66e65924880018cd1154524e9d620ec20b99dd 100644 (file)
@@ -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);
index 177e9bd984a4cdb18578434f22a5ffbb6709945c..1b83afc45772cc132169ad8fda54d3d4deafb603 100644 (file)
 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
 #define DEFAULT_PREBUFFER_MSEC (50)
 
+#ifdef __PROCESSOR_HOLDER_DEBUG__
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+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
+
index 7ba027593dd01c5699630658c4a818dd37f52635..6dde8e2709b1a3fffb320e2421ebc891480b4b6b 100644 (file)
@@ -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);
index a4fc6602253d5f4306e29ab2fd2bace1511e6354..22a6076e6794b5c138d588b2f04e7ac6ad318952 100644 (file)
@@ -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;
+}
index b126aa968bf82e731f9c57e14082df6ae9a648db..08ad04aeda3add9b1311339f3d0b81a865b6534e 100644 (file)
@@ -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