[pulseaudio-commits] r1490 - in /branches/lennart/src/pulsecore: sink.c sink.h

svnmailer-noreply at 0pointer.de svnmailer-noreply at 0pointer.de
Sat Jun 23 13:04:48 PDT 2007


Author: lennart
Date: Sat Jun 23 22:04:47 2007
New Revision: 1490

URL: http://0pointer.de/cgi-bin/viewcvs.cgi?rev=3D1490&root=3Dpulseaudio&vi=
ew=3Drev
Log:
remove underrun condition in pa_sinks. Instead return silence in pa_sink_re=
nder() when necessary. This is required to guarantee that the time function=
s in connected sink inputs stays linear

Modified:
    branches/lennart/src/pulsecore/sink.c
    branches/lennart/src/pulsecore/sink.h

Modified: branches/lennart/src/pulsecore/sink.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/lennart/src/pulsecore/=
sink.c?rev=3D1490&root=3Dpulseaudio&r1=3D1489&r2=3D1490&view=3Ddiff
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/lennart/src/pulsecore/sink.c (original)
+++ branches/lennart/src/pulsecore/sink.c Sat Jun 23 22:04:47 2007
@@ -116,6 +116,7 @@
     s->userdata =3D NULL;
 =

     s->asyncmsgq =3D NULL;
+    s->silence =3D NULL;
 =

     r =3D pa_idxset_put(core->sinks, s, &s->index);
     pa_assert(s->index !=3D PA_IDXSET_INVALID && r >=3D 0);
@@ -222,6 +223,9 @@
     =

     pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
 =

+    if (s->silence)
+        pa_memblock_unref(s->silence);
+    =

     pa_xfree(s->name);
     pa_xfree(s->description);
     pa_xfree(s->driver);
@@ -270,53 +274,85 @@
     pa_sink_assert_ref(s);
     pa_assert(info);
 =

+    while ((i =3D pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))=
 && maxinfo > 0) {
+        pa_sink_input_assert_ref(i);
+
+        if (pa_sink_input_peek(i, &info->chunk, &info->volume) < 0)
+            continue;
+
+        info->userdata =3D pa_sink_input_ref(i);
+
+        pa_assert(info->chunk.memblock);
+        pa_assert(info->chunk.length > 0);
+
+        info++;
+        n++;
+        maxinfo--;
+    }
+
+    return n;
+}
+
+static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t =
length) {
+    pa_sink_input *i;
+    void *state =3D NULL;
+    unsigned p =3D 0;
+    unsigned n_unreffed =3D 0;
+
+    pa_sink_assert_ref(s);
+
+    /* We optimize for the case where the order of the inputs has not chan=
ged */
+
     while ((i =3D pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))=
) {
-        /* Increase ref counter, to make sure that this input doesn't
-         * vanish while we still need it */
-        pa_sink_input_ref(i);
-
-        if (pa_sink_input_peek(i, &info->chunk, &info->volume) < 0) {
-            pa_sink_input_unref(i);
-            continue;
+        unsigned j;
+        pa_mix_info* m;
+
+        pa_sink_input_assert_ref(i);
+
+        m =3D NULL;
+
+        /* Let's try to find the matching entry info the pa_mix_info array=
 */
+        for (j =3D 0; j < n; j ++) {
+
+            if (info[p].userdata =3D=3D i) {
+                m =3D info + p;
+                break;
+            }
+
+            if (++p > n)
+                p =3D 0;
         }
 =

-        info->userdata =3D i;
-
-        pa_assert(info->chunk.memblock);
-        pa_assert(info->chunk.length);
-
-        info++;
-        maxinfo--;
-        n++;
-    }
-
-    return n;
-}
-
-static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, s=
ize_t length) {
-    pa_sink_assert_ref(s);
-    pa_assert(info);
-
-    for (; maxinfo > 0; maxinfo--, info++) {
-        pa_sink_input *i =3D info->userdata;
-
-        pa_assert(i);
-        pa_assert(info->chunk.memblock);
-
         /* Drop read data */
-        pa_sink_input_drop(i, &info->chunk, length);
-        pa_memblock_unref(info->chunk.memblock);
-
-        /* Decrease ref counter */
-        pa_sink_input_unref(i);
-        info->userdata =3D NULL;
-    }
-}
-
-int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
+        pa_sink_input_drop(i, m ? &m->chunk : NULL, length);
+
+        if (m) {
+            pa_sink_input_unref(m->userdata);
+            m->userdata =3D NULL;
+            if (m->chunk.memblock)
+                pa_memblock_unref(m->chunk.memblock);
+            pa_memchunk_reset(&m->chunk);
+
+            n_unreffed +=3D 1;
+        }
+    }
+
+    /* Now drop references to entries that are included in the
+     * pa_mix_info array but don't exist anymore */
+
+    if (n_unreffed < n) {
+        for (; n > 0; info++, n--) {
+            if (info->userdata)
+                pa_sink_input_unref(info->userdata);
+            if (info->chunk.memblock)
+                pa_memblock_unref(info->chunk.memblock);
+        }
+    }
+}
+
+void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     pa_mix_info info[MAX_MIX_CHANNELS];
     unsigned n;
-    int r =3D -1;
 =

     pa_sink_assert_ref(s);
     pa_assert(length);
@@ -326,10 +362,19 @@
 =

     n =3D fill_mix_info(s, info, MAX_MIX_CHANNELS);
 =

-    if (n <=3D 0)
-        goto finish;
-
-    if (n =3D=3D 1) {
+    if (n =3D=3D 0) {
+
+        if (!s->silence || pa_memblock_get_length(s->silence) < length) {
+            if (s->silence)
+                pa_memblock_unref(s->silence);
+            s->silence =3D pa_silence_memblock_new(s->core->mempool, &s->s=
ample_spec, length);
+        }
+
+        result->memblock =3D pa_memblock_ref(s->silence);
+        result->length =3D length;
+        result->index =3D 0;
+
+    } else if (n =3D=3D 1) {
         pa_cvolume volume;
 =

         *result =3D info[0].chunk;
@@ -363,18 +408,12 @@
     if (s->monitor_source)
         pa_source_post(s->monitor_source, result);
 =

-    r =3D 0;
-
-finish:
     pa_sink_unref(s);
-
-    return r;
-}
-
-int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
+}
+
+void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     pa_mix_info info[MAX_MIX_CHANNELS];
     unsigned n;
-    int r =3D -1;
 =

     pa_sink_assert_ref(s);
     pa_assert(target);
@@ -385,11 +424,9 @@
 =

     n =3D fill_mix_info(s, info, MAX_MIX_CHANNELS);
 =

-    if (n <=3D 0)
-        goto finish;
-
-
-    if (n =3D=3D 1) {
+    if (n =3D=3D 0) {
+        pa_silence_memchunk(target, &s->sample_spec);
+    } else if (n =3D=3D 1) {
         if (target->length > info[0].chunk.length)
             target->length =3D info[0].chunk.length;
 =

@@ -435,12 +472,7 @@
     if (s->monitor_source)
         pa_source_post(s->monitor_source, target);
 =

-    r =3D 0;
-
-finish:
     pa_sink_unref(s);
-
-    return r;
 }
 =

 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
@@ -461,18 +493,10 @@
         chunk.index +=3D d;
         chunk.length -=3D d;
 =

-        if (pa_sink_render_into(s, &chunk) < 0)
-            break;
+        pa_sink_render_into(s, &chunk);
 =

         d +=3D chunk.length;
         l -=3D chunk.length;
-    }
-
-    if (l > 0) {
-        chunk =3D *target;
-        chunk.index +=3D d;
-        chunk.length -=3D d;
-        pa_silence_memchunk(&chunk, &s->sample_spec);
     }
 =

     pa_sink_unref(s);
@@ -668,7 +692,7 @@
         case PA_SINK_MESSAGE_SET_STATE:
             s->thread_info.state =3D PA_PTR_TO_UINT(userdata);
             return 0;
-            =

+
         case PA_SINK_MESSAGE_GET_LATENCY:
         case PA_SINK_MESSAGE_MAX:
             ;

Modified: branches/lennart/src/pulsecore/sink.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/branches/lennart/src/pulsecore/=
sink.h?rev=3D1490&root=3Dpulseaudio&r1=3D1489&r2=3D1490&view=3Ddiff
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/lennart/src/pulsecore/sink.h (original)
+++ branches/lennart/src/pulsecore/sink.h Sat Jun 23 22:04:47 2007
@@ -92,6 +92,8 @@
         int soft_muted;
     } thread_info;
 =

+    pa_memblock *silence;
+
     void *userdata;
 };
 =

@@ -149,9 +151,9 @@
 =

 /* To be used exclusively by the sink driver thread */
 =

-int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result);
+void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result);
 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result);
-int pa_sink_render_into(pa_sink*s, pa_memchunk *target);
+void pa_sink_render_into(pa_sink*s, pa_memchunk *target);
 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target);
 =

 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memc=
hunk *chunk);




More information about the pulseaudio-commits mailing list