Browse code

Merge remote-tracking branch 'qatar/master'

* qatar/master:
rtmp: Return a proper error code instead of -1
rtmp: Check malloc calls
rtmp: Check ff_rtmp_packet_create calls
lavfi: add audio mix filter
flvdec: Make sure sample_rate is set to the updated value
tqi: Pass errors from the MB decoder

Conflicts:
Changelog
doc/filters.texi
libavcodec/eatqi.c
libavfilter/Makefile
libavfilter/allfilters.c
libavfilter/version.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2012/05/25 07:38:16
Showing 11 changed files
... ...
@@ -38,6 +38,7 @@ version 0.11:
38 38
 - audio split filter
39 39
 - vorbis parser
40 40
 - png parser
41
+- audio mix filter
41 42
 
42 43
 
43 44
 version 0.10:
... ...
@@ -216,6 +216,44 @@ amovie=input.mkv:si=5 [a5];
216 216
 [x3][a5] amerge" -c:a pcm_s16le output.mkv
217 217
 @end example
218 218
 
219
+@section amix
220
+
221
+Mixes multiple audio inputs into a single output.
222
+
223
+For example
224
+@example
225
+ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=first:dropout_transition=3 OUTPUT
226
+@end example
227
+will mix 3 input audio streams to a single output with the same duration as the
228
+first input and a dropout transition time of 3 seconds.
229
+
230
+The filter accepts the following named parameters:
231
+@table @option
232
+
233
+@item inputs
234
+Number of inputs. If unspecified, it defaults to 2.
235
+
236
+@item duration
237
+How to determine the end-of-stream.
238
+@table @option
239
+
240
+@item longest
241
+Duration of longest input. (default)
242
+
243
+@item shortest
244
+Duration of shortest input.
245
+
246
+@item first
247
+Duration of first input.
248
+
249
+@end table
250
+
251
+@item dropout_transition
252
+Transition time, in seconds, for volume renormalization when an input
253
+stream ends. The default value is 2 seconds.
254
+
255
+@end table
256
+
219 257
 @section anull
220 258
 
221 259
 Pass the audio source unchanged to the output.
... ...
@@ -62,7 +62,7 @@ static int tqi_decode_mb(MpegEncContext *s, DCTELEM (*block)[64])
62 62
     int n;
63 63
     s->dsp.clear_blocks(block[0]);
64 64
     for (n=0; n<6; n++)
65
-        if(ff_mpeg1_decode_block_intra(s, block[n], n)<0)
65
+        if (ff_mpeg1_decode_block_intra(s, block[n], n) < 0)
66 66
             return -1;
67 67
 
68 68
     return 0;
... ...
@@ -138,7 +138,7 @@ static int tqi_decode_frame(AVCodecContext *avctx,
138 138
     for (s->mb_y=0; s->mb_y<(avctx->height+15)/16; s->mb_y++)
139 139
     for (s->mb_x=0; s->mb_x<(avctx->width+15)/16; s->mb_x++)
140 140
     {
141
-        if(tqi_decode_mb(s, t->block) < 0)
141
+        if (tqi_decode_mb(s, t->block) < 0)
142 142
             goto end;
143 143
         tqi_idct_put(t, t->block);
144 144
     }
... ...
@@ -47,6 +47,7 @@ OBJS-$(CONFIG_SWSCALE)                       += lswsutils.o
47 47
 OBJS-$(CONFIG_ACONVERT_FILTER)               += af_aconvert.o
48 48
 OBJS-$(CONFIG_AFORMAT_FILTER)                += af_aformat.o
49 49
 OBJS-$(CONFIG_AMERGE_FILTER)                 += af_amerge.o
50
+OBJS-$(CONFIG_AMIX_FILTER)                   += af_amix.o
50 51
 OBJS-$(CONFIG_ANULL_FILTER)                  += af_anull.o
51 52
 OBJS-$(CONFIG_ARESAMPLE_FILTER)              += af_aresample.o
52 53
 OBJS-$(CONFIG_ASHOWINFO_FILTER)              += af_ashowinfo.o
53 54
new file mode 100644
... ...
@@ -0,0 +1,545 @@
0
+/*
1
+ * Audio Mix Filter
2
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3
+ *
4
+ * This file is part of Libav.
5
+ *
6
+ * Libav is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * Libav is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with Libav; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * Audio Mix Filter
24
+ *
25
+ * Mixes audio from multiple sources into a single output. The channel layout,
26
+ * sample rate, and sample format will be the same for all inputs and the
27
+ * output.
28
+ */
29
+
30
+#include "libavutil/audioconvert.h"
31
+#include "libavutil/audio_fifo.h"
32
+#include "libavutil/avassert.h"
33
+#include "libavutil/avstring.h"
34
+#include "libavutil/mathematics.h"
35
+#include "libavutil/opt.h"
36
+#include "libavutil/samplefmt.h"
37
+
38
+#include "audio.h"
39
+#include "avfilter.h"
40
+#include "formats.h"
41
+#include "internal.h"
42
+
43
+#define INPUT_OFF      0    /**< input has reached EOF */
44
+#define INPUT_ON       1    /**< input is active */
45
+#define INPUT_INACTIVE 2    /**< input is on, but is currently inactive */
46
+
47
+#define DURATION_LONGEST  0
48
+#define DURATION_SHORTEST 1
49
+#define DURATION_FIRST    2
50
+
51
+
52
+typedef struct FrameInfo {
53
+    int nb_samples;
54
+    int64_t pts;
55
+    struct FrameInfo *next;
56
+} FrameInfo;
57
+
58
+/**
59
+ * Linked list used to store timestamps and frame sizes of all frames in the
60
+ * FIFO for the first input.
61
+ *
62
+ * This is needed to keep timestamps synchronized for the case where multiple
63
+ * input frames are pushed to the filter for processing before a frame is
64
+ * requested by the output link.
65
+ */
66
+typedef struct FrameList {
67
+    int nb_frames;
68
+    int nb_samples;
69
+    FrameInfo *list;
70
+    FrameInfo *end;
71
+} FrameList;
72
+
73
+static void frame_list_clear(FrameList *frame_list)
74
+{
75
+    if (frame_list) {
76
+        while (frame_list->list) {
77
+            FrameInfo *info = frame_list->list;
78
+            frame_list->list = info->next;
79
+            av_free(info);
80
+        }
81
+        frame_list->nb_frames  = 0;
82
+        frame_list->nb_samples = 0;
83
+        frame_list->end        = NULL;
84
+    }
85
+}
86
+
87
+static int frame_list_next_frame_size(FrameList *frame_list)
88
+{
89
+    if (!frame_list->list)
90
+        return 0;
91
+    return frame_list->list->nb_samples;
92
+}
93
+
94
+static int64_t frame_list_next_pts(FrameList *frame_list)
95
+{
96
+    if (!frame_list->list)
97
+        return AV_NOPTS_VALUE;
98
+    return frame_list->list->pts;
99
+}
100
+
101
+static void frame_list_remove_samples(FrameList *frame_list, int nb_samples)
102
+{
103
+    if (nb_samples >= frame_list->nb_samples) {
104
+        frame_list_clear(frame_list);
105
+    } else {
106
+        int samples = nb_samples;
107
+        while (samples > 0) {
108
+            FrameInfo *info = frame_list->list;
109
+            av_assert0(info != NULL);
110
+            if (info->nb_samples <= samples) {
111
+                samples -= info->nb_samples;
112
+                frame_list->list = info->next;
113
+                if (!frame_list->list)
114
+                    frame_list->end = NULL;
115
+                frame_list->nb_frames--;
116
+                frame_list->nb_samples -= info->nb_samples;
117
+                av_free(info);
118
+            } else {
119
+                info->nb_samples       -= samples;
120
+                info->pts              += samples;
121
+                frame_list->nb_samples -= samples;
122
+                samples = 0;
123
+            }
124
+        }
125
+    }
126
+}
127
+
128
+static int frame_list_add_frame(FrameList *frame_list, int nb_samples, int64_t pts)
129
+{
130
+    FrameInfo *info = av_malloc(sizeof(*info));
131
+    if (!info)
132
+        return AVERROR(ENOMEM);
133
+    info->nb_samples = nb_samples;
134
+    info->pts        = pts;
135
+    info->next       = NULL;
136
+
137
+    if (!frame_list->list) {
138
+        frame_list->list = info;
139
+        frame_list->end  = info;
140
+    } else {
141
+        av_assert0(frame_list->end != NULL);
142
+        frame_list->end->next = info;
143
+        frame_list->end       = info;
144
+    }
145
+    frame_list->nb_frames++;
146
+    frame_list->nb_samples += nb_samples;
147
+
148
+    return 0;
149
+}
150
+
151
+
152
+typedef struct MixContext {
153
+    const AVClass *class;       /**< class for AVOptions */
154
+
155
+    int nb_inputs;              /**< number of inputs */
156
+    int active_inputs;          /**< number of input currently active */
157
+    int duration_mode;          /**< mode for determining duration */
158
+    float dropout_transition;   /**< transition time when an input drops out */
159
+
160
+    int nb_channels;            /**< number of channels */
161
+    int sample_rate;            /**< sample rate */
162
+    AVAudioFifo **fifos;        /**< audio fifo for each input */
163
+    uint8_t *input_state;       /**< current state of each input */
164
+    float *input_scale;         /**< mixing scale factor for each input */
165
+    float scale_norm;           /**< normalization factor for all inputs */
166
+    int64_t next_pts;           /**< calculated pts for next output frame */
167
+    FrameList *frame_list;      /**< list of frame info for the first input */
168
+} MixContext;
169
+
170
+#define OFFSET(x) offsetof(MixContext, x)
171
+#define A AV_OPT_FLAG_AUDIO_PARAM
172
+static const AVOption options[] = {
173
+    { "inputs", "Number of inputs.",
174
+            OFFSET(nb_inputs), AV_OPT_TYPE_INT, { 2 }, 1, 32, A },
175
+    { "duration", "How to determine the end-of-stream.",
176
+            OFFSET(duration_mode), AV_OPT_TYPE_INT, { DURATION_LONGEST }, 0,  2, A, "duration" },
177
+        { "longest",  "Duration of longest input.",  0, AV_OPT_TYPE_CONST, { DURATION_LONGEST  }, INT_MIN, INT_MAX, A, "duration" },
178
+        { "shortest", "Duration of shortest input.", 0, AV_OPT_TYPE_CONST, { DURATION_SHORTEST }, INT_MIN, INT_MAX, A, "duration" },
179
+        { "first",    "Duration of first input.",    0, AV_OPT_TYPE_CONST, { DURATION_FIRST    }, INT_MIN, INT_MAX, A, "duration" },
180
+    { "dropout_transition", "Transition time, in seconds, for volume "
181
+                            "renormalization when an input stream ends.",
182
+            OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { 2.0 }, 0, INT_MAX, A },
183
+    { NULL },
184
+};
185
+
186
+static const AVClass amix_class = {
187
+    .class_name = "amix filter",
188
+    .item_name  = av_default_item_name,
189
+    .option     = options,
190
+    .version    = LIBAVUTIL_VERSION_INT,
191
+};
192
+
193
+
194
+/**
195
+ * Update the scaling factors to apply to each input during mixing.
196
+ *
197
+ * This balances the full volume range between active inputs and handles
198
+ * volume transitions when EOF is encountered on an input but mixing continues
199
+ * with the remaining inputs.
200
+ */
201
+static void calculate_scales(MixContext *s, int nb_samples)
202
+{
203
+    int i;
204
+
205
+    if (s->scale_norm > s->active_inputs) {
206
+        s->scale_norm -= nb_samples / (s->dropout_transition * s->sample_rate);
207
+        s->scale_norm = FFMAX(s->scale_norm, s->active_inputs);
208
+    }
209
+
210
+    for (i = 0; i < s->nb_inputs; i++) {
211
+        if (s->input_state[i] == INPUT_ON)
212
+            s->input_scale[i] = 1.0f / s->scale_norm;
213
+        else
214
+            s->input_scale[i] = 0.0f;
215
+    }
216
+}
217
+
218
+static int config_output(AVFilterLink *outlink)
219
+{
220
+    AVFilterContext *ctx = outlink->src;
221
+    MixContext *s      = ctx->priv;
222
+    int i;
223
+    char buf[64];
224
+
225
+    s->sample_rate     = outlink->sample_rate;
226
+    outlink->time_base = (AVRational){ 1, outlink->sample_rate };
227
+    s->next_pts        = AV_NOPTS_VALUE;
228
+
229
+    s->frame_list = av_mallocz(sizeof(*s->frame_list));
230
+    if (!s->frame_list)
231
+        return AVERROR(ENOMEM);
232
+
233
+    s->fifos = av_mallocz(s->nb_inputs * sizeof(*s->fifos));
234
+    if (!s->fifos)
235
+        return AVERROR(ENOMEM);
236
+
237
+    s->nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout);
238
+    for (i = 0; i < s->nb_inputs; i++) {
239
+        s->fifos[i] = av_audio_fifo_alloc(outlink->format, s->nb_channels, 1024);
240
+        if (!s->fifos[i])
241
+            return AVERROR(ENOMEM);
242
+    }
243
+
244
+    s->input_state = av_malloc(s->nb_inputs);
245
+    if (!s->input_state)
246
+        return AVERROR(ENOMEM);
247
+    memset(s->input_state, INPUT_ON, s->nb_inputs);
248
+    s->active_inputs = s->nb_inputs;
249
+
250
+    s->input_scale = av_mallocz(s->nb_inputs * sizeof(*s->input_scale));
251
+    if (!s->input_scale)
252
+        return AVERROR(ENOMEM);
253
+    s->scale_norm = s->active_inputs;
254
+    calculate_scales(s, 0);
255
+
256
+    av_get_channel_layout_string(buf, sizeof(buf), -1, outlink->channel_layout);
257
+
258
+    av_log(ctx, AV_LOG_VERBOSE,
259
+           "inputs:%d fmt:%s srate:%"PRId64" cl:%s\n", s->nb_inputs,
260
+           av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf);
261
+
262
+    return 0;
263
+}
264
+
265
+/* TODO: move optimized version from DSPContext to libavutil */
266
+static void vector_fmac_scalar(float *dst, const float *src, float mul, int len)
267
+{
268
+    int i;
269
+    for (i = 0; i < len; i++)
270
+        dst[i] += src[i] * mul;
271
+}
272
+
273
+/**
274
+ * Read samples from the input FIFOs, mix, and write to the output link.
275
+ */
276
+static int output_frame(AVFilterLink *outlink, int nb_samples)
277
+{
278
+    AVFilterContext *ctx = outlink->src;
279
+    MixContext      *s = ctx->priv;
280
+    AVFilterBufferRef *out_buf, *in_buf;
281
+    int i;
282
+
283
+    calculate_scales(s, nb_samples);
284
+
285
+    out_buf = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
286
+    if (!out_buf)
287
+        return AVERROR(ENOMEM);
288
+
289
+    in_buf = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
290
+    if (!in_buf)
291
+        return AVERROR(ENOMEM);
292
+
293
+    for (i = 0; i < s->nb_inputs; i++) {
294
+        if (s->input_state[i] == INPUT_ON) {
295
+            av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data,
296
+                               nb_samples);
297
+            vector_fmac_scalar((float *)out_buf->extended_data[0],
298
+                               (float *) in_buf->extended_data[0],
299
+                               s->input_scale[i], nb_samples * s->nb_channels);
300
+        }
301
+    }
302
+    avfilter_unref_buffer(in_buf);
303
+
304
+    out_buf->pts = s->next_pts;
305
+    if (s->next_pts != AV_NOPTS_VALUE)
306
+        s->next_pts += nb_samples;
307
+
308
+    ff_filter_samples(outlink, out_buf);
309
+
310
+    return 0;
311
+}
312
+
313
+/**
314
+ * Returns the smallest number of samples available in the input FIFOs other
315
+ * than that of the first input.
316
+ */
317
+static int get_available_samples(MixContext *s)
318
+{
319
+    int i;
320
+    int available_samples = INT_MAX;
321
+
322
+    av_assert0(s->nb_inputs > 1);
323
+
324
+    for (i = 1; i < s->nb_inputs; i++) {
325
+        int nb_samples;
326
+        if (s->input_state[i] == INPUT_OFF)
327
+            continue;
328
+        nb_samples = av_audio_fifo_size(s->fifos[i]);
329
+        available_samples = FFMIN(available_samples, nb_samples);
330
+    }
331
+    if (available_samples == INT_MAX)
332
+        return 0;
333
+    return available_samples;
334
+}
335
+
336
+/**
337
+ * Requests a frame, if needed, from each input link other than the first.
338
+ */
339
+static int request_samples(AVFilterContext *ctx, int min_samples)
340
+{
341
+    MixContext *s = ctx->priv;
342
+    int i, ret;
343
+
344
+    av_assert0(s->nb_inputs > 1);
345
+
346
+    for (i = 1; i < s->nb_inputs; i++) {
347
+        ret = 0;
348
+        if (s->input_state[i] == INPUT_OFF)
349
+            continue;
350
+        while (!ret && av_audio_fifo_size(s->fifos[i]) < min_samples)
351
+            ret = avfilter_request_frame(ctx->inputs[i]);
352
+        if (ret == AVERROR_EOF) {
353
+            if (av_audio_fifo_size(s->fifos[i]) == 0) {
354
+                s->input_state[i] = INPUT_OFF;
355
+                continue;
356
+            }
357
+        } else if (ret)
358
+            return ret;
359
+    }
360
+    return 0;
361
+}
362
+
363
+/**
364
+ * Calculates the number of active inputs and determines EOF based on the
365
+ * duration option.
366
+ *
367
+ * @return 0 if mixing should continue, or AVERROR_EOF if mixing should stop.
368
+ */
369
+static int calc_active_inputs(MixContext *s)
370
+{
371
+    int i;
372
+    int active_inputs = 0;
373
+    for (i = 0; i < s->nb_inputs; i++)
374
+        active_inputs += !!(s->input_state[i] != INPUT_OFF);
375
+    s->active_inputs = active_inputs;
376
+
377
+    if (!active_inputs ||
378
+        (s->duration_mode == DURATION_FIRST && s->input_state[0] == INPUT_OFF) ||
379
+        (s->duration_mode == DURATION_SHORTEST && active_inputs != s->nb_inputs))
380
+        return AVERROR_EOF;
381
+    return 0;
382
+}
383
+
384
+static int request_frame(AVFilterLink *outlink)
385
+{
386
+    AVFilterContext *ctx = outlink->src;
387
+    MixContext      *s = ctx->priv;
388
+    int ret;
389
+    int wanted_samples, available_samples;
390
+
391
+    if (s->input_state[0] == INPUT_OFF) {
392
+        ret = request_samples(ctx, 1);
393
+        if (ret < 0)
394
+            return ret;
395
+
396
+        ret = calc_active_inputs(s);
397
+        if (ret < 0)
398
+            return ret;
399
+
400
+        available_samples = get_available_samples(s);
401
+        if (!available_samples)
402
+            return 0;
403
+
404
+        return output_frame(outlink, available_samples);
405
+    }
406
+
407
+    if (s->frame_list->nb_frames == 0) {
408
+        ret = avfilter_request_frame(ctx->inputs[0]);
409
+        if (ret == AVERROR_EOF) {
410
+            s->input_state[0] = INPUT_OFF;
411
+            if (s->nb_inputs == 1)
412
+                return AVERROR_EOF;
413
+            else
414
+                return AVERROR(EAGAIN);
415
+        } else if (ret)
416
+            return ret;
417
+    }
418
+    av_assert0(s->frame_list->nb_frames > 0);
419
+
420
+    wanted_samples = frame_list_next_frame_size(s->frame_list);
421
+    ret = request_samples(ctx, wanted_samples);
422
+    if (ret < 0)
423
+        return ret;
424
+
425
+    ret = calc_active_inputs(s);
426
+    if (ret < 0)
427
+        return ret;
428
+
429
+    if (s->active_inputs > 1) {
430
+        available_samples = get_available_samples(s);
431
+        if (!available_samples)
432
+            return 0;
433
+        available_samples = FFMIN(available_samples, wanted_samples);
434
+    } else {
435
+        available_samples = wanted_samples;
436
+    }
437
+
438
+    s->next_pts = frame_list_next_pts(s->frame_list);
439
+    frame_list_remove_samples(s->frame_list, available_samples);
440
+
441
+    return output_frame(outlink, available_samples);
442
+}
443
+
444
+static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
445
+{
446
+    AVFilterContext  *ctx = inlink->dst;
447
+    MixContext       *s = ctx->priv;
448
+    AVFilterLink *outlink = ctx->outputs[0];
449
+    int i;
450
+
451
+    for (i = 0; i < ctx->input_count; i++)
452
+        if (ctx->inputs[i] == inlink)
453
+            break;
454
+    if (i >= ctx->input_count) {
455
+        av_log(ctx, AV_LOG_ERROR, "unknown input link\n");
456
+        return;
457
+    }
458
+
459
+    if (i == 0) {
460
+        int64_t pts = av_rescale_q(buf->pts, inlink->time_base,
461
+                                   outlink->time_base);
462
+        frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts);
463
+    }
464
+
465
+    av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data,
466
+                        buf->audio->nb_samples);
467
+
468
+    avfilter_unref_buffer(buf);
469
+}
470
+
471
+static int init(AVFilterContext *ctx, const char *args, void *opaque)
472
+{
473
+    MixContext *s = ctx->priv;
474
+    int i, ret;
475
+
476
+    s->class = &amix_class;
477
+    av_opt_set_defaults(s);
478
+
479
+    if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
480
+        av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
481
+        return ret;
482
+    }
483
+    av_opt_free(s);
484
+
485
+    for (i = 0; i < s->nb_inputs; i++) {
486
+        char name[32];
487
+        AVFilterPad pad = { 0 };
488
+
489
+        snprintf(name, sizeof(name), "input%d", i);
490
+        pad.type           = AVMEDIA_TYPE_AUDIO;
491
+        pad.name           = av_strdup(name);
492
+        pad.filter_samples = filter_samples;
493
+
494
+        avfilter_insert_inpad(ctx, i, &pad);
495
+    }
496
+
497
+    return 0;
498
+}
499
+
500
+static void uninit(AVFilterContext *ctx)
501
+{
502
+    int i;
503
+    MixContext *s = ctx->priv;
504
+
505
+    if (s->fifos) {
506
+        for (i = 0; i < s->nb_inputs; i++)
507
+            av_audio_fifo_free(s->fifos[i]);
508
+        av_freep(&s->fifos);
509
+    }
510
+    frame_list_clear(s->frame_list);
511
+    av_freep(&s->frame_list);
512
+    av_freep(&s->input_state);
513
+    av_freep(&s->input_scale);
514
+
515
+    for (i = 0; i < ctx->input_count; i++)
516
+        av_freep(&ctx->input_pads[i].name);
517
+}
518
+
519
+static int query_formats(AVFilterContext *ctx)
520
+{
521
+    AVFilterFormats *formats = NULL;
522
+    avfilter_add_format(&formats, AV_SAMPLE_FMT_FLT);
523
+    avfilter_set_common_formats(ctx, formats);
524
+    ff_set_common_channel_layouts(ctx, ff_all_channel_layouts());
525
+    ff_set_common_samplerates(ctx, ff_all_samplerates());
526
+    return 0;
527
+}
528
+
529
+AVFilter avfilter_af_amix = {
530
+    .name          = "amix",
531
+    .description   = NULL_IF_CONFIG_SMALL("Audio mixing."),
532
+    .priv_size     = sizeof(MixContext),
533
+
534
+    .init           = init,
535
+    .uninit         = uninit,
536
+    .query_formats  = query_formats,
537
+
538
+    .inputs    = (const AVFilterPad[]) {{ .name = NULL}},
539
+    .outputs   = (const AVFilterPad[]) {{ .name          = "default",
540
+                                          .type          = AVMEDIA_TYPE_AUDIO,
541
+                                          .config_props  = config_output,
542
+                                          .request_frame = request_frame },
543
+                                        { .name = NULL}},
544
+};
... ...
@@ -37,6 +37,7 @@ void avfilter_register_all(void)
37 37
     REGISTER_FILTER (ACONVERT,    aconvert,    af);
38 38
     REGISTER_FILTER (AFORMAT,     aformat,     af);
39 39
     REGISTER_FILTER (AMERGE,      amerge,      af);
40
+    REGISTER_FILTER (AMIX,        amix,        af);
40 41
     REGISTER_FILTER (ANULL,       anull,       af);
41 42
     REGISTER_FILTER (ARESAMPLE,   aresample,   af);
42 43
     REGISTER_FILTER (ASHOWINFO,   ashowinfo,   af);
... ...
@@ -29,7 +29,7 @@
29 29
 #include "libavutil/avutil.h"
30 30
 
31 31
 #define LIBAVFILTER_VERSION_MAJOR  2
32
-#define LIBAVFILTER_VERSION_MINOR 76
32
+#define LIBAVFILTER_VERSION_MINOR 77
33 33
 #define LIBAVFILTER_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
... ...
@@ -591,8 +591,8 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
591 591
         }
592 592
         if(!st->codec->codec_id){
593 593
             flv_set_audio_codec(s, st, st->codec, flags & FLV_AUDIO_CODECID_MASK);
594
-            flv->last_sample_rate = st->codec->sample_rate;
595
-            flv->last_channels    = st->codec->channels;
594
+            flv->last_sample_rate = sample_rate = st->codec->sample_rate;
595
+            flv->last_channels    = channels    = st->codec->channels;
596 596
         } else {
597 597
             AVCodecContext ctx;
598 598
             ctx.sample_rate = sample_rate;
... ...
@@ -79,6 +79,7 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
79 79
     uint32_t extra = 0;
80 80
     enum RTMPPacketType type;
81 81
     int size = 0;
82
+    int ret;
82 83
 
83 84
     if (ffurl_read(h, &hdr, 1) != 1)
84 85
         return AVERROR(EIO);
... ...
@@ -129,8 +130,9 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
129 129
     if (hdr != RTMP_PS_TWELVEBYTES)
130 130
         timestamp += prev_pkt[channel_id].timestamp;
131 131
 
132
-    if (ff_rtmp_packet_create(p, channel_id, type, timestamp, data_size))
133
-        return -1;
132
+    if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp,
133
+                                     data_size)) < 0)
134
+        return ret;
134 135
     p->extra = extra;
135 136
     // save history
136 137
     prev_pkt[channel_id].channel_id = channel_id;
... ...
@@ -115,12 +115,16 @@ static const uint8_t rtmp_server_key[] = {
115 115
 /**
116 116
  * Generate 'connect' call and send it to the server.
117 117
  */
118
-static void gen_connect(URLContext *s, RTMPContext *rt)
118
+static int gen_connect(URLContext *s, RTMPContext *rt)
119 119
 {
120 120
     RTMPPacket pkt;
121 121
     uint8_t *p;
122
+    int ret;
123
+
124
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
125
+                                     0, 4096)) < 0)
126
+        return ret;
122 127
 
123
-    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
124 128
     p = pkt.data;
125 129
 
126 130
     ff_amf_write_string(&p, "connect");
... ...
@@ -165,19 +169,23 @@ static void gen_connect(URLContext *s, RTMPContext *rt)
165 165
 
166 166
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
167 167
     ff_rtmp_packet_destroy(&pkt);
168
+
169
+    return 0;
168 170
 }
169 171
 
170 172
 /**
171 173
  * Generate 'releaseStream' call and send it to the server. It should make
172 174
  * the server release some channel for media streams.
173 175
  */
174
-static void gen_release_stream(URLContext *s, RTMPContext *rt)
176
+static int gen_release_stream(URLContext *s, RTMPContext *rt)
175 177
 {
176 178
     RTMPPacket pkt;
177 179
     uint8_t *p;
180
+    int ret;
178 181
 
179
-    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
180
-                          29 + strlen(rt->playpath));
182
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
183
+                                     0, 29 + strlen(rt->playpath))) < 0)
184
+        return ret;
181 185
 
182 186
     av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
183 187
     p = pkt.data;
... ...
@@ -188,19 +196,23 @@ static void gen_release_stream(URLContext *s, RTMPContext *rt)
188 188
 
189 189
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
190 190
     ff_rtmp_packet_destroy(&pkt);
191
+
192
+    return 0;
191 193
 }
192 194
 
193 195
 /**
194 196
  * Generate 'FCPublish' call and send it to the server. It should make
195 197
  * the server preapare for receiving media streams.
196 198
  */
197
-static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
199
+static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
198 200
 {
199 201
     RTMPPacket pkt;
200 202
     uint8_t *p;
203
+    int ret;
201 204
 
202
-    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
203
-                          25 + strlen(rt->playpath));
205
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
206
+                                     0, 25 + strlen(rt->playpath))) < 0)
207
+        return ret;
204 208
 
205 209
     av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
206 210
     p = pkt.data;
... ...
@@ -211,19 +223,23 @@ static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
211 211
 
212 212
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
213 213
     ff_rtmp_packet_destroy(&pkt);
214
+
215
+    return 0;
214 216
 }
215 217
 
216 218
 /**
217 219
  * Generate 'FCUnpublish' call and send it to the server. It should make
218 220
  * the server destroy stream.
219 221
  */
220
-static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
222
+static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
221 223
 {
222 224
     RTMPPacket pkt;
223 225
     uint8_t *p;
226
+    int ret;
224 227
 
225
-    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
226
-                          27 + strlen(rt->playpath));
228
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
229
+                                     0, 27 + strlen(rt->playpath))) < 0)
230
+        return ret;
227 231
 
228 232
     av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
229 233
     p = pkt.data;
... ...
@@ -234,19 +250,25 @@ static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
234 234
 
235 235
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
236 236
     ff_rtmp_packet_destroy(&pkt);
237
+
238
+    return 0;
237 239
 }
238 240
 
239 241
 /**
240 242
  * Generate 'createStream' call and send it to the server. It should make
241 243
  * the server allocate some channel for media streams.
242 244
  */
243
-static void gen_create_stream(URLContext *s, RTMPContext *rt)
245
+static int gen_create_stream(URLContext *s, RTMPContext *rt)
244 246
 {
245 247
     RTMPPacket pkt;
246 248
     uint8_t *p;
249
+    int ret;
247 250
 
248 251
     av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
249
-    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 25);
252
+
253
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
254
+                                     0, 25)) < 0)
255
+        return ret;
250 256
 
251 257
     p = pkt.data;
252 258
     ff_amf_write_string(&p, "createStream");
... ...
@@ -256,6 +278,8 @@ static void gen_create_stream(URLContext *s, RTMPContext *rt)
256 256
 
257 257
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
258 258
     ff_rtmp_packet_destroy(&pkt);
259
+
260
+    return 0;
259 261
 }
260 262
 
261 263
 
... ...
@@ -263,13 +287,17 @@ static void gen_create_stream(URLContext *s, RTMPContext *rt)
263 263
  * Generate 'deleteStream' call and send it to the server. It should make
264 264
  * the server remove some channel for media streams.
265 265
  */
266
-static void gen_delete_stream(URLContext *s, RTMPContext *rt)
266
+static int gen_delete_stream(URLContext *s, RTMPContext *rt)
267 267
 {
268 268
     RTMPPacket pkt;
269 269
     uint8_t *p;
270
+    int ret;
270 271
 
271 272
     av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
272
-    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 34);
273
+
274
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
275
+                                     0, 34)) < 0)
276
+        return ret;
273 277
 
274 278
     p = pkt.data;
275 279
     ff_amf_write_string(&p, "deleteStream");
... ...
@@ -279,20 +307,26 @@ static void gen_delete_stream(URLContext *s, RTMPContext *rt)
279 279
 
280 280
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
281 281
     ff_rtmp_packet_destroy(&pkt);
282
+
283
+    return 0;
282 284
 }
283 285
 
284 286
 /**
285 287
  * Generate 'play' call and send it to the server, then ping the server
286 288
  * to start actual playing.
287 289
  */
288
-static void gen_play(URLContext *s, RTMPContext *rt)
290
+static int gen_play(URLContext *s, RTMPContext *rt)
289 291
 {
290 292
     RTMPPacket pkt;
291 293
     uint8_t *p;
294
+    int ret;
292 295
 
293 296
     av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
294
-    ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
295
-                          29 + strlen(rt->playpath));
297
+
298
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
299
+                                     0, 29 + strlen(rt->playpath))) < 0)
300
+        return ret;
301
+
296 302
     pkt.extra = rt->main_channel_id;
297 303
 
298 304
     p = pkt.data;
... ...
@@ -306,7 +340,9 @@ static void gen_play(URLContext *s, RTMPContext *rt)
306 306
     ff_rtmp_packet_destroy(&pkt);
307 307
 
308 308
     // set client buffer time disguised in ping packet
309
-    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
309
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
310
+                                     1, 10)) < 0)
311
+        return ret;
310 312
 
311 313
     p = pkt.data;
312 314
     bytestream_put_be16(&p, 3);
... ...
@@ -315,19 +351,25 @@ static void gen_play(URLContext *s, RTMPContext *rt)
315 315
 
316 316
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
317 317
     ff_rtmp_packet_destroy(&pkt);
318
+
319
+    return 0;
318 320
 }
319 321
 
320 322
 /**
321 323
  * Generate 'publish' call and send it to the server.
322 324
  */
323
-static void gen_publish(URLContext *s, RTMPContext *rt)
325
+static int gen_publish(URLContext *s, RTMPContext *rt)
324 326
 {
325 327
     RTMPPacket pkt;
326 328
     uint8_t *p;
329
+    int ret;
327 330
 
328 331
     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
329
-    ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, 0,
330
-                          30 + strlen(rt->playpath));
332
+
333
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
334
+                                     0, 30 + strlen(rt->playpath))) < 0)
335
+        return ret;
336
+
331 337
     pkt.extra = rt->main_channel_id;
332 338
 
333 339
     p = pkt.data;
... ...
@@ -339,48 +381,65 @@ static void gen_publish(URLContext *s, RTMPContext *rt)
339 339
 
340 340
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
341 341
     ff_rtmp_packet_destroy(&pkt);
342
+
343
+    return ret;
342 344
 }
343 345
 
344 346
 /**
345 347
  * Generate ping reply and send it to the server.
346 348
  */
347
-static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
349
+static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
348 350
 {
349 351
     RTMPPacket pkt;
350 352
     uint8_t *p;
353
+    int ret;
354
+
355
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
356
+                                     ppkt->timestamp + 1, 6)) < 0)
357
+        return ret;
351 358
 
352
-    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, ppkt->timestamp + 1, 6);
353 359
     p = pkt.data;
354 360
     bytestream_put_be16(&p, 7);
355 361
     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
356 362
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
357 363
     ff_rtmp_packet_destroy(&pkt);
364
+
365
+    return 0;
358 366
 }
359 367
 
360 368
 /**
361 369
  * Generate server bandwidth message and send it to the server.
362 370
  */
363
-static void gen_server_bw(URLContext *s, RTMPContext *rt)
371
+static int gen_server_bw(URLContext *s, RTMPContext *rt)
364 372
 {
365 373
     RTMPPacket pkt;
366 374
     uint8_t *p;
375
+    int ret;
376
+
377
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
378
+                                     0, 4)) < 0)
379
+        return ret;
367 380
 
368
-    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW, 0, 4);
369 381
     p = pkt.data;
370 382
     bytestream_put_be32(&p, 2500000);
371 383
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
372 384
     ff_rtmp_packet_destroy(&pkt);
385
+
386
+    return 0;
373 387
 }
374 388
 
375 389
 /**
376 390
  * Generate check bandwidth message and send it to the server.
377 391
  */
378
-static void gen_check_bw(URLContext *s, RTMPContext *rt)
392
+static int gen_check_bw(URLContext *s, RTMPContext *rt)
379 393
 {
380 394
     RTMPPacket pkt;
381 395
     uint8_t *p;
396
+    int ret;
382 397
 
383
-    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 21);
398
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
399
+                                     0, 21)) < 0)
400
+        return ret;
384 401
 
385 402
     p = pkt.data;
386 403
     ff_amf_write_string(&p, "_checkbw");
... ...
@@ -389,21 +448,29 @@ static void gen_check_bw(URLContext *s, RTMPContext *rt)
389 389
 
390 390
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
391 391
     ff_rtmp_packet_destroy(&pkt);
392
+
393
+    return ret;
392 394
 }
393 395
 
394 396
 /**
395 397
  * Generate report on bytes read so far and send it to the server.
396 398
  */
397
-static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
399
+static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
398 400
 {
399 401
     RTMPPacket pkt;
400 402
     uint8_t *p;
403
+    int ret;
404
+
405
+    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
406
+                                     ts, 4)) < 0)
407
+        return ret;
401 408
 
402
-    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ, ts, 4);
403 409
     p = pkt.data;
404 410
     bytestream_put_be32(&p, rt->bytes_read);
405 411
     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
406 412
     ff_rtmp_packet_destroy(&pkt);
413
+
414
+    return 0;
407 415
 }
408 416
 
409 417
 //TODO: Move HMAC code somewhere. Eventually.
... ...
@@ -421,14 +488,16 @@ static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
421 421
  * @param keylen digest key length
422 422
  * @param dst    buffer where calculated digest will be stored (32 bytes)
423 423
  */
424
-static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
425
-                             const uint8_t *key, int keylen, uint8_t *dst)
424
+static int rtmp_calc_digest(const uint8_t *src, int len, int gap,
425
+                            const uint8_t *key, int keylen, uint8_t *dst)
426 426
 {
427 427
     struct AVSHA *sha;
428 428
     uint8_t hmac_buf[64+32] = {0};
429 429
     int i;
430 430
 
431 431
     sha = av_mallocz(av_sha_size);
432
+    if (!sha)
433
+        return AVERROR(ENOMEM);
432 434
 
433 435
     if (keylen < 64) {
434 436
         memcpy(hmac_buf, key, keylen);
... ...
@@ -457,6 +526,8 @@ static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
457 457
     av_sha_final(sha, dst);
458 458
 
459 459
     av_free(sha);
460
+
461
+    return 0;
460 462
 }
461 463
 
462 464
 /**
... ...
@@ -469,14 +540,18 @@ static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
469 469
 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
470 470
 {
471 471
     int i, digest_pos = 0;
472
+    int ret;
472 473
 
473 474
     for (i = 8; i < 12; i++)
474 475
         digest_pos += buf[i];
475 476
     digest_pos = (digest_pos % 728) + 12;
476 477
 
477
-    rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
478
-                     rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
479
-                     buf + digest_pos);
478
+    ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
479
+                           rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
480
+                           buf + digest_pos);
481
+    if (ret < 0)
482
+        return ret;
483
+
480 484
     return digest_pos;
481 485
 }
482 486
 
... ...
@@ -491,14 +566,18 @@ static int rtmp_validate_digest(uint8_t *buf, int off)
491 491
 {
492 492
     int i, digest_pos = 0;
493 493
     uint8_t digest[32];
494
+    int ret;
494 495
 
495 496
     for (i = 0; i < 4; i++)
496 497
         digest_pos += buf[i + off];
497 498
     digest_pos = (digest_pos % 728) + off + 4;
498 499
 
499
-    rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
500
-                     rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
501
-                     digest);
500
+    ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
501
+                           rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
502
+                           digest);
503
+    if (ret < 0)
504
+        return ret;
505
+
502 506
     if (!memcmp(digest, buf + digest_pos, 32))
503 507
         return digest_pos;
504 508
     return 0;
... ...
@@ -526,6 +605,7 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt)
526 526
     int i;
527 527
     int server_pos, client_pos;
528 528
     uint8_t digest[32];
529
+    int ret;
529 530
 
530 531
     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
531 532
 
... ...
@@ -534,17 +614,19 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt)
534 534
     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
535 535
         tosend[i] = av_lfg_get(&rnd) >> 24;
536 536
     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
537
+    if (client_pos < 0)
538
+        return client_pos;
537 539
 
538 540
     ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
539 541
     i = ffurl_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
540 542
     if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
541 543
         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
542
-        return -1;
544
+        return AVERROR(EIO);
543 545
     }
544 546
     i = ffurl_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
545 547
     if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
546 548
         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
547
-        return -1;
549
+        return AVERROR(EIO);
548 550
     }
549 551
 
550 552
     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
... ...
@@ -552,33 +634,48 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt)
552 552
 
553 553
     if (rt->is_input && serverdata[5] >= 3) {
554 554
         server_pos = rtmp_validate_digest(serverdata + 1, 772);
555
+        if (server_pos < 0)
556
+            return server_pos;
557
+
555 558
         if (!server_pos) {
556 559
             server_pos = rtmp_validate_digest(serverdata + 1, 8);
560
+            if (server_pos < 0)
561
+                return server_pos;
562
+
557 563
             if (!server_pos) {
558 564
                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
559
-                return -1;
565
+                return AVERROR(EIO);
560 566
             }
561 567
         }
562 568
 
563
-        rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
564
-                         rtmp_server_key, sizeof(rtmp_server_key),
565
-                         digest);
566
-        rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE-32, 0,
567
-                         digest, 32,
568
-                         digest);
569
+        ret = rtmp_calc_digest(tosend + 1 + client_pos, 32, 0, rtmp_server_key,
570
+                               sizeof(rtmp_server_key), digest);
571
+        if (ret < 0)
572
+            return ret;
573
+
574
+        ret = rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
575
+                               digest, 32, digest);
576
+        if (ret < 0)
577
+            return ret;
578
+
569 579
         if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
570 580
             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
571
-            return -1;
581
+            return AVERROR(EIO);
572 582
         }
573 583
 
574 584
         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
575 585
             tosend[i] = av_lfg_get(&rnd) >> 24;
576
-        rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
577
-                         rtmp_player_key, sizeof(rtmp_player_key),
578
-                         digest);
579
-        rtmp_calc_digest(tosend,  RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
580
-                         digest, 32,
581
-                         tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
586
+        ret = rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
587
+                               rtmp_player_key, sizeof(rtmp_player_key),
588
+                               digest);
589
+        if (ret < 0)
590
+            return ret;
591
+
592
+        ret = rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
593
+                               digest, 32,
594
+                               tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
595
+        if (ret < 0)
596
+            return ret;
582 597
 
583 598
         // write reply back to the server
584 599
         ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
... ...
@@ -599,6 +696,7 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
599 599
 {
600 600
     int i, t;
601 601
     const uint8_t *data_end = pkt->data + pkt->data_size;
602
+    int ret;
602 603
 
603 604
 #ifdef DEBUG
604 605
     ff_rtmp_packet_dump(s, pkt);
... ...
@@ -623,7 +721,8 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
623 623
     case RTMP_PT_PING:
624 624
         t = AV_RB16(pkt->data);
625 625
         if (t == 6)
626
-            gen_pong(s, rt, pkt);
626
+            if ((ret = gen_pong(s, rt, pkt)) < 0)
627
+                return ret;
627 628
         break;
628 629
     case RTMP_PT_CLIENT_BW:
629 630
         if (pkt->data_size < 4) {
... ...
@@ -648,14 +747,18 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
648 648
             switch (rt->state) {
649 649
             case STATE_HANDSHAKED:
650 650
                 if (!rt->is_input) {
651
-                    gen_release_stream(s, rt);
652
-                    gen_fcpublish_stream(s, rt);
651
+                    if ((ret = gen_release_stream(s, rt)) < 0)
652
+                        return ret;
653
+                    if ((ret = gen_fcpublish_stream(s, rt)) < 0)
654
+                        return ret;
653 655
                     rt->state = STATE_RELEASING;
654 656
                 } else {
655
-                    gen_server_bw(s, rt);
657
+                    if ((ret = gen_server_bw(s, rt)) < 0)
658
+                        return ret;
656 659
                     rt->state = STATE_CONNECTING;
657 660
                 }
658
-                gen_create_stream(s, rt);
661
+                if ((ret = gen_create_stream(s, rt)) < 0)
662
+                    return ret;
659 663
                 break;
660 664
             case STATE_FCPUBLISH:
661 665
                 rt->state = STATE_CONNECTING;
... ...
@@ -679,9 +782,11 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
679 679
                     rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
680 680
                 }
681 681
                 if (rt->is_input) {
682
-                    gen_play(s, rt);
682
+                    if ((ret = gen_play(s, rt)) < 0)
683
+                        return ret;
683 684
                 } else {
684
-                    gen_publish(s, rt);
685
+                    if ((ret = gen_publish(s, rt)) < 0)
686
+                        return ret;
685 687
                 }
686 688
                 rt->state = STATE_READY;
687 689
                 break;
... ...
@@ -711,7 +816,8 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
711 711
             if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
712 712
             if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
713 713
         } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
714
-            gen_check_bw(s, rt);
714
+            if ((ret = gen_check_bw(s, rt)) < 0)
715
+                return ret;
715 716
         }
716 717
         break;
717 718
     }
... ...
@@ -754,14 +860,15 @@ static int get_packet(URLContext *s, int for_header)
754 754
         rt->bytes_read += ret;
755 755
         if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
756 756
             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
757
-            gen_bytes_read(s, rt, rpkt.timestamp + 1);
757
+            if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
758
+                return ret;
758 759
             rt->last_bytes_read = rt->bytes_read;
759 760
         }
760 761
 
761 762
         ret = rtmp_parse_result(s, rt, &rpkt);
762 763
         if (ret < 0) {//serious error in current packet
763 764
             ff_rtmp_packet_destroy(&rpkt);
764
-            return -1;
765
+            return ret;
765 766
         }
766 767
         if (rt->state == STATE_STOPPED) {
767 768
             ff_rtmp_packet_destroy(&rpkt);
... ...
@@ -825,20 +932,21 @@ static int get_packet(URLContext *s, int for_header)
825 825
 static int rtmp_close(URLContext *h)
826 826
 {
827 827
     RTMPContext *rt = h->priv_data;
828
+    int ret = 0;
828 829
 
829 830
     if (!rt->is_input) {
830 831
         rt->flv_data = NULL;
831 832
         if (rt->out_pkt.data_size)
832 833
             ff_rtmp_packet_destroy(&rt->out_pkt);
833 834
         if (rt->state > STATE_FCPUBLISH)
834
-            gen_fcunpublish_stream(h, rt);
835
+            ret = gen_fcunpublish_stream(h, rt);
835 836
     }
836 837
     if (rt->state > STATE_HANDSHAKED)
837
-        gen_delete_stream(h, rt);
838
+        ret = gen_delete_stream(h, rt);
838 839
 
839 840
     av_freep(&rt->flv_data);
840 841
     ffurl_close(rt->stream);
841
-    return 0;
842
+    return ret;
842 843
 }
843 844
 
844 845
 /**
... ...
@@ -868,14 +976,14 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
868 868
         port = RTMP_DEFAULT_PORT;
869 869
     ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
870 870
 
871
-    if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
872
-                   &s->interrupt_callback, NULL) < 0) {
871
+    if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
872
+                          &s->interrupt_callback, NULL)) < 0) {
873 873
         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
874 874
         goto fail;
875 875
     }
876 876
 
877 877
     rt->state = STATE_START;
878
-    if (rtmp_handshake(s, rt))
878
+    if ((ret = rtmp_handshake(s, rt)) < 0)
879 879
         goto fail;
880 880
 
881 881
     rt->chunk_size = 128;
... ...
@@ -886,8 +994,8 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
886 886
 
887 887
     rt->app = av_malloc(APP_MAX_LENGTH);
888 888
     if (!rt->app) {
889
-        rtmp_close(s);
890
-        return AVERROR(ENOMEM);
889
+        ret = AVERROR(ENOMEM);
890
+        goto fail;
891 891
     }
892 892
 
893 893
     //extract "app" part from path
... ...
@@ -922,8 +1030,8 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
922 922
     if (!rt->playpath) {
923 923
         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
924 924
         if (!rt->playpath) {
925
-            rtmp_close(s);
926
-            return AVERROR(ENOMEM);
925
+            ret = AVERROR(ENOMEM);
926
+            goto fail;
927 927
         }
928 928
 
929 929
         if (!strchr(fname, ':') &&
... ...
@@ -938,12 +1046,20 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
938 938
 
939 939
     if (!rt->tcurl) {
940 940
         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
941
+        if (!rt->tcurl) {
942
+            ret = AVERROR(ENOMEM);
943
+            goto fail;
944
+        }
941 945
         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
942 946
                     port, "/%s", rt->app);
943 947
     }
944 948
 
945 949
     if (!rt->flashver) {
946 950
         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
951
+        if (!rt->flashver) {
952
+            ret = AVERROR(ENOMEM);
953
+            goto fail;
954
+        }
947 955
         if (rt->is_input) {
948 956
             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
949 957
                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
... ...
@@ -960,7 +1076,8 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
960 960
 
961 961
     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
962 962
            proto, path, rt->app, rt->playpath);
963
-    gen_connect(s, rt);
963
+    if ((ret = gen_connect(s, rt)) < 0)
964
+        goto fail;
964 965
 
965 966
     do {
966 967
         ret = get_packet(s, 1);
... ...
@@ -987,7 +1104,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
987 987
 
988 988
 fail:
989 989
     rtmp_close(s);
990
-    return AVERROR(EIO);
990
+    return ret;
991 991
 }
992 992
 
993 993
 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
... ...
@@ -1024,6 +1141,7 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
1024 1024
     int pktsize, pkttype;
1025 1025
     uint32_t ts;
1026 1026
     const uint8_t *buf_temp = buf;
1027
+    int ret;
1027 1028
 
1028 1029
     do {
1029 1030
         if (rt->skip_bytes) {
... ...
@@ -1059,7 +1177,10 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
1059 1059
             }
1060 1060
 
1061 1061
             //this can be a big packet, it's better to send it right here
1062
-            ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL, pkttype, ts, pktsize);
1062
+            if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
1063
+                                             pkttype, ts, pktsize)) < 0)
1064
+                return ret;
1065
+
1063 1066
             rt->out_pkt.extra = rt->main_channel_id;
1064 1067
             rt->flv_data = rt->out_pkt.data;
1065 1068
 
... ...
@@ -39,8 +39,8 @@ fate-nellymoser-aref-encode: $(AREF)
39 39
 fate-nellymoser-aref-encode: CMD = enc_dec_pcm flv wav s16le $(REF) -c:a nellymoser
40 40
 fate-nellymoser-aref-encode: CMP = stddev
41 41
 fate-nellymoser-aref-encode: REF = ./tests/data/acodec-16000-1.ref.wav
42
-fate-nellymoser-aref-encode: CMP_SHIFT = -1172
43
-fate-nellymoser-aref-encode: CMP_TARGET = 9617
42
+fate-nellymoser-aref-encode: CMP_SHIFT = -244
43
+fate-nellymoser-aref-encode: CMP_TARGET = 9612
44 44
 fate-nellymoser-aref-encode: SIZE_TOLERANCE = 268
45 45
 
46 46
 FATE_SAMPLES_AUDIO += fate-sierra-vmd-audio