Browse code

af_amerge: use the buferqueue API.

Nicolas George authored on 2012/06/01 04:47:10
Showing 1 changed files
... ...
@@ -26,28 +26,27 @@
26 26
 #include "libswresample/swresample.h" // only for SWR_CH_MAX
27 27
 #include "avfilter.h"
28 28
 #include "audio.h"
29
+#include "bufferqueue.h"
29 30
 #include "internal.h"
30 31
 
31
-#define QUEUE_SIZE 16
32
-
33 32
 typedef struct {
34 33
     int nb_in_ch[2];       /**< number of channels for each input */
35 34
     int route[SWR_CH_MAX]; /**< channels routing, see copy_samples */
36 35
     int bps;
37
-    struct amerge_queue {
38
-        AVFilterBufferRef *buf[QUEUE_SIZE];
39
-        int nb_buf, nb_samples, pos;
40
-    } queue[2];
36
+    struct amerge_input {
37
+        struct FFBufQueue queue;
38
+        int nb_samples;
39
+        int pos;
40
+    } in[2];
41 41
 } AMergeContext;
42 42
 
43 43
 static av_cold void uninit(AVFilterContext *ctx)
44 44
 {
45 45
     AMergeContext *am = ctx->priv;
46
-    int i, j;
46
+    int i;
47 47
 
48 48
     for (i = 0; i < 2; i++)
49
-        for (j = 0; j < am->queue[i].nb_buf; j++)
50
-            avfilter_unref_buffer(am->queue[i].buf[j]);
49
+        ff_bufqueue_discard_all(&am->in[i].queue);
51 50
 }
52 51
 
53 52
 static int query_formats(AVFilterContext *ctx)
... ...
@@ -144,7 +143,7 @@ static int request_frame(AVFilterLink *outlink)
144 144
     int i, ret;
145 145
 
146 146
     for (i = 0; i < 2; i++)
147
-        if (!am->queue[i].nb_samples)
147
+        if (!am->in[i].nb_samples)
148 148
             if ((ret = avfilter_request_frame(ctx->inputs[i])) < 0)
149 149
                 return ret;
150 150
     return 0;
... ...
@@ -189,47 +188,38 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
189 189
     AMergeContext *am = ctx->priv;
190 190
     AVFilterLink *const outlink = ctx->outputs[0];
191 191
     int input_number = inlink == ctx->inputs[1];
192
-    struct amerge_queue *inq = &am->queue[input_number];
193 192
     int nb_samples, ns, i;
194
-    AVFilterBufferRef *outbuf, **inbuf[2];
193
+    AVFilterBufferRef *outbuf, *inbuf[2];
195 194
     uint8_t *ins[2], *outs;
196 195
 
197
-    if (inq->nb_buf == QUEUE_SIZE) {
198
-        av_log(ctx, AV_LOG_ERROR, "Packet queue overflow; dropped\n");
199
-        avfilter_unref_buffer(insamples);
200
-        return;
201
-    }
202
-    inq->buf[inq->nb_buf++] = avfilter_ref_buffer(insamples, AV_PERM_READ |
203
-                                                             AV_PERM_PRESERVE);
204
-    inq->nb_samples += insamples->audio->nb_samples;
205
-    avfilter_unref_buffer(insamples);
206
-    if (!am->queue[!input_number].nb_samples)
196
+    ff_bufqueue_add(ctx, &am->in[input_number].queue, insamples);
197
+    am->in[input_number].nb_samples += insamples->audio->nb_samples;
198
+    if (!am->in[!input_number].nb_samples)
207 199
         return;
208 200
 
209
-    nb_samples = FFMIN(am->queue[0].nb_samples,
210
-                       am->queue[1].nb_samples);
211
-    outbuf = ff_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE,
212
-                                       nb_samples);
201
+    nb_samples = FFMIN(am->in[0].nb_samples,
202
+                       am->in[1].nb_samples);
203
+    outbuf = ff_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE, nb_samples);
213 204
     outs = outbuf->data[0];
214 205
     for (i = 0; i < 2; i++) {
215
-        inbuf[i] = am->queue[i].buf;
216
-        ins[i] = (*inbuf[i])->data[0] +
217
-                 am->queue[i].pos * am->nb_in_ch[i] * am->bps;
206
+        inbuf[i] = ff_bufqueue_peek(&am->in[i].queue, 0);
207
+        ins[i] = inbuf[i]->data[0] +
208
+                 am->in[i].pos * am->nb_in_ch[i] * am->bps;
218 209
     }
219
-    outbuf->pts = (*inbuf[0])->pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE :
220
-                  (*inbuf[0])->pts +
221
-                  av_rescale_q(am->queue[0].pos,
210
+    outbuf->pts = inbuf[0]->pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE :
211
+                  inbuf[0]->pts +
212
+                  av_rescale_q(am->in[0].pos,
222 213
                                (AVRational){ 1, ctx->inputs[0]->sample_rate },
223 214
                                ctx->outputs[0]->time_base);
224 215
 
225
-    avfilter_copy_buffer_ref_props(outbuf, *inbuf[0]);
216
+    avfilter_copy_buffer_ref_props(outbuf, inbuf[0]);
226 217
     outbuf->audio->nb_samples     = nb_samples;
227 218
     outbuf->audio->channel_layout = outlink->channel_layout;
228 219
 
229 220
     while (nb_samples) {
230 221
         ns = nb_samples;
231 222
         for (i = 0; i < 2; i++)
232
-            ns = FFMIN(ns, (*inbuf[i])->audio->nb_samples - am->queue[i].pos);
223
+            ns = FFMIN(ns, inbuf[i]->audio->nb_samples - am->in[i].pos);
233 224
         /* Unroll the most common sample formats: speed +~350% for the loop,
234 225
            +~13% overall (including two common decoders) */
235 226
         switch (am->bps) {
... ...
@@ -249,25 +239,17 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
249 249
 
250 250
         nb_samples -= ns;
251 251
         for (i = 0; i < 2; i++) {
252
-            am->queue[i].nb_samples -= ns;
253
-            am->queue[i].pos += ns;
254
-            if (am->queue[i].pos == (*inbuf[i])->audio->nb_samples) {
255
-                am->queue[i].pos = 0;
256
-                avfilter_unref_buffer(*inbuf[i]);
257
-                *inbuf[i] = NULL;
258
-                inbuf[i]++;
259
-                ins[i] = *inbuf[i] ? (*inbuf[i])->data[0] : NULL;
252
+            am->in[i].nb_samples -= ns;
253
+            am->in[i].pos += ns;
254
+            if (am->in[i].pos == inbuf[i]->audio->nb_samples) {
255
+                am->in[i].pos = 0;
256
+                avfilter_unref_buffer(inbuf[i]);
257
+                ff_bufqueue_get(&am->in[i].queue);
258
+                inbuf[i] = ff_bufqueue_peek(&am->in[i].queue, 0);
259
+                ins[i] = inbuf[i] ? inbuf[i]->data[0] : NULL;
260 260
             }
261 261
         }
262 262
     }
263
-    for (i = 0; i < 2; i++) {
264
-        int nbufused = inbuf[i] - am->queue[i].buf;
265
-        if (nbufused) {
266
-            am->queue[i].nb_buf -= nbufused;
267
-            memmove(am->queue[i].buf, inbuf[i],
268
-                    am->queue[i].nb_buf * sizeof(**inbuf));
269
-        }
270
-    }
271 263
     ff_filter_samples(ctx->outputs[0], outbuf);
272 264
 }
273 265
 
... ...
@@ -283,11 +265,11 @@ AVFilter avfilter_af_amerge = {
283 283
         { .name             = "in1",
284 284
           .type             = AVMEDIA_TYPE_AUDIO,
285 285
           .filter_samples   = filter_samples,
286
-          .min_perms        = AV_PERM_READ, },
286
+          .min_perms        = AV_PERM_READ | AV_PERM_PRESERVE, },
287 287
         { .name             = "in2",
288 288
           .type             = AVMEDIA_TYPE_AUDIO,
289 289
           .filter_samples   = filter_samples,
290
-          .min_perms        = AV_PERM_READ, },
290
+          .min_perms        = AV_PERM_READ | AV_PERM_PRESERVE, },
291 291
         { .name = NULL }
292 292
     },
293 293
     .outputs   = (const AVFilterPad[]) {