* qatar/master:
mss3: use standard zigzag table
mss3: split DSP functions that are used in MTS2(MSS4) into separate file
motion-test: do not use getopt()
tcp: add initial timeout limit for incoming connections
configure: Change the rdtsc check to a linker check
avconv: propagate fatal errors from lavfi.
lavfi: add error handling to filter_samples().
fate-run: make avconv() properly deal with multiple inputs.
asplit: don't leak the input buffer.
af_resample: fix request_frame() behavior.
af_asyncts: fix request_frame() behavior.
libx264: support aspect ratio switching
matroskadec: honor error_recognition when encountering unknown elements.
lavr: resampling: add support for s32p, fltp, and dblp internal sample formats
lavr: resampling: add filter type and Kaiser window beta to AVOptions
lavr: Use AV_SAMPLE_FMT_NONE to auto-select the internal sample format
lavr: mix: validate internal sample format in ff_audio_mix_init()
Conflicts:
ffmpeg.c
ffplay.c
libavcodec/libx264.c
libavfilter/audio.c
libavfilter/split.c
libavformat/tcp.c
tests/fate-run.sh
Merged-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -327,7 +327,7 @@ OBJS-$(CONFIG_MSMPEG4V3_ENCODER) += msmpeg4.o msmpeg4enc.o msmpeg4data.o \ |
327 | 327 |
h263dec.o h263.o ituh263dec.o \ |
328 | 328 |
mpeg4videodec.o |
329 | 329 |
OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o |
330 |
-OBJS-$(CONFIG_MSA1_DECODER) += mss3.o |
|
330 |
+OBJS-$(CONFIG_MSA1_DECODER) += mss3.o mss34dsp.o |
|
331 | 331 |
OBJS-$(CONFIG_MSS1_DECODER) += mss1.o |
332 | 332 |
OBJS-$(CONFIG_MSVIDEO1_DECODER) += msvideo1.o |
333 | 333 |
OBJS-$(CONFIG_MSVIDEO1_ENCODER) += msvideo1enc.o elbg.o |
... | ... |
@@ -175,10 +175,10 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, |
175 | 175 |
x4->params.b_tff = frame->top_field_first; |
176 | 176 |
x264_encoder_reconfig(x4->enc, &x4->params); |
177 | 177 |
} |
178 |
- if (x4->params.vui.i_sar_height != ctx->sample_aspect_ratio.den |
|
179 |
- || x4->params.vui.i_sar_width != ctx->sample_aspect_ratio.num) { |
|
178 |
+ if (x4->params.vui.i_sar_height != ctx->sample_aspect_ratio.den || |
|
179 |
+ x4->params.vui.i_sar_width != ctx->sample_aspect_ratio.num) { |
|
180 | 180 |
x4->params.vui.i_sar_height = ctx->sample_aspect_ratio.den; |
181 |
- x4->params.vui.i_sar_width = ctx->sample_aspect_ratio.num; |
|
181 |
+ x4->params.vui.i_sar_width = ctx->sample_aspect_ratio.num; |
|
182 | 182 |
x264_encoder_reconfig(x4->enc, &x4->params); |
183 | 183 |
} |
184 | 184 |
} |
... | ... |
@@ -119,15 +119,9 @@ int main(int argc, char **argv) |
119 | 119 |
int flags[2] = { AV_CPU_FLAG_MMX, AV_CPU_FLAG_MMX2 }; |
120 | 120 |
int flags_size = HAVE_MMX2 ? 2 : 1; |
121 | 121 |
|
122 |
- for(;;) { |
|
123 |
- c = getopt(argc, argv, "h"); |
|
124 |
- if (c == -1) |
|
125 |
- break; |
|
126 |
- switch(c) { |
|
127 |
- case 'h': |
|
128 |
- help(); |
|
129 |
- return 1; |
|
130 |
- } |
|
122 |
+ if (argc > 1) { |
|
123 |
+ help(); |
|
124 |
+ return 1; |
|
131 | 125 |
} |
132 | 126 |
|
133 | 127 |
printf("ffmpeg motion test\n"); |
... | ... |
@@ -26,6 +26,8 @@ |
26 | 26 |
|
27 | 27 |
#include "avcodec.h" |
28 | 28 |
#include "bytestream.h" |
29 |
+#include "dsputil.h" |
|
30 |
+#include "mss34dsp.h" |
|
29 | 31 |
|
30 | 32 |
#define HEADER_SIZE 27 |
31 | 33 |
|
... | ... |
@@ -119,39 +121,6 @@ typedef struct MSS3Context { |
119 | 119 |
int hblock[16 * 16]; |
120 | 120 |
} MSS3Context; |
121 | 121 |
|
122 |
-static const uint8_t mss3_luma_quant[64] = { |
|
123 |
- 16, 11, 10, 16, 24, 40, 51, 61, |
|
124 |
- 12, 12, 14, 19, 26, 58, 60, 55, |
|
125 |
- 14, 13, 16, 24, 40, 57, 69, 56, |
|
126 |
- 14, 17, 22, 29, 51, 87, 80, 62, |
|
127 |
- 18, 22, 37, 56, 68, 109, 103, 77, |
|
128 |
- 24, 35, 55, 64, 81, 104, 113, 92, |
|
129 |
- 49, 64, 78, 87, 103, 121, 120, 101, |
|
130 |
- 72, 92, 95, 98, 112, 100, 103, 99 |
|
131 |
-}; |
|
132 |
- |
|
133 |
-static const uint8_t mss3_chroma_quant[64] = { |
|
134 |
- 17, 18, 24, 47, 99, 99, 99, 99, |
|
135 |
- 18, 21, 26, 66, 99, 99, 99, 99, |
|
136 |
- 24, 26, 56, 99, 99, 99, 99, 99, |
|
137 |
- 47, 66, 99, 99, 99, 99, 99, 99, |
|
138 |
- 99, 99, 99, 99, 99, 99, 99, 99, |
|
139 |
- 99, 99, 99, 99, 99, 99, 99, 99, |
|
140 |
- 99, 99, 99, 99, 99, 99, 99, 99, |
|
141 |
- 99, 99, 99, 99, 99, 99, 99, 99 |
|
142 |
-}; |
|
143 |
- |
|
144 |
-static const uint8_t zigzag_scan[64] = { |
|
145 |
- 0, 1, 8, 16, 9, 2, 3, 10, |
|
146 |
- 17, 24, 32, 25, 18, 11, 4, 5, |
|
147 |
- 12, 19, 26, 33, 40, 48, 41, 34, |
|
148 |
- 27, 20, 13, 6, 7, 14, 21, 28, |
|
149 |
- 35, 42, 49, 56, 57, 50, 43, 36, |
|
150 |
- 29, 22, 15, 23, 30, 37, 44, 51, |
|
151 |
- 58, 59, 52, 45, 38, 31, 39, 46, |
|
152 |
- 53, 60, 61, 54, 47, 55, 62, 63 |
|
153 |
-}; |
|
154 |
- |
|
155 | 122 |
|
156 | 123 |
static void model2_reset(Model2 *m) |
157 | 124 |
{ |
... | ... |
@@ -578,7 +547,7 @@ static int decode_dct(RangeCoder *c, DCTBlockCoder *bc, int *block, |
578 | 578 |
if (!sign) |
579 | 579 |
val = -val; |
580 | 580 |
|
581 |
- zz_pos = zigzag_scan[pos]; |
|
581 |
+ zz_pos = ff_zigzag_direct[pos]; |
|
582 | 582 |
block[zz_pos] = val * bc->qmat[zz_pos]; |
583 | 583 |
pos++; |
584 | 584 |
} |
... | ... |
@@ -586,58 +555,6 @@ static int decode_dct(RangeCoder *c, DCTBlockCoder *bc, int *block, |
586 | 586 |
return pos == 64 ? 0 : -1; |
587 | 587 |
} |
588 | 588 |
|
589 |
-#define DCT_TEMPLATE(blk, step, SOP, shift) \ |
|
590 |
- const int t0 = -39409 * blk[7 * step] - 58980 * blk[1 * step]; \ |
|
591 |
- const int t1 = 39410 * blk[1 * step] - 58980 * blk[7 * step]; \ |
|
592 |
- const int t2 = -33410 * blk[5 * step] - 167963 * blk[3 * step]; \ |
|
593 |
- const int t3 = 33410 * blk[3 * step] - 167963 * blk[5 * step]; \ |
|
594 |
- const int t4 = blk[3 * step] + blk[7 * step]; \ |
|
595 |
- const int t5 = blk[1 * step] + blk[5 * step]; \ |
|
596 |
- const int t6 = 77062 * t4 + 51491 * t5; \ |
|
597 |
- const int t7 = 77062 * t5 - 51491 * t4; \ |
|
598 |
- const int t8 = 35470 * blk[2 * step] - 85623 * blk[6 * step]; \ |
|
599 |
- const int t9 = 35470 * blk[6 * step] + 85623 * blk[2 * step]; \ |
|
600 |
- const int tA = SOP(blk[0 * step] - blk[4 * step]); \ |
|
601 |
- const int tB = SOP(blk[0 * step] + blk[4 * step]); \ |
|
602 |
- \ |
|
603 |
- blk[0 * step] = ( t1 + t6 + t9 + tB) >> shift; \ |
|
604 |
- blk[1 * step] = ( t3 + t7 + t8 + tA) >> shift; \ |
|
605 |
- blk[2 * step] = ( t2 + t6 - t8 + tA) >> shift; \ |
|
606 |
- blk[3 * step] = ( t0 + t7 - t9 + tB) >> shift; \ |
|
607 |
- blk[4 * step] = (-(t0 + t7) - t9 + tB) >> shift; \ |
|
608 |
- blk[5 * step] = (-(t2 + t6) - t8 + tA) >> shift; \ |
|
609 |
- blk[6 * step] = (-(t3 + t7) + t8 + tA) >> shift; \ |
|
610 |
- blk[7 * step] = (-(t1 + t6) + t9 + tB) >> shift; \ |
|
611 |
- |
|
612 |
-#define SOP_ROW(a) ((a) << 16) + 0x2000 |
|
613 |
-#define SOP_COL(a) ((a + 32) << 16) |
|
614 |
- |
|
615 |
-static void dct_put(uint8_t *dst, int stride, int *block) |
|
616 |
-{ |
|
617 |
- int i, j; |
|
618 |
- int *ptr; |
|
619 |
- |
|
620 |
- ptr = block; |
|
621 |
- for (i = 0; i < 8; i++) { |
|
622 |
- DCT_TEMPLATE(ptr, 1, SOP_ROW, 13); |
|
623 |
- ptr += 8; |
|
624 |
- } |
|
625 |
- |
|
626 |
- ptr = block; |
|
627 |
- for (i = 0; i < 8; i++) { |
|
628 |
- DCT_TEMPLATE(ptr, 8, SOP_COL, 22); |
|
629 |
- ptr++; |
|
630 |
- } |
|
631 |
- |
|
632 |
- ptr = block; |
|
633 |
- for (j = 0; j < 8; j++) { |
|
634 |
- for (i = 0; i < 8; i++) |
|
635 |
- dst[i] = av_clip_uint8(ptr[i] + 128); |
|
636 |
- dst += stride; |
|
637 |
- ptr += 8; |
|
638 |
- } |
|
639 |
-} |
|
640 |
- |
|
641 | 589 |
static void decode_dct_block(RangeCoder *c, DCTBlockCoder *bc, |
642 | 590 |
uint8_t *dst, int stride, int block_size, |
643 | 591 |
int *block, int mb_x, int mb_y) |
... | ... |
@@ -655,7 +572,7 @@ static void decode_dct_block(RangeCoder *c, DCTBlockCoder *bc, |
655 | 655 |
c->got_error = 1; |
656 | 656 |
return; |
657 | 657 |
} |
658 |
- dct_put(dst + i * 8, stride, block); |
|
658 |
+ ff_mss34_dct_put(dst + i * 8, stride, block); |
|
659 | 659 |
} |
660 | 660 |
dst += 8 * stride; |
661 | 661 |
} |
... | ... |
@@ -702,14 +619,6 @@ static void decode_haar_block(RangeCoder *c, HaarBlockCoder *hc, |
702 | 702 |
} |
703 | 703 |
} |
704 | 704 |
|
705 |
-static void gen_quant_mat(uint16_t *qmat, const uint8_t *ref, float scale) |
|
706 |
-{ |
|
707 |
- int i; |
|
708 |
- |
|
709 |
- for (i = 0; i < 64; i++) |
|
710 |
- qmat[i] = (uint16_t)(ref[i] * scale + 50.0) / 100; |
|
711 |
-} |
|
712 |
- |
|
713 | 705 |
static void reset_coders(MSS3Context *ctx, int quality) |
714 | 706 |
{ |
715 | 707 |
int i, j; |
... | ... |
@@ -726,15 +635,8 @@ static void reset_coders(MSS3Context *ctx, int quality) |
726 | 726 |
for (j = 0; j < 125; j++) |
727 | 727 |
model_reset(&ctx->image_coder[i].vq_model[j]); |
728 | 728 |
if (ctx->dct_coder[i].quality != quality) { |
729 |
- float scale; |
|
730 | 729 |
ctx->dct_coder[i].quality = quality; |
731 |
- if (quality > 50) |
|
732 |
- scale = 200.0f - 2 * quality; |
|
733 |
- else |
|
734 |
- scale = 5000.0f / quality; |
|
735 |
- gen_quant_mat(ctx->dct_coder[i].qmat, |
|
736 |
- i ? mss3_chroma_quant : mss3_luma_quant, |
|
737 |
- scale); |
|
730 |
+ ff_mss34_gen_quant_mat(ctx->dct_coder[i].qmat, quality, !i); |
|
738 | 731 |
} |
739 | 732 |
memset(ctx->dct_coder[i].prev_dc, 0, |
740 | 733 |
sizeof(*ctx->dct_coder[i].prev_dc) * |
741 | 734 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,114 @@ |
0 |
+/* |
|
1 |
+ * Common stuff for some Microsoft Screen codecs |
|
2 |
+ * Copyright (C) 2012 Konstantin Shishkov |
|
3 |
+ * |
|
4 |
+ * This file is part of FFmpeg. |
|
5 |
+ * |
|
6 |
+ * FFmpeg 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 |
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#include <stdint.h> |
|
22 |
+#include "libavutil/common.h" |
|
23 |
+#include "mss34dsp.h" |
|
24 |
+ |
|
25 |
+static const uint8_t luma_quant[64] = { |
|
26 |
+ 16, 11, 10, 16, 24, 40, 51, 61, |
|
27 |
+ 12, 12, 14, 19, 26, 58, 60, 55, |
|
28 |
+ 14, 13, 16, 24, 40, 57, 69, 56, |
|
29 |
+ 14, 17, 22, 29, 51, 87, 80, 62, |
|
30 |
+ 18, 22, 37, 56, 68, 109, 103, 77, |
|
31 |
+ 24, 35, 55, 64, 81, 104, 113, 92, |
|
32 |
+ 49, 64, 78, 87, 103, 121, 120, 101, |
|
33 |
+ 72, 92, 95, 98, 112, 100, 103, 99 |
|
34 |
+}; |
|
35 |
+ |
|
36 |
+static const uint8_t chroma_quant[64] = { |
|
37 |
+ 17, 18, 24, 47, 99, 99, 99, 99, |
|
38 |
+ 18, 21, 26, 66, 99, 99, 99, 99, |
|
39 |
+ 24, 26, 56, 99, 99, 99, 99, 99, |
|
40 |
+ 47, 66, 99, 99, 99, 99, 99, 99, |
|
41 |
+ 99, 99, 99, 99, 99, 99, 99, 99, |
|
42 |
+ 99, 99, 99, 99, 99, 99, 99, 99, |
|
43 |
+ 99, 99, 99, 99, 99, 99, 99, 99, |
|
44 |
+ 99, 99, 99, 99, 99, 99, 99, 99 |
|
45 |
+}; |
|
46 |
+ |
|
47 |
+void ff_mss34_gen_quant_mat(uint16_t *qmat, int quality, int luma) |
|
48 |
+{ |
|
49 |
+ int i; |
|
50 |
+ const uint8_t *qsrc = luma ? luma_quant : chroma_quant; |
|
51 |
+ |
|
52 |
+ if (quality >= 50) { |
|
53 |
+ int scale = 200 - 2 * quality; |
|
54 |
+ |
|
55 |
+ for (i = 0; i < 64; i++) |
|
56 |
+ qmat[i] = (qsrc[i] * scale + 50) / 100; |
|
57 |
+ } else { |
|
58 |
+ for (i = 0; i < 64; i++) |
|
59 |
+ qmat[i] = (5000 * qsrc[i] / quality + 50) / 100; |
|
60 |
+ } |
|
61 |
+} |
|
62 |
+ |
|
63 |
+#define DCT_TEMPLATE(blk, step, SOP, shift) \ |
|
64 |
+ const int t0 = -39409 * blk[7 * step] - 58980 * blk[1 * step]; \ |
|
65 |
+ const int t1 = 39410 * blk[1 * step] - 58980 * blk[7 * step]; \ |
|
66 |
+ const int t2 = -33410 * blk[5 * step] - 167963 * blk[3 * step]; \ |
|
67 |
+ const int t3 = 33410 * blk[3 * step] - 167963 * blk[5 * step]; \ |
|
68 |
+ const int t4 = blk[3 * step] + blk[7 * step]; \ |
|
69 |
+ const int t5 = blk[1 * step] + blk[5 * step]; \ |
|
70 |
+ const int t6 = 77062 * t4 + 51491 * t5; \ |
|
71 |
+ const int t7 = 77062 * t5 - 51491 * t4; \ |
|
72 |
+ const int t8 = 35470 * blk[2 * step] - 85623 * blk[6 * step]; \ |
|
73 |
+ const int t9 = 35470 * blk[6 * step] + 85623 * blk[2 * step]; \ |
|
74 |
+ const int tA = SOP(blk[0 * step] - blk[4 * step]); \ |
|
75 |
+ const int tB = SOP(blk[0 * step] + blk[4 * step]); \ |
|
76 |
+ \ |
|
77 |
+ blk[0 * step] = ( t1 + t6 + t9 + tB) >> shift; \ |
|
78 |
+ blk[1 * step] = ( t3 + t7 + t8 + tA) >> shift; \ |
|
79 |
+ blk[2 * step] = ( t2 + t6 - t8 + tA) >> shift; \ |
|
80 |
+ blk[3 * step] = ( t0 + t7 - t9 + tB) >> shift; \ |
|
81 |
+ blk[4 * step] = (-(t0 + t7) - t9 + tB) >> shift; \ |
|
82 |
+ blk[5 * step] = (-(t2 + t6) - t8 + tA) >> shift; \ |
|
83 |
+ blk[6 * step] = (-(t3 + t7) + t8 + tA) >> shift; \ |
|
84 |
+ blk[7 * step] = (-(t1 + t6) + t9 + tB) >> shift; \ |
|
85 |
+ |
|
86 |
+#define SOP_ROW(a) ((a) << 16) + 0x2000 |
|
87 |
+#define SOP_COL(a) ((a + 32) << 16) |
|
88 |
+ |
|
89 |
+void ff_mss34_dct_put(uint8_t *dst, int stride, int *block) |
|
90 |
+{ |
|
91 |
+ int i, j; |
|
92 |
+ int *ptr; |
|
93 |
+ |
|
94 |
+ ptr = block; |
|
95 |
+ for (i = 0; i < 8; i++) { |
|
96 |
+ DCT_TEMPLATE(ptr, 1, SOP_ROW, 13); |
|
97 |
+ ptr += 8; |
|
98 |
+ } |
|
99 |
+ |
|
100 |
+ ptr = block; |
|
101 |
+ for (i = 0; i < 8; i++) { |
|
102 |
+ DCT_TEMPLATE(ptr, 8, SOP_COL, 22); |
|
103 |
+ ptr++; |
|
104 |
+ } |
|
105 |
+ |
|
106 |
+ ptr = block; |
|
107 |
+ for (j = 0; j < 8; j++) { |
|
108 |
+ for (i = 0; i < 8; i++) |
|
109 |
+ dst[i] = av_clip_uint8(ptr[i] + 128); |
|
110 |
+ dst += stride; |
|
111 |
+ ptr += 8; |
|
112 |
+ } |
|
113 |
+} |
0 | 114 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,45 @@ |
0 |
+/* |
|
1 |
+ * Common stuff for some Microsoft Screen codecs |
|
2 |
+ * Copyright (C) 2012 Konstantin Shishkov |
|
3 |
+ * |
|
4 |
+ * This file is part of FFmpeg. |
|
5 |
+ * |
|
6 |
+ * FFmpeg 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 |
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#ifndef AVCODEC_MSS34DSP_H |
|
22 |
+#define AVCODEC_MSS34DSP_H |
|
23 |
+ |
|
24 |
+#include <stdint.h> |
|
25 |
+ |
|
26 |
+/** |
|
27 |
+ * Generate quantisation matrix for given quality. |
|
28 |
+ * |
|
29 |
+ * @param qmat destination matrix |
|
30 |
+ * @param quality quality setting (1-100) |
|
31 |
+ * @param luma generate quantisation matrix for luma or chroma |
|
32 |
+ */ |
|
33 |
+void ff_mss34_gen_quant_mat(uint16_t *qmat, int quality, int luma); |
|
34 |
+ |
|
35 |
+/** |
|
36 |
+ * Transform and output DCT block. |
|
37 |
+ * |
|
38 |
+ * @param dst output plane |
|
39 |
+ * @param stride output plane stride |
|
40 |
+ * @param block block to transform and output |
|
41 |
+ */ |
|
42 |
+void ff_mss34_dct_put(uint8_t *dst, int stride, int *block); |
|
43 |
+ |
|
44 |
+#endif /* AVCODEC_MSS34DSP_H */ |
... | ... |
@@ -135,12 +135,13 @@ static int config_output(AVFilterLink *outlink) |
135 | 135 |
return 0; |
136 | 136 |
} |
137 | 137 |
|
138 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) |
|
138 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) |
|
139 | 139 |
{ |
140 | 140 |
AConvertContext *aconvert = inlink->dst->priv; |
141 | 141 |
const int n = insamplesref->audio->nb_samples; |
142 | 142 |
AVFilterLink *const outlink = inlink->dst->outputs[0]; |
143 | 143 |
AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n); |
144 |
+ int ret; |
|
144 | 145 |
|
145 | 146 |
swr_convert(aconvert->swr, outsamplesref->data, n, |
146 | 147 |
(void *)insamplesref->data, n); |
... | ... |
@@ -148,8 +149,9 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref |
148 | 148 |
avfilter_copy_buffer_ref_props(outsamplesref, insamplesref); |
149 | 149 |
outsamplesref->audio->channel_layout = outlink->channel_layout; |
150 | 150 |
|
151 |
- ff_filter_samples(outlink, outsamplesref); |
|
151 |
+ ret = ff_filter_samples(outlink, outsamplesref); |
|
152 | 152 |
avfilter_unref_buffer(insamplesref); |
153 |
+ return ret; |
|
153 | 154 |
} |
154 | 155 |
|
155 | 156 |
AVFilter avfilter_af_aconvert = { |
... | ... |
@@ -212,7 +212,7 @@ static inline void copy_samples(int nb_inputs, struct amerge_input in[], |
212 | 212 |
} |
213 | 213 |
} |
214 | 214 |
|
215 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
215 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
216 | 216 |
{ |
217 | 217 |
AVFilterContext *ctx = inlink->dst; |
218 | 218 |
AMergeContext *am = ctx->priv; |
... | ... |
@@ -232,7 +232,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
232 | 232 |
for (i = 1; i < am->nb_inputs; i++) |
233 | 233 |
nb_samples = FFMIN(nb_samples, am->in[i].nb_samples); |
234 | 234 |
if (!nb_samples) |
235 |
- return; |
|
235 |
+ return 0; |
|
236 | 236 |
|
237 | 237 |
outbuf = ff_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE, nb_samples); |
238 | 238 |
outs = outbuf->data[0]; |
... | ... |
@@ -285,7 +285,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
285 | 285 |
} |
286 | 286 |
} |
287 | 287 |
} |
288 |
- ff_filter_samples(ctx->outputs[0], outbuf); |
|
288 |
+ return ff_filter_samples(ctx->outputs[0], outbuf); |
|
289 | 289 |
} |
290 | 290 |
|
291 | 291 |
static av_cold int init(AVFilterContext *ctx, const char *args) |
... | ... |
@@ -305,9 +305,7 @@ static int output_frame(AVFilterLink *outlink, int nb_samples) |
305 | 305 |
if (s->next_pts != AV_NOPTS_VALUE) |
306 | 306 |
s->next_pts += nb_samples; |
307 | 307 |
|
308 |
- ff_filter_samples(outlink, out_buf); |
|
309 |
- |
|
310 |
- return 0; |
|
308 |
+ return ff_filter_samples(outlink, out_buf); |
|
311 | 309 |
} |
312 | 310 |
|
313 | 311 |
/** |
... | ... |
@@ -448,31 +446,37 @@ static int request_frame(AVFilterLink *outlink) |
448 | 448 |
return output_frame(outlink, available_samples); |
449 | 449 |
} |
450 | 450 |
|
451 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
451 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
452 | 452 |
{ |
453 | 453 |
AVFilterContext *ctx = inlink->dst; |
454 | 454 |
MixContext *s = ctx->priv; |
455 | 455 |
AVFilterLink *outlink = ctx->outputs[0]; |
456 |
- int i; |
|
456 |
+ int i, ret = 0; |
|
457 | 457 |
|
458 | 458 |
for (i = 0; i < ctx->nb_inputs; i++) |
459 | 459 |
if (ctx->inputs[i] == inlink) |
460 | 460 |
break; |
461 | 461 |
if (i >= ctx->nb_inputs) { |
462 | 462 |
av_log(ctx, AV_LOG_ERROR, "unknown input link\n"); |
463 |
- return; |
|
463 |
+ ret = AVERROR(EINVAL); |
|
464 |
+ goto fail; |
|
464 | 465 |
} |
465 | 466 |
|
466 | 467 |
if (i == 0) { |
467 | 468 |
int64_t pts = av_rescale_q(buf->pts, inlink->time_base, |
468 | 469 |
outlink->time_base); |
469 |
- frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts); |
|
470 |
+ ret = frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts); |
|
471 |
+ if (ret < 0) |
|
472 |
+ goto fail; |
|
470 | 473 |
} |
471 | 474 |
|
472 |
- av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data, |
|
473 |
- buf->audio->nb_samples); |
|
475 |
+ ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data, |
|
476 |
+ buf->audio->nb_samples); |
|
474 | 477 |
|
478 |
+fail: |
|
475 | 479 |
avfilter_unref_buffer(buf); |
480 |
+ |
|
481 |
+ return ret; |
|
476 | 482 |
} |
477 | 483 |
|
478 | 484 |
static int init(AVFilterContext *ctx, const char *args) |
... | ... |
@@ -168,13 +168,14 @@ static int config_output(AVFilterLink *outlink) |
168 | 168 |
return 0; |
169 | 169 |
} |
170 | 170 |
|
171 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) |
|
171 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) |
|
172 | 172 |
{ |
173 | 173 |
AResampleContext *aresample = inlink->dst->priv; |
174 | 174 |
const int n_in = insamplesref->audio->nb_samples; |
175 | 175 |
int n_out = n_in * aresample->ratio * 2 ; |
176 | 176 |
AVFilterLink *const outlink = inlink->dst->outputs[0]; |
177 | 177 |
AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n_out); |
178 |
+ int ret; |
|
178 | 179 |
|
179 | 180 |
|
180 | 181 |
avfilter_copy_buffer_ref_props(outsamplesref, insamplesref); |
... | ... |
@@ -193,15 +194,16 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref |
193 | 193 |
if (n_out <= 0) { |
194 | 194 |
avfilter_unref_buffer(outsamplesref); |
195 | 195 |
avfilter_unref_buffer(insamplesref); |
196 |
- return; |
|
196 |
+ return 0; |
|
197 | 197 |
} |
198 | 198 |
|
199 | 199 |
outsamplesref->audio->sample_rate = outlink->sample_rate; |
200 | 200 |
outsamplesref->audio->nb_samples = n_out; |
201 | 201 |
|
202 |
- ff_filter_samples(outlink, outsamplesref); |
|
202 |
+ ret = ff_filter_samples(outlink, outsamplesref); |
|
203 | 203 |
aresample->req_fullfilled= 1; |
204 | 204 |
avfilter_unref_buffer(insamplesref); |
205 |
+ return ret; |
|
205 | 206 |
} |
206 | 207 |
|
207 | 208 |
static int request_frame(AVFilterLink *outlink) |
... | ... |
@@ -131,7 +131,7 @@ static int push_samples(AVFilterLink *outlink) |
131 | 131 |
return nb_out_samples; |
132 | 132 |
} |
133 | 133 |
|
134 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
134 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
135 | 135 |
{ |
136 | 136 |
AVFilterContext *ctx = inlink->dst; |
137 | 137 |
ASNSContext *asns = ctx->priv; |
... | ... |
@@ -145,7 +145,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
145 | 145 |
if (ret < 0) { |
146 | 146 |
av_log(ctx, AV_LOG_ERROR, |
147 | 147 |
"Stretching audio fifo failed, discarded %d samples\n", nb_samples); |
148 |
- return; |
|
148 |
+ return -1; |
|
149 | 149 |
} |
150 | 150 |
} |
151 | 151 |
av_audio_fifo_write(asns->fifo, (void **)insamples->extended_data, nb_samples); |
... | ... |
@@ -155,6 +155,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
155 | 155 |
|
156 | 156 |
if (av_audio_fifo_size(asns->fifo) >= asns->nb_out_samples) |
157 | 157 |
push_samples(outlink); |
158 |
+ return 0; |
|
158 | 159 |
} |
159 | 160 |
|
160 | 161 |
static int request_frame(AVFilterLink *outlink) |
... | ... |
@@ -40,7 +40,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args) |
40 | 40 |
return 0; |
41 | 41 |
} |
42 | 42 |
|
43 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) |
|
43 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) |
|
44 | 44 |
{ |
45 | 45 |
AVFilterContext *ctx = inlink->dst; |
46 | 46 |
ShowInfoContext *showinfo = ctx->priv; |
... | ... |
@@ -83,7 +83,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) |
83 | 83 |
av_log(ctx, AV_LOG_INFO, "]\n"); |
84 | 84 |
|
85 | 85 |
showinfo->frame++; |
86 |
- ff_filter_samples(inlink->dst->outputs[0], samplesref); |
|
86 |
+ return ff_filter_samples(inlink->dst->outputs[0], samplesref); |
|
87 | 87 |
} |
88 | 88 |
|
89 | 89 |
AVFilter avfilter_af_ashowinfo = { |
... | ... |
@@ -107,11 +107,12 @@ static int config_output(AVFilterLink *outlink) |
107 | 107 |
return 0; |
108 | 108 |
} |
109 | 109 |
|
110 |
-static void send_out(AVFilterContext *ctx, int out_id) |
|
110 |
+static int send_out(AVFilterContext *ctx, int out_id) |
|
111 | 111 |
{ |
112 | 112 |
AStreamSyncContext *as = ctx->priv; |
113 | 113 |
struct buf_queue *queue = &as->queue[out_id]; |
114 | 114 |
AVFilterBufferRef *buf = queue->buf[queue->tail]; |
115 |
+ int ret; |
|
115 | 116 |
|
116 | 117 |
queue->buf[queue->tail] = NULL; |
117 | 118 |
as->var_values[VAR_B1 + out_id]++; |
... | ... |
@@ -121,11 +122,12 @@ static void send_out(AVFilterContext *ctx, int out_id) |
121 | 121 |
av_q2d(ctx->outputs[out_id]->time_base) * buf->pts; |
122 | 122 |
as->var_values[VAR_T1 + out_id] += buf->audio->nb_samples / |
123 | 123 |
(double)ctx->inputs[out_id]->sample_rate; |
124 |
- ff_filter_samples(ctx->outputs[out_id], buf); |
|
124 |
+ ret = ff_filter_samples(ctx->outputs[out_id], buf); |
|
125 | 125 |
queue->nb--; |
126 | 126 |
queue->tail = (queue->tail + 1) % QUEUE_SIZE; |
127 | 127 |
if (as->req[out_id]) |
128 | 128 |
as->req[out_id]--; |
129 |
+ return ret; |
|
129 | 130 |
} |
130 | 131 |
|
131 | 132 |
static void send_next(AVFilterContext *ctx) |
... | ... |
@@ -165,7 +167,7 @@ static int request_frame(AVFilterLink *outlink) |
165 | 165 |
return 0; |
166 | 166 |
} |
167 | 167 |
|
168 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
168 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
169 | 169 |
{ |
170 | 170 |
AVFilterContext *ctx = inlink->dst; |
171 | 171 |
AStreamSyncContext *as = ctx->priv; |
... | ... |
@@ -175,6 +177,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
175 | 175 |
insamples; |
176 | 176 |
as->eof &= ~(1 << id); |
177 | 177 |
send_next(ctx); |
178 |
+ return 0; |
|
178 | 179 |
} |
179 | 180 |
|
180 | 181 |
AVFilter avfilter_af_astreamsync = { |
... | ... |
@@ -37,6 +37,9 @@ typedef struct ASyncContext { |
37 | 37 |
int resample; |
38 | 38 |
float min_delta_sec; |
39 | 39 |
int max_comp; |
40 |
+ |
|
41 |
+ /* set by filter_samples() to signal an output frame to request_frame() */ |
|
42 |
+ int got_output; |
|
40 | 43 |
} ASyncContext; |
41 | 44 |
|
42 | 45 |
#define OFFSET(x) offsetof(ASyncContext, x) |
... | ... |
@@ -112,9 +115,13 @@ static int request_frame(AVFilterLink *link) |
112 | 112 |
{ |
113 | 113 |
AVFilterContext *ctx = link->src; |
114 | 114 |
ASyncContext *s = ctx->priv; |
115 |
- int ret = ff_request_frame(ctx->inputs[0]); |
|
115 |
+ int ret = 0; |
|
116 | 116 |
int nb_samples; |
117 | 117 |
|
118 |
+ s->got_output = 0; |
|
119 |
+ while (ret >= 0 && !s->got_output) |
|
120 |
+ ret = ff_request_frame(ctx->inputs[0]); |
|
121 |
+ |
|
118 | 122 |
/* flush the fifo */ |
119 | 123 |
if (ret == AVERROR_EOF && (nb_samples = avresample_get_delay(s->avr))) { |
120 | 124 |
AVFilterBufferRef *buf = ff_get_audio_buffer(link, AV_PERM_WRITE, |
... | ... |
@@ -124,18 +131,18 @@ static int request_frame(AVFilterLink *link) |
124 | 124 |
avresample_convert(s->avr, (void**)buf->extended_data, buf->linesize[0], |
125 | 125 |
nb_samples, NULL, 0, 0); |
126 | 126 |
buf->pts = s->pts; |
127 |
- ff_filter_samples(link, buf); |
|
128 |
- return 0; |
|
127 |
+ return ff_filter_samples(link, buf); |
|
129 | 128 |
} |
130 | 129 |
|
131 | 130 |
return ret; |
132 | 131 |
} |
133 | 132 |
|
134 |
-static void write_to_fifo(ASyncContext *s, AVFilterBufferRef *buf) |
|
133 |
+static int write_to_fifo(ASyncContext *s, AVFilterBufferRef *buf) |
|
135 | 134 |
{ |
136 |
- avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data, |
|
137 |
- buf->linesize[0], buf->audio->nb_samples); |
|
135 |
+ int ret = avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data, |
|
136 |
+ buf->linesize[0], buf->audio->nb_samples); |
|
138 | 137 |
avfilter_unref_buffer(buf); |
138 |
+ return ret; |
|
139 | 139 |
} |
140 | 140 |
|
141 | 141 |
/* get amount of data currently buffered, in samples */ |
... | ... |
@@ -144,7 +151,7 @@ static int64_t get_delay(ASyncContext *s) |
144 | 144 |
return avresample_available(s->avr) + avresample_get_delay(s->avr); |
145 | 145 |
} |
146 | 146 |
|
147 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
147 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
148 | 148 |
{ |
149 | 149 |
AVFilterContext *ctx = inlink->dst; |
150 | 150 |
ASyncContext *s = ctx->priv; |
... | ... |
@@ -152,7 +159,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
152 | 152 |
int nb_channels = av_get_channel_layout_nb_channels(buf->audio->channel_layout); |
153 | 153 |
int64_t pts = (buf->pts == AV_NOPTS_VALUE) ? buf->pts : |
154 | 154 |
av_rescale_q(buf->pts, inlink->time_base, outlink->time_base); |
155 |
- int out_size; |
|
155 |
+ int out_size, ret; |
|
156 | 156 |
int64_t delta; |
157 | 157 |
|
158 | 158 |
/* buffer data until we get the first timestamp */ |
... | ... |
@@ -160,14 +167,12 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
160 | 160 |
if (pts != AV_NOPTS_VALUE) { |
161 | 161 |
s->pts = pts - get_delay(s); |
162 | 162 |
} |
163 |
- write_to_fifo(s, buf); |
|
164 |
- return; |
|
163 |
+ return write_to_fifo(s, buf); |
|
165 | 164 |
} |
166 | 165 |
|
167 | 166 |
/* now wait for the next timestamp */ |
168 | 167 |
if (pts == AV_NOPTS_VALUE) { |
169 |
- write_to_fifo(s, buf); |
|
170 |
- return; |
|
168 |
+ return write_to_fifo(s, buf); |
|
171 | 169 |
} |
172 | 170 |
|
173 | 171 |
/* when we have two timestamps, compute how many samples would we have |
... | ... |
@@ -190,8 +195,10 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
190 | 190 |
if (out_size > 0) { |
191 | 191 |
AVFilterBufferRef *buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE, |
192 | 192 |
out_size); |
193 |
- if (!buf_out) |
|
194 |
- return; |
|
193 |
+ if (!buf_out) { |
|
194 |
+ ret = AVERROR(ENOMEM); |
|
195 |
+ goto fail; |
|
196 |
+ } |
|
195 | 197 |
|
196 | 198 |
avresample_read(s->avr, (void**)buf_out->extended_data, out_size); |
197 | 199 |
buf_out->pts = s->pts; |
... | ... |
@@ -200,7 +207,10 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
200 | 200 |
av_samples_set_silence(buf_out->extended_data, out_size - delta, |
201 | 201 |
delta, nb_channels, buf->format); |
202 | 202 |
} |
203 |
- ff_filter_samples(outlink, buf_out); |
|
203 |
+ ret = ff_filter_samples(outlink, buf_out); |
|
204 |
+ if (ret < 0) |
|
205 |
+ goto fail; |
|
206 |
+ s->got_output = 1; |
|
204 | 207 |
} else { |
205 | 208 |
av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping " |
206 | 209 |
"whole buffer.\n"); |
... | ... |
@@ -210,9 +220,13 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
210 | 210 |
avresample_read(s->avr, NULL, avresample_available(s->avr)); |
211 | 211 |
|
212 | 212 |
s->pts = pts - avresample_get_delay(s->avr); |
213 |
- avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data, |
|
214 |
- buf->linesize[0], buf->audio->nb_samples); |
|
213 |
+ ret = avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data, |
|
214 |
+ buf->linesize[0], buf->audio->nb_samples); |
|
215 |
+ |
|
216 |
+fail: |
|
215 | 217 |
avfilter_unref_buffer(buf); |
218 |
+ |
|
219 |
+ return ret; |
|
216 | 220 |
} |
217 | 221 |
|
218 | 222 |
AVFilter avfilter_af_asyncts = { |
... | ... |
@@ -1040,7 +1040,7 @@ static void push_samples(ATempoContext *atempo, |
1040 | 1040 |
atempo->nsamples_out += n_out; |
1041 | 1041 |
} |
1042 | 1042 |
|
1043 |
-static void filter_samples(AVFilterLink *inlink, |
|
1043 |
+static int filter_samples(AVFilterLink *inlink, |
|
1044 | 1044 |
AVFilterBufferRef *src_buffer) |
1045 | 1045 |
{ |
1046 | 1046 |
AVFilterContext *ctx = inlink->dst; |
... | ... |
@@ -1074,6 +1074,7 @@ static void filter_samples(AVFilterLink *inlink, |
1074 | 1074 |
|
1075 | 1075 |
atempo->nsamples_in += n_in; |
1076 | 1076 |
avfilter_unref_bufferp(&src_buffer); |
1077 |
+ return 0; |
|
1077 | 1078 |
} |
1078 | 1079 |
|
1079 | 1080 |
static int request_frame(AVFilterLink *outlink) |
... | ... |
@@ -313,7 +313,7 @@ static int channelmap_query_formats(AVFilterContext *ctx) |
313 | 313 |
return 0; |
314 | 314 |
} |
315 | 315 |
|
316 |
-static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
316 |
+static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
317 | 317 |
{ |
318 | 318 |
AVFilterContext *ctx = inlink->dst; |
319 | 319 |
AVFilterLink *outlink = ctx->outputs[0]; |
... | ... |
@@ -330,8 +330,10 @@ static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *b |
330 | 330 |
if (nch_out > FF_ARRAY_ELEMS(buf->data)) { |
331 | 331 |
uint8_t **new_extended_data = |
332 | 332 |
av_mallocz(nch_out * sizeof(*buf->extended_data)); |
333 |
- if (!new_extended_data) |
|
334 |
- return; |
|
333 |
+ if (!new_extended_data) { |
|
334 |
+ avfilter_unref_buffer(buf); |
|
335 |
+ return AVERROR(ENOMEM); |
|
336 |
+ } |
|
335 | 337 |
if (buf->extended_data == buf->data) { |
336 | 338 |
buf->extended_data = new_extended_data; |
337 | 339 |
} else { |
... | ... |
@@ -353,7 +355,7 @@ static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *b |
353 | 353 |
memcpy(buf->data, buf->extended_data, |
354 | 354 |
FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0])); |
355 | 355 |
|
356 |
- ff_filter_samples(outlink, buf); |
|
356 |
+ return ff_filter_samples(outlink, buf); |
|
357 | 357 |
} |
358 | 358 |
|
359 | 359 |
static int channelmap_config_input(AVFilterLink *inlink) |
... | ... |
@@ -105,24 +105,29 @@ static int query_formats(AVFilterContext *ctx) |
105 | 105 |
return 0; |
106 | 106 |
} |
107 | 107 |
|
108 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
108 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
109 | 109 |
{ |
110 | 110 |
AVFilterContext *ctx = inlink->dst; |
111 |
- int i; |
|
111 |
+ int i, ret = 0; |
|
112 | 112 |
|
113 | 113 |
for (i = 0; i < ctx->nb_outputs; i++) { |
114 | 114 |
AVFilterBufferRef *buf_out = avfilter_ref_buffer(buf, ~AV_PERM_WRITE); |
115 | 115 |
|
116 |
- if (!buf_out) |
|
117 |
- return; |
|
116 |
+ if (!buf_out) { |
|
117 |
+ ret = AVERROR(ENOMEM); |
|
118 |
+ break; |
|
119 |
+ } |
|
118 | 120 |
|
119 | 121 |
buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[i]; |
120 | 122 |
buf_out->audio->channel_layout = |
121 | 123 |
av_channel_layout_extract_channel(buf->audio->channel_layout, i); |
122 | 124 |
|
123 |
- ff_filter_samples(ctx->outputs[i], buf_out); |
|
125 |
+ ret = ff_filter_samples(ctx->outputs[i], buf_out); |
|
126 |
+ if (ret < 0) |
|
127 |
+ break; |
|
124 | 128 |
} |
125 | 129 |
avfilter_unref_buffer(buf); |
130 |
+ return ret; |
|
126 | 131 |
} |
127 | 132 |
|
128 | 133 |
AVFilter avfilter_af_channelsplit = { |
... | ... |
@@ -120,13 +120,15 @@ static inline int16_t *scalarproduct(const int16_t *in, const int16_t *endin, in |
120 | 120 |
return out; |
121 | 121 |
} |
122 | 122 |
|
123 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
123 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
124 | 124 |
{ |
125 | 125 |
AVFilterLink *outlink = inlink->dst->outputs[0]; |
126 | 126 |
int16_t *taps, *endin, *in, *out; |
127 | 127 |
AVFilterBufferRef *outsamples = |
128 | 128 |
ff_get_audio_buffer(inlink, AV_PERM_WRITE, |
129 | 129 |
insamples->audio->nb_samples); |
130 |
+ int ret; |
|
131 |
+ |
|
130 | 132 |
avfilter_copy_buffer_ref_props(outsamples, insamples); |
131 | 133 |
|
132 | 134 |
taps = ((EarwaxContext *)inlink->dst->priv)->taps; |
... | ... |
@@ -144,8 +146,9 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
144 | 144 |
// save part of input for next round |
145 | 145 |
memcpy(taps, endin, NUMTAPS * sizeof(*taps)); |
146 | 146 |
|
147 |
- ff_filter_samples(outlink, outsamples); |
|
147 |
+ ret = ff_filter_samples(outlink, outsamples); |
|
148 | 148 |
avfilter_unref_buffer(insamples); |
149 |
+ return ret; |
|
149 | 150 |
} |
150 | 151 |
|
151 | 152 |
AVFilter avfilter_af_earwax = { |
... | ... |
@@ -92,7 +92,7 @@ static const AVClass join_class = { |
92 | 92 |
.version = LIBAVUTIL_VERSION_INT, |
93 | 93 |
}; |
94 | 94 |
|
95 |
-static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) |
|
95 |
+static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) |
|
96 | 96 |
{ |
97 | 97 |
AVFilterContext *ctx = link->dst; |
98 | 98 |
JoinContext *s = ctx->priv; |
... | ... |
@@ -104,6 +104,8 @@ static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) |
104 | 104 |
av_assert0(i < ctx->nb_inputs); |
105 | 105 |
av_assert0(!s->input_frames[i]); |
106 | 106 |
s->input_frames[i] = buf; |
107 |
+ |
|
108 |
+ return 0; |
|
107 | 109 |
} |
108 | 110 |
|
109 | 111 |
static int parse_maps(AVFilterContext *ctx) |
... | ... |
@@ -468,11 +470,11 @@ static int join_request_frame(AVFilterLink *outlink) |
468 | 468 |
priv->nb_in_buffers = ctx->nb_inputs; |
469 | 469 |
buf->buf->priv = priv; |
470 | 470 |
|
471 |
- ff_filter_samples(outlink, buf); |
|
471 |
+ ret = ff_filter_samples(outlink, buf); |
|
472 | 472 |
|
473 | 473 |
memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs); |
474 | 474 |
|
475 |
- return 0; |
|
475 |
+ return ret; |
|
476 | 476 |
|
477 | 477 |
fail: |
478 | 478 |
avfilter_unref_buffer(buf); |
... | ... |
@@ -343,8 +343,9 @@ static int config_props(AVFilterLink *link) |
343 | 343 |
return 0; |
344 | 344 |
} |
345 | 345 |
|
346 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
346 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
347 | 347 |
{ |
348 |
+ int ret; |
|
348 | 349 |
int n = insamples->audio->nb_samples; |
349 | 350 |
AVFilterLink *const outlink = inlink->dst->outputs[0]; |
350 | 351 |
AVFilterBufferRef *outsamples = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n); |
... | ... |
@@ -354,8 +355,9 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
354 | 354 |
avfilter_copy_buffer_ref_props(outsamples, insamples); |
355 | 355 |
outsamples->audio->channel_layout = outlink->channel_layout; |
356 | 356 |
|
357 |
- ff_filter_samples(outlink, outsamples); |
|
357 |
+ ret = ff_filter_samples(outlink, outsamples); |
|
358 | 358 |
avfilter_unref_buffer(insamples); |
359 |
+ return ret; |
|
359 | 360 |
} |
360 | 361 |
|
361 | 362 |
static av_cold void uninit(AVFilterContext *ctx) |
... | ... |
@@ -38,6 +38,9 @@ typedef struct ResampleContext { |
38 | 38 |
AVAudioResampleContext *avr; |
39 | 39 |
|
40 | 40 |
int64_t next_pts; |
41 |
+ |
|
42 |
+ /* set by filter_samples() to signal an output frame to request_frame() */ |
|
43 |
+ int got_output; |
|
41 | 44 |
} ResampleContext; |
42 | 45 |
|
43 | 46 |
static av_cold void uninit(AVFilterContext *ctx) |
... | ... |
@@ -102,12 +105,6 @@ static int config_output(AVFilterLink *outlink) |
102 | 102 |
av_opt_set_int(s->avr, "in_sample_rate", inlink ->sample_rate, 0); |
103 | 103 |
av_opt_set_int(s->avr, "out_sample_rate", outlink->sample_rate, 0); |
104 | 104 |
|
105 |
- /* if both the input and output formats are s16 or u8, use s16 as |
|
106 |
- the internal sample format */ |
|
107 |
- if (av_get_bytes_per_sample(inlink->format) <= 2 && |
|
108 |
- av_get_bytes_per_sample(outlink->format) <= 2) |
|
109 |
- av_opt_set_int(s->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0); |
|
110 |
- |
|
111 | 105 |
if ((ret = avresample_open(s->avr)) < 0) |
112 | 106 |
return ret; |
113 | 107 |
|
... | ... |
@@ -130,7 +127,11 @@ static int request_frame(AVFilterLink *outlink) |
130 | 130 |
{ |
131 | 131 |
AVFilterContext *ctx = outlink->src; |
132 | 132 |
ResampleContext *s = ctx->priv; |
133 |
- int ret = ff_request_frame(ctx->inputs[0]); |
|
133 |
+ int ret = 0; |
|
134 |
+ |
|
135 |
+ s->got_output = 0; |
|
136 |
+ while (ret >= 0 && !s->got_output) |
|
137 |
+ ret = ff_request_frame(ctx->inputs[0]); |
|
134 | 138 |
|
135 | 139 |
/* flush the lavr delay buffer */ |
136 | 140 |
if (ret == AVERROR_EOF && s->avr) { |
... | ... |
@@ -156,21 +157,21 @@ static int request_frame(AVFilterLink *outlink) |
156 | 156 |
} |
157 | 157 |
|
158 | 158 |
buf->pts = s->next_pts; |
159 |
- ff_filter_samples(outlink, buf); |
|
160 |
- return 0; |
|
159 |
+ return ff_filter_samples(outlink, buf); |
|
161 | 160 |
} |
162 | 161 |
return ret; |
163 | 162 |
} |
164 | 163 |
|
165 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
164 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
166 | 165 |
{ |
167 | 166 |
AVFilterContext *ctx = inlink->dst; |
168 | 167 |
ResampleContext *s = ctx->priv; |
169 | 168 |
AVFilterLink *outlink = ctx->outputs[0]; |
169 |
+ int ret; |
|
170 | 170 |
|
171 | 171 |
if (s->avr) { |
172 | 172 |
AVFilterBufferRef *buf_out; |
173 |
- int delay, nb_samples, ret; |
|
173 |
+ int delay, nb_samples; |
|
174 | 174 |
|
175 | 175 |
/* maximum possible samples lavr can output */ |
176 | 176 |
delay = avresample_get_delay(s->avr); |
... | ... |
@@ -179,10 +180,19 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
179 | 179 |
AV_ROUND_UP); |
180 | 180 |
|
181 | 181 |
buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples); |
182 |
+ if (!buf_out) { |
|
183 |
+ ret = AVERROR(ENOMEM); |
|
184 |
+ goto fail; |
|
185 |
+ } |
|
186 |
+ |
|
182 | 187 |
ret = avresample_convert(s->avr, (void**)buf_out->extended_data, |
183 | 188 |
buf_out->linesize[0], nb_samples, |
184 | 189 |
(void**)buf->extended_data, buf->linesize[0], |
185 | 190 |
buf->audio->nb_samples); |
191 |
+ if (ret < 0) { |
|
192 |
+ avfilter_unref_buffer(buf_out); |
|
193 |
+ goto fail; |
|
194 |
+ } |
|
186 | 195 |
|
187 | 196 |
av_assert0(!avresample_available(s->avr)); |
188 | 197 |
|
... | ... |
@@ -208,11 +218,18 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) |
208 | 208 |
|
209 | 209 |
s->next_pts = buf_out->pts + buf_out->audio->nb_samples; |
210 | 210 |
|
211 |
- ff_filter_samples(outlink, buf_out); |
|
211 |
+ ret = ff_filter_samples(outlink, buf_out); |
|
212 |
+ s->got_output = 1; |
|
212 | 213 |
} |
214 |
+ |
|
215 |
+fail: |
|
213 | 216 |
avfilter_unref_buffer(buf); |
214 |
- } else |
|
215 |
- ff_filter_samples(outlink, buf); |
|
217 |
+ } else { |
|
218 |
+ ret = ff_filter_samples(outlink, buf); |
|
219 |
+ s->got_output = 1; |
|
220 |
+ } |
|
221 |
+ |
|
222 |
+ return ret; |
|
216 | 223 |
} |
217 | 224 |
|
218 | 225 |
AVFilter avfilter_af_resample = { |
... | ... |
@@ -78,7 +78,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args) |
78 | 78 |
return 0; |
79 | 79 |
} |
80 | 80 |
|
81 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
81 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
82 | 82 |
{ |
83 | 83 |
int i; |
84 | 84 |
SilenceDetectContext *silence = inlink->dst->priv; |
... | ... |
@@ -118,7 +118,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
118 | 118 |
} |
119 | 119 |
} |
120 | 120 |
|
121 |
- ff_filter_samples(inlink->dst->outputs[0], insamples); |
|
121 |
+ return ff_filter_samples(inlink->dst->outputs[0], insamples); |
|
122 | 122 |
} |
123 | 123 |
|
124 | 124 |
static int query_formats(AVFilterContext *ctx) |
... | ... |
@@ -110,7 +110,7 @@ static int query_formats(AVFilterContext *ctx) |
110 | 110 |
return 0; |
111 | 111 |
} |
112 | 112 |
|
113 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
113 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
114 | 114 |
{ |
115 | 115 |
VolumeContext *vol = inlink->dst->priv; |
116 | 116 |
AVFilterLink *outlink = inlink->dst->outputs[0]; |
... | ... |
@@ -169,7 +169,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
169 | 169 |
} |
170 | 170 |
} |
171 | 171 |
} |
172 |
- ff_filter_samples(outlink, insamples); |
|
172 |
+ return ff_filter_samples(outlink, insamples); |
|
173 | 173 |
} |
174 | 174 |
|
175 | 175 |
AVFilter avfilter_af_volume = { |
... | ... |
@@ -21,7 +21,10 @@ |
21 | 21 |
#include "avfilter.h" |
22 | 22 |
#include "internal.h" |
23 | 23 |
|
24 |
-static void null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) { } |
|
24 |
+static int null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) |
|
25 |
+{ |
|
26 |
+ return 0; |
|
27 |
+} |
|
25 | 28 |
|
26 | 29 |
AVFilter avfilter_asink_anullsink = { |
27 | 30 |
.name = "anullsink", |
... | ... |
@@ -150,19 +150,19 @@ fail: |
150 | 150 |
return NULL; |
151 | 151 |
} |
152 | 152 |
|
153 |
-static void default_filter_samples(AVFilterLink *link, |
|
154 |
- AVFilterBufferRef *samplesref) |
|
153 |
+static int default_filter_samples(AVFilterLink *link, |
|
154 |
+ AVFilterBufferRef *samplesref) |
|
155 | 155 |
{ |
156 |
- ff_filter_samples(link->dst->outputs[0], samplesref); |
|
156 |
+ return ff_filter_samples(link->dst->outputs[0], samplesref); |
|
157 | 157 |
} |
158 | 158 |
|
159 |
-void ff_filter_samples_framed(AVFilterLink *link, |
|
160 |
- AVFilterBufferRef *samplesref) |
|
159 |
+int ff_filter_samples_framed(AVFilterLink *link, AVFilterBufferRef *samplesref) |
|
161 | 160 |
{ |
162 |
- void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); |
|
161 |
+ int (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); |
|
163 | 162 |
AVFilterPad *dst = link->dstpad; |
164 | 163 |
int64_t pts; |
165 | 164 |
AVFilterBufferRef *buf_out; |
165 |
+ int ret; |
|
166 | 166 |
|
167 | 167 |
FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1); |
168 | 168 |
|
... | ... |
@@ -193,21 +193,22 @@ void ff_filter_samples_framed(AVFilterLink *link, |
193 | 193 |
|
194 | 194 |
link->cur_buf = buf_out; |
195 | 195 |
pts = buf_out->pts; |
196 |
- filter_samples(link, buf_out); |
|
196 |
+ ret = filter_samples(link, buf_out); |
|
197 | 197 |
ff_update_link_current_pts(link, pts); |
198 |
+ return ret; |
|
198 | 199 |
} |
199 | 200 |
|
200 |
-void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) |
|
201 |
+int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) |
|
201 | 202 |
{ |
202 | 203 |
int insamples = samplesref->audio->nb_samples, inpos = 0, nb_samples; |
203 | 204 |
AVFilterBufferRef *pbuf = link->partial_buf; |
204 | 205 |
int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); |
206 |
+ int ret = 0; |
|
205 | 207 |
|
206 | 208 |
if (!link->min_samples || |
207 | 209 |
(!pbuf && |
208 | 210 |
insamples >= link->min_samples && insamples <= link->max_samples)) { |
209 |
- ff_filter_samples_framed(link, samplesref); |
|
210 |
- return; |
|
211 |
+ return ff_filter_samples_framed(link, samplesref); |
|
211 | 212 |
} |
212 | 213 |
/* Handle framing (min_samples, max_samples) */ |
213 | 214 |
while (insamples) { |
... | ... |
@@ -218,7 +219,7 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) |
218 | 218 |
if (!pbuf) { |
219 | 219 |
av_log(link->dst, AV_LOG_WARNING, |
220 | 220 |
"Samples dropped due to memory allocation failure.\n"); |
221 |
- return; |
|
221 |
+ return 0; |
|
222 | 222 |
} |
223 | 223 |
avfilter_copy_buffer_ref_props(pbuf, samplesref); |
224 | 224 |
pbuf->pts = samplesref->pts + |
... | ... |
@@ -234,10 +235,11 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) |
234 | 234 |
insamples -= nb_samples; |
235 | 235 |
pbuf->audio->nb_samples += nb_samples; |
236 | 236 |
if (pbuf->audio->nb_samples >= link->min_samples) { |
237 |
- ff_filter_samples_framed(link, pbuf); |
|
237 |
+ ret = ff_filter_samples_framed(link, pbuf); |
|
238 | 238 |
pbuf = NULL; |
239 | 239 |
} |
240 | 240 |
} |
241 | 241 |
avfilter_unref_buffer(samplesref); |
242 | 242 |
link->partial_buf = pbuf; |
243 |
+ return ret; |
|
243 | 244 |
} |
... | ... |
@@ -70,14 +70,17 @@ AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms, |
70 | 70 |
* @param samplesref a reference to the buffer of audio samples being sent. The |
71 | 71 |
* receiving filter will free this reference when it no longer |
72 | 72 |
* needs it or pass it on to the next filter. |
73 |
+ * |
|
74 |
+ * @return >= 0 on success, a negative AVERROR on error. The receiving filter |
|
75 |
+ * is responsible for unreferencing samplesref in case of error. |
|
73 | 76 |
*/ |
74 |
-void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); |
|
77 |
+int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); |
|
75 | 78 |
|
76 | 79 |
/** |
77 | 80 |
* Send a buffer of audio samples to the next link, without checking |
78 | 81 |
* min_samples. |
79 | 82 |
*/ |
80 |
-void ff_filter_samples_framed(AVFilterLink *link, |
|
83 |
+int ff_filter_samples_framed(AVFilterLink *link, |
|
81 | 84 |
AVFilterBufferRef *samplesref); |
82 | 85 |
|
83 | 86 |
#endif /* AVFILTER_AUDIO_H */ |
... | ... |
@@ -180,7 +180,7 @@ static int request_frame(AVFilterLink *outlink) |
180 | 180 |
|
181 | 181 |
#define MAX_INT16 ((1<<15) -1) |
182 | 182 |
|
183 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
183 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
184 | 184 |
{ |
185 | 185 |
AVFilterContext *ctx = inlink->dst; |
186 | 186 |
AVFilterLink *outlink = ctx->outputs[0]; |
... | ... |
@@ -225,6 +225,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
225 | 225 |
} |
226 | 226 |
|
227 | 227 |
avfilter_unref_buffer(insamples); |
228 |
+ return 0; |
|
228 | 229 |
} |
229 | 230 |
|
230 | 231 |
AVFilter avfilter_avf_showwaves = { |
... | ... |
@@ -301,8 +301,12 @@ struct AVFilterPad { |
301 | 301 |
* and should do its processing. |
302 | 302 |
* |
303 | 303 |
* Input audio pads only. |
304 |
+ * |
|
305 |
+ * @return >= 0 on success, a negative AVERROR on error. This function |
|
306 |
+ * must ensure that samplesref is properly unreferenced on error if it |
|
307 |
+ * hasn't been passed on to another filter. |
|
304 | 308 |
*/ |
305 |
- void (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); |
|
309 |
+ int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); |
|
306 | 310 |
|
307 | 311 |
/** |
308 | 312 |
* Frame poll callback. This returns the number of immediately available |
... | ... |
@@ -56,6 +56,12 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *buf) |
56 | 56 |
link->cur_buf = NULL; |
57 | 57 |
}; |
58 | 58 |
|
59 |
+static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) |
|
60 |
+{ |
|
61 |
+ start_frame(link, buf); |
|
62 |
+ return 0; |
|
63 |
+} |
|
64 |
+ |
|
59 | 65 |
int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf) |
60 | 66 |
{ |
61 | 67 |
BufferSinkContext *s = ctx->priv; |
... | ... |
@@ -160,7 +166,7 @@ AVFilter avfilter_asink_abuffer = { |
160 | 160 |
|
161 | 161 |
.inputs = (AVFilterPad[]) {{ .name = "default", |
162 | 162 |
.type = AVMEDIA_TYPE_AUDIO, |
163 |
- .filter_samples = start_frame, |
|
163 |
+ .filter_samples = filter_samples, |
|
164 | 164 |
.min_perms = AV_PERM_READ, |
165 | 165 |
.needs_fifo = 1 }, |
166 | 166 |
{ .name = NULL }}, |
... | ... |
@@ -408,6 +408,7 @@ static int request_frame(AVFilterLink *link) |
408 | 408 |
{ |
409 | 409 |
BufferSourceContext *c = link->src->priv; |
410 | 410 |
AVFilterBufferRef *buf; |
411 |
+ int ret = 0; |
|
411 | 412 |
|
412 | 413 |
if (!av_fifo_size(c->fifo)) { |
413 | 414 |
if (c->eof) |
... | ... |
@@ -424,7 +425,7 @@ static int request_frame(AVFilterLink *link) |
424 | 424 |
ff_end_frame(link); |
425 | 425 |
break; |
426 | 426 |
case AVMEDIA_TYPE_AUDIO: |
427 |
- ff_filter_samples(link, avfilter_ref_buffer(buf, ~0)); |
|
427 |
+ ret = ff_filter_samples(link, avfilter_ref_buffer(buf, ~0)); |
|
428 | 428 |
break; |
429 | 429 |
default: |
430 | 430 |
return AVERROR(EINVAL); |
... | ... |
@@ -432,7 +433,7 @@ static int request_frame(AVFilterLink *link) |
432 | 432 |
|
433 | 433 |
avfilter_unref_buffer(buf); |
434 | 434 |
|
435 |
- return 0; |
|
435 |
+ return ret; |
|
436 | 436 |
} |
437 | 437 |
|
438 | 438 |
static int poll_frame(AVFilterLink *link) |
... | ... |
@@ -117,7 +117,7 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) |
117 | 117 |
ff_start_frame(outlink, picref2); |
118 | 118 |
} |
119 | 119 |
|
120 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
120 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
|
121 | 121 |
{ |
122 | 122 |
AVFilterContext *ctx = inlink->dst; |
123 | 123 |
AVFilterLink *outlink = ctx->outputs[0]; |
... | ... |
@@ -132,7 +132,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
132 | 132 |
avfilter_unref_buffer(insamples); |
133 | 133 |
} |
134 | 134 |
|
135 |
- ff_filter_samples(outlink, outsamples); |
|
135 |
+ return ff_filter_samples(outlink, outsamples); |
|
136 | 136 |
} |
137 | 137 |
|
138 | 138 |
#if CONFIG_SETTB_FILTER |
... | ... |
@@ -72,13 +72,25 @@ static av_cold void uninit(AVFilterContext *ctx) |
72 | 72 |
avfilter_unref_buffer(fifo->buf_out); |
73 | 73 |
} |
74 | 74 |
|
75 |
-static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
75 |
+static int add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
76 | 76 |
{ |
77 | 77 |
FifoContext *fifo = inlink->dst->priv; |
78 | 78 |
|
79 | 79 |
fifo->last->next = av_mallocz(sizeof(Buf)); |
80 |
+ if (!fifo->last->next) { |
|
81 |
+ avfilter_unref_buffer(buf); |
|
82 |
+ return AVERROR(ENOMEM); |
|
83 |
+ } |
|
84 |
+ |
|
80 | 85 |
fifo->last = fifo->last->next; |
81 | 86 |
fifo->last->buf = buf; |
87 |
+ |
|
88 |
+ return 0; |
|
89 |
+} |
|
90 |
+ |
|
91 |
+static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) |
|
92 |
+{ |
|
93 |
+ add_to_queue(inlink, buf); |
|
82 | 94 |
} |
83 | 95 |
|
84 | 96 |
static void queue_pop(FifoContext *s) |
... | ... |
@@ -210,15 +222,13 @@ static int return_audio_frame(AVFilterContext *ctx) |
210 | 210 |
buf_out = s->buf_out; |
211 | 211 |
s->buf_out = NULL; |
212 | 212 |
} |
213 |
- ff_filter_samples(link, buf_out); |
|
214 |
- |
|
215 |
- return 0; |
|
213 |
+ return ff_filter_samples(link, buf_out); |
|
216 | 214 |
} |
217 | 215 |
|
218 | 216 |
static int request_frame(AVFilterLink *outlink) |
219 | 217 |
{ |
220 | 218 |
FifoContext *fifo = outlink->src->priv; |
221 |
- int ret; |
|
219 |
+ int ret = 0; |
|
222 | 220 |
|
223 | 221 |
if (!fifo->root.next) { |
224 | 222 |
if ((ret = ff_request_frame(outlink->src->inputs[0])) < 0) |
... | ... |
@@ -238,7 +248,7 @@ static int request_frame(AVFilterLink *outlink) |
238 | 238 |
if (outlink->request_samples) { |
239 | 239 |
return return_audio_frame(outlink->src); |
240 | 240 |
} else { |
241 |
- ff_filter_samples(outlink, fifo->root.next->buf); |
|
241 |
+ ret = ff_filter_samples(outlink, fifo->root.next->buf); |
|
242 | 242 |
queue_pop(fifo); |
243 | 243 |
} |
244 | 244 |
break; |
... | ... |
@@ -246,7 +256,7 @@ static int request_frame(AVFilterLink *outlink) |
246 | 246 |
return AVERROR(EINVAL); |
247 | 247 |
} |
248 | 248 |
|
249 |
- return 0; |
|
249 |
+ return ret; |
|
250 | 250 |
} |
251 | 251 |
|
252 | 252 |
AVFilter avfilter_vf_fifo = { |
... | ... |
@@ -261,7 +271,7 @@ AVFilter avfilter_vf_fifo = { |
261 | 261 |
.inputs = (const AVFilterPad[]) {{ .name = "default", |
262 | 262 |
.type = AVMEDIA_TYPE_VIDEO, |
263 | 263 |
.get_video_buffer= ff_null_get_video_buffer, |
264 |
- .start_frame = add_to_queue, |
|
264 |
+ .start_frame = start_frame, |
|
265 | 265 |
.draw_slice = draw_slice, |
266 | 266 |
.end_frame = end_frame, |
267 | 267 |
.rej_perms = AV_PERM_REUSE2, }, |
... | ... |
@@ -135,8 +135,12 @@ struct AVFilterPad { |
135 | 135 |
* and should do its processing. |
136 | 136 |
* |
137 | 137 |
* Input audio pads only. |
138 |
+ * |
|
139 |
+ * @return >= 0 on success, a negative AVERROR on error. This function |
|
140 |
+ * must ensure that samplesref is properly unreferenced on error if it |
|
141 |
+ * hasn't been passed on to another filter. |
|
138 | 142 |
*/ |
139 |
- void (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); |
|
143 |
+ int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); |
|
140 | 144 |
|
141 | 145 |
/** |
142 | 146 |
* Frame poll callback. This returns the number of immediately available |
... | ... |
@@ -244,9 +244,10 @@ AVFilter avfilter_vsink_buffersink = { |
244 | 244 |
|
245 | 245 |
#if CONFIG_ABUFFERSINK_FILTER |
246 | 246 |
|
247 |
-static void filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) |
|
247 |
+static int filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) |
|
248 | 248 |
{ |
249 | 249 |
end_frame(link); |
250 |
+ return 0; |
|
250 | 251 |
} |
251 | 252 |
|
252 | 253 |
static av_cold int asink_init(AVFilterContext *ctx, const char *args) |
... | ... |
@@ -110,15 +110,19 @@ AVFilter avfilter_vf_split = { |
110 | 110 |
.outputs = (AVFilterPad[]) {{ .name = NULL}}, |
111 | 111 |
}; |
112 | 112 |
|
113 |
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) |
|
113 |
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) |
|
114 | 114 |
{ |
115 | 115 |
AVFilterContext *ctx = inlink->dst; |
116 |
- int i; |
|
116 |
+ int i, ret = 0; |
|
117 | 117 |
|
118 |
- for (i = 0; i < ctx->nb_outputs; i++) |
|
119 |
- ff_filter_samples(inlink->dst->outputs[i], |
|
120 |
- avfilter_ref_buffer(samplesref, ~AV_PERM_WRITE)); |
|
118 |
+ for (i = 0; i < ctx->nb_outputs; i++) { |
|
119 |
+ ret = ff_filter_samples(inlink->dst->outputs[i], |
|
120 |
+ avfilter_ref_buffer(samplesref, ~AV_PERM_WRITE)); |
|
121 |
+ if (ret < 0) |
|
122 |
+ break; |
|
123 |
+ } |
|
121 | 124 |
avfilter_unref_buffer(samplesref); |
125 |
+ return ret; |
|
122 | 126 |
} |
123 | 127 |
|
124 | 128 |
AVFilter avfilter_af_asplit = { |
... | ... |
@@ -842,8 +842,11 @@ static int ebml_parse_id(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, |
842 | 842 |
matroska->num_levels > 0 && |
843 | 843 |
matroska->levels[matroska->num_levels-1].length == 0xffffffffffffff) |
844 | 844 |
return 0; // we reached the end of an unknown size cluster |
845 |
- if (!syntax[i].id && id != EBML_ID_VOID && id != EBML_ID_CRC32) |
|
845 |
+ if (!syntax[i].id && id != EBML_ID_VOID && id != EBML_ID_CRC32) { |
|
846 | 846 |
av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%X\n", id); |
847 |
+ if (matroska->ctx->error_recognition & AV_EF_EXPLODE) |
|
848 |
+ return AVERROR_INVALIDDATA; |
|
849 |
+ } |
|
847 | 850 |
return ebml_parse_elem(matroska, &syntax[i], data); |
848 | 851 |
} |
849 | 852 |
|
... | ... |
@@ -43,7 +43,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
43 | 43 |
char buf[256]; |
44 | 44 |
int ret; |
45 | 45 |
socklen_t optlen; |
46 |
- int timeout = 50; |
|
46 |
+ int timeout = 50, listen_timeout = -1; |
|
47 | 47 |
char hostname[1024],proto[1024],path[1024]; |
48 | 48 |
char portstr[10]; |
49 | 49 |
|
... | ... |
@@ -59,6 +59,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
59 | 59 |
if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { |
60 | 60 |
timeout = strtol(buf, NULL, 10); |
61 | 61 |
} |
62 |
+ if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { |
|
63 |
+ listen_timeout = strtol(buf, NULL, 10); |
|
64 |
+ } |
|
62 | 65 |
} |
63 | 66 |
hints.ai_family = AF_UNSPEC; |
64 | 67 |
hints.ai_socktype = SOCK_STREAM; |
... | ... |
@@ -87,6 +90,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
87 | 87 |
if (listen_socket) { |
88 | 88 |
int fd1; |
89 | 89 |
int reuse = 1; |
90 |
+ struct pollfd lp = { fd, POLLIN, 0 }; |
|
90 | 91 |
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); |
91 | 92 |
ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); |
92 | 93 |
if (ret) { |
... | ... |
@@ -98,6 +102,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
98 | 98 |
ret = ff_neterrno(); |
99 | 99 |
goto fail1; |
100 | 100 |
} |
101 |
+ ret = poll(&lp, 1, listen_timeout >= 0 ? listen_timeout : -1); |
|
102 |
+ if (ret <= 0) { |
|
103 |
+ ret = AVERROR(ETIMEDOUT); |
|
104 |
+ goto fail1; |
|
105 |
+ } |
|
101 | 106 |
fd1 = accept(fd, NULL, NULL); |
102 | 107 |
if (fd1 < 0) { |
103 | 108 |
ret = ff_neterrno(); |
... | ... |
@@ -305,6 +305,14 @@ int ff_audio_mix_init(AVAudioResampleContext *avr) |
305 | 305 |
{ |
306 | 306 |
int ret; |
307 | 307 |
|
308 |
+ if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && |
|
309 |
+ avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) { |
|
310 |
+ av_log(avr, AV_LOG_ERROR, "Unsupported internal format for " |
|
311 |
+ "mixing: %s\n", |
|
312 |
+ av_get_sample_fmt_name(avr->internal_sample_fmt)); |
|
313 |
+ return AVERROR(EINVAL); |
|
314 |
+ } |
|
315 |
+ |
|
308 | 316 |
/* build matrix if the user did not already set one */ |
309 | 317 |
if (!avr->am->matrix) { |
310 | 318 |
int i, j; |
... | ... |
@@ -45,6 +45,13 @@ enum AVMixCoeffType { |
45 | 45 |
AV_MIX_COEFF_TYPE_NB, /** Number of coeff types. Not part of ABI */ |
46 | 46 |
}; |
47 | 47 |
|
48 |
+/** Resampling Filter Types */ |
|
49 |
+enum AVResampleFilterType { |
|
50 |
+ AV_RESAMPLE_FILTER_TYPE_CUBIC, /**< Cubic */ |
|
51 |
+ AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL, /**< Blackman Nuttall Windowed Sinc */ |
|
52 |
+ AV_RESAMPLE_FILTER_TYPE_KAISER, /**< Kaiser Windowed Sinc */ |
|
53 |
+}; |
|
54 |
+ |
|
48 | 55 |
/** |
49 | 56 |
* Return the LIBAVRESAMPLE_VERSION_INT constant. |
50 | 57 |
*/ |
... | ... |
@@ -50,6 +50,8 @@ struct AVAudioResampleContext { |
50 | 50 |
int phase_shift; /**< log2 of the number of entries in the resampling polyphase filterbank */ |
51 | 51 |
int linear_interp; /**< if 1 then the resampling FIR filter will be linearly interpolated */ |
52 | 52 |
double cutoff; /**< resampling cutoff frequency. 1.0 corresponds to half the output sample rate */ |
53 |
+ enum AVResampleFilterType filter_type; /**< resampling filter type */ |
|
54 |
+ int kaiser_beta; /**< beta value for Kaiser window (only applicable if filter_type == AV_FILTER_TYPE_KAISER) */ |
|
53 | 55 |
|
54 | 56 |
int in_channels; /**< number of input channels */ |
55 | 57 |
int out_channels; /**< number of output channels */ |
... | ... |
@@ -39,7 +39,7 @@ static const AVOption options[] = { |
39 | 39 |
{ "out_channel_layout", "Output Channel Layout", OFFSET(out_channel_layout), AV_OPT_TYPE_INT64, { 0 }, INT64_MIN, INT64_MAX, PARAM }, |
40 | 40 |
{ "out_sample_fmt", "Output Sample Format", OFFSET(out_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM }, |
41 | 41 |
{ "out_sample_rate", "Output Sample Rate", OFFSET(out_sample_rate), AV_OPT_TYPE_INT, { 48000 }, 1, INT_MAX, PARAM }, |
42 |
- { "internal_sample_fmt", "Internal Sample Format", OFFSET(internal_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_FLTP }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, PARAM }, |
|
42 |
+ { "internal_sample_fmt", "Internal Sample Format", OFFSET(internal_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, PARAM }, |
|
43 | 43 |
{ "mix_coeff_type", "Mixing Coefficient Type", OFFSET(mix_coeff_type), AV_OPT_TYPE_INT, { AV_MIX_COEFF_TYPE_FLT }, AV_MIX_COEFF_TYPE_Q8, AV_MIX_COEFF_TYPE_NB-1, PARAM, "mix_coeff_type" }, |
44 | 44 |
{ "q8", "16-bit 8.8 Fixed-Point", 0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_Q8 }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" }, |
45 | 45 |
{ "q15", "32-bit 17.15 Fixed-Point", 0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_Q15 }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" }, |
... | ... |
@@ -56,6 +56,11 @@ static const AVOption options[] = { |
56 | 56 |
{ "none", "None", 0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_NONE }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, |
57 | 57 |
{ "dolby", "Dolby", 0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_DOLBY }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, |
58 | 58 |
{ "dplii", "Dolby Pro Logic II", 0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_DPLII }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, |
59 |
+ { "filter_type", "Filter Type", OFFSET(filter_type), AV_OPT_TYPE_INT, { AV_RESAMPLE_FILTER_TYPE_KAISER }, AV_RESAMPLE_FILTER_TYPE_CUBIC, AV_RESAMPLE_FILTER_TYPE_KAISER, PARAM, "filter_type" }, |
|
60 |
+ { "cubic", "Cubic", 0, AV_OPT_TYPE_CONST, { AV_RESAMPLE_FILTER_TYPE_CUBIC }, INT_MIN, INT_MAX, PARAM, "filter_type" }, |
|
61 |
+ { "blackman_nuttall", "Blackman Nuttall Windowed Sinc", 0, AV_OPT_TYPE_CONST, { AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL }, INT_MIN, INT_MAX, PARAM, "filter_type" }, |
|
62 |
+ { "kaiser", "Kaiser Windowed Sinc", 0, AV_OPT_TYPE_CONST, { AV_RESAMPLE_FILTER_TYPE_KAISER }, INT_MIN, INT_MAX, PARAM, "filter_type" }, |
|
63 |
+ { "kaiser_beta", "Kaiser Window Beta", OFFSET(kaiser_beta), AV_OPT_TYPE_INT, { 9 }, 2, 16, PARAM }, |
|
59 | 64 |
{ NULL }, |
60 | 65 |
}; |
61 | 66 |
|
... | ... |
@@ -24,37 +24,10 @@ |
24 | 24 |
#include "internal.h" |
25 | 25 |
#include "audio_data.h" |
26 | 26 |
|
27 |
-#ifdef CONFIG_RESAMPLE_FLT |
|
28 |
-/* float template */ |
|
29 |
-#define FILTER_SHIFT 0 |
|
30 |
-#define FELEM float |
|
31 |
-#define FELEM2 float |
|
32 |
-#define FELEML float |
|
33 |
-#define WINDOW_TYPE 24 |
|
34 |
-#elifdef CONFIG_RESAMPLE_S32 |
|
35 |
-/* s32 template */ |
|
36 |
-#define FILTER_SHIFT 30 |
|
37 |
-#define FELEM int32_t |
|
38 |
-#define FELEM2 int64_t |
|
39 |
-#define FELEML int64_t |
|
40 |
-#define FELEM_MAX INT32_MAX |
|
41 |
-#define FELEM_MIN INT32_MIN |
|
42 |
-#define WINDOW_TYPE 12 |
|
43 |
-#else |
|
44 |
-/* s16 template */ |
|
45 |
-#define FILTER_SHIFT 15 |
|
46 |
-#define FELEM int16_t |
|
47 |
-#define FELEM2 int32_t |
|
48 |
-#define FELEML int64_t |
|
49 |
-#define FELEM_MAX INT16_MAX |
|
50 |
-#define FELEM_MIN INT16_MIN |
|
51 |
-#define WINDOW_TYPE 9 |
|
52 |
-#endif |
|
53 |
- |
|
54 | 27 |
struct ResampleContext { |
55 | 28 |
AVAudioResampleContext *avr; |
56 | 29 |
AudioData *buffer; |
57 |
- FELEM *filter_bank; |
|
30 |
+ uint8_t *filter_bank; |
|
58 | 31 |
int filter_length; |
59 | 32 |
int ideal_dst_incr; |
60 | 33 |
int dst_incr; |
... | ... |
@@ -65,9 +38,35 @@ struct ResampleContext { |
65 | 65 |
int phase_shift; |
66 | 66 |
int phase_mask; |
67 | 67 |
int linear; |
68 |
+ enum AVResampleFilterType filter_type; |
|
69 |
+ int kaiser_beta; |
|
68 | 70 |
double factor; |
71 |
+ void (*set_filter)(void *filter, double *tab, int phase, int tap_count); |
|
72 |
+ void (*resample_one)(struct ResampleContext *c, int no_filter, void *dst0, |
|
73 |
+ int dst_index, const void *src0, int src_size, |
|
74 |
+ int index, int frac); |
|
69 | 75 |
}; |
70 | 76 |
|
77 |
+ |
|
78 |
+/* double template */ |
|
79 |
+#define CONFIG_RESAMPLE_DBL |
|
80 |
+#include "resample_template.c" |
|
81 |
+#undef CONFIG_RESAMPLE_DBL |
|
82 |
+ |
|
83 |
+/* float template */ |
|
84 |
+#define CONFIG_RESAMPLE_FLT |
|
85 |
+#include "resample_template.c" |
|
86 |
+#undef CONFIG_RESAMPLE_FLT |
|
87 |
+ |
|
88 |
+/* s32 template */ |
|
89 |
+#define CONFIG_RESAMPLE_S32 |
|
90 |
+#include "resample_template.c" |
|
91 |
+#undef CONFIG_RESAMPLE_S32 |
|
92 |
+ |
|
93 |
+/* s16 template */ |
|
94 |
+#include "resample_template.c" |
|
95 |
+ |
|
96 |
+ |
|
71 | 97 |
/** |
72 | 98 |
* 0th order modified bessel function of the first kind. |
73 | 99 |
*/ |
... | ... |
@@ -95,17 +94,17 @@ static double bessel(double x) |
95 | 95 |
* @param tap_count tap count |
96 | 96 |
* @param phase_count phase count |
97 | 97 |
* @param scale wanted sum of coefficients for each filter |
98 |
- * @param type 0->cubic |
|
99 |
- * 1->blackman nuttall windowed sinc |
|
100 |
- * 2..16->kaiser windowed sinc beta=2..16 |
|
98 |
+ * @param filter_type filter type |
|
99 |
+ * @param kaiser_beta kaiser window beta |
|
101 | 100 |
* @return 0 on success, negative AVERROR code on failure |
102 | 101 |
*/ |
103 |
-static int build_filter(FELEM *filter, double factor, int tap_count, |
|
104 |
- int phase_count, int scale, int type) |
|
102 |
+static int build_filter(ResampleContext *c) |
|
105 | 103 |
{ |
106 | 104 |
int ph, i; |
107 |
- double x, y, w; |
|
105 |
+ double x, y, w, factor; |
|
108 | 106 |
double *tab; |
107 |
+ int tap_count = c->filter_length; |
|
108 |
+ int phase_count = 1 << c->phase_shift; |
|
109 | 109 |
const int center = (tap_count - 1) / 2; |
110 | 110 |
|
111 | 111 |
tab = av_malloc(tap_count * sizeof(*tab)); |
... | ... |
@@ -113,8 +112,7 @@ static int build_filter(FELEM *filter, double factor, int tap_count, |
113 | 113 |
return AVERROR(ENOMEM); |
114 | 114 |
|
115 | 115 |
/* if upsampling, only need to interpolate, no filter */ |
116 |
- if (factor > 1.0) |
|
117 |
- factor = 1.0; |
|
116 |
+ factor = FFMIN(c->factor, 1.0); |
|
118 | 117 |
|
119 | 118 |
for (ph = 0; ph < phase_count; ph++) { |
120 | 119 |
double norm = 0; |
... | ... |
@@ -122,39 +120,34 @@ static int build_filter(FELEM *filter, double factor, int tap_count, |
122 | 122 |
x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor; |
123 | 123 |
if (x == 0) y = 1.0; |
124 | 124 |
else y = sin(x) / x; |
125 |
- switch (type) { |
|
126 |
- case 0: { |
|
125 |
+ switch (c->filter_type) { |
|
126 |
+ case AV_RESAMPLE_FILTER_TYPE_CUBIC: { |
|
127 | 127 |
const float d = -0.5; //first order derivative = -0.5 |
128 | 128 |
x = fabs(((double)(i - center) - (double)ph / phase_count) * factor); |
129 | 129 |
if (x < 1.0) y = 1 - 3 * x*x + 2 * x*x*x + d * ( -x*x + x*x*x); |
130 | 130 |
else y = d * (-4 + 8 * x - 5 * x*x + x*x*x); |
131 | 131 |
break; |
132 | 132 |
} |
133 |
- case 1: |
|
133 |
+ case AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL: |
|
134 | 134 |
w = 2.0 * x / (factor * tap_count) + M_PI; |
135 | 135 |
y *= 0.3635819 - 0.4891775 * cos( w) + |
136 | 136 |
0.1365995 * cos(2 * w) - |
137 | 137 |
0.0106411 * cos(3 * w); |
138 | 138 |
break; |
139 |
- default: |
|
139 |
+ case AV_RESAMPLE_FILTER_TYPE_KAISER: |
|
140 | 140 |
w = 2.0 * x / (factor * tap_count * M_PI); |
141 |
- y *= bessel(type * sqrt(FFMAX(1 - w * w, 0))); |
|
141 |
+ y *= bessel(c->kaiser_beta * sqrt(FFMAX(1 - w * w, 0))); |
|
142 | 142 |
break; |
143 | 143 |
} |
144 | 144 |
|
145 | 145 |
tab[i] = y; |
146 | 146 |
norm += y; |
147 | 147 |
} |
148 |
- |
|
149 | 148 |
/* normalize so that an uniform color remains the same */ |
150 |
- for (i = 0; i < tap_count; i++) { |
|
151 |
-#ifdef CONFIG_RESAMPLE_FLT |
|
152 |
- filter[ph * tap_count + i] = tab[i] / norm; |
|
153 |
-#else |
|
154 |
- filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm), |
|
155 |
- FELEM_MIN, FELEM_MAX); |
|
156 |
-#endif |
|
157 |
- } |
|
149 |
+ for (i = 0; i < tap_count; i++) |
|
150 |
+ tab[i] = tab[i] / norm; |
|
151 |
+ |
|
152 |
+ c->set_filter(c->filter_bank, tab, ph, tap_count); |
|
158 | 153 |
} |
159 | 154 |
|
160 | 155 |
av_free(tab); |
... | ... |
@@ -168,9 +161,12 @@ ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr) |
168 | 168 |
int in_rate = avr->in_sample_rate; |
169 | 169 |
double factor = FFMIN(out_rate * avr->cutoff / in_rate, 1.0); |
170 | 170 |
int phase_count = 1 << avr->phase_shift; |
171 |
+ int felem_size; |
|
171 | 172 |
|
172 |
- /* TODO: add support for s32 and float internal formats */ |
|
173 |
- if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) { |
|
173 |
+ if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && |
|
174 |
+ avr->internal_sample_fmt != AV_SAMPLE_FMT_S32P && |
|
175 |
+ avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP && |
|
176 |
+ avr->internal_sample_fmt != AV_SAMPLE_FMT_DBLP) { |
|
174 | 177 |
av_log(avr, AV_LOG_ERROR, "Unsupported internal format for " |
175 | 178 |
"resampling: %s\n", |
176 | 179 |
av_get_sample_fmt_name(avr->internal_sample_fmt)); |
... | ... |
@@ -186,18 +182,40 @@ ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr) |
186 | 186 |
c->linear = avr->linear_interp; |
187 | 187 |
c->factor = factor; |
188 | 188 |
c->filter_length = FFMAX((int)ceil(avr->filter_size / factor), 1); |
189 |
+ c->filter_type = avr->filter_type; |
|
190 |
+ c->kaiser_beta = avr->kaiser_beta; |
|
191 |
+ |
|
192 |
+ switch (avr->internal_sample_fmt) { |
|
193 |
+ case AV_SAMPLE_FMT_DBLP: |
|
194 |
+ c->resample_one = resample_one_dbl; |
|
195 |
+ c->set_filter = set_filter_dbl; |
|
196 |
+ break; |
|
197 |
+ case AV_SAMPLE_FMT_FLTP: |
|
198 |
+ c->resample_one = resample_one_flt; |
|
199 |
+ c->set_filter = set_filter_flt; |
|
200 |
+ break; |
|
201 |
+ case AV_SAMPLE_FMT_S32P: |
|
202 |
+ c->resample_one = resample_one_s32; |
|
203 |
+ c->set_filter = set_filter_s32; |
|
204 |
+ break; |
|
205 |
+ case AV_SAMPLE_FMT_S16P: |
|
206 |
+ c->resample_one = resample_one_s16; |
|
207 |
+ c->set_filter = set_filter_s16; |
|
208 |
+ break; |
|
209 |
+ } |
|
189 | 210 |
|
190 |
- c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * sizeof(FELEM)); |
|
211 |
+ felem_size = av_get_bytes_per_sample(avr->internal_sample_fmt); |
|
212 |
+ c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * felem_size); |
|
191 | 213 |
if (!c->filter_bank) |
192 | 214 |
goto error; |
193 | 215 |
|
194 |
- if (build_filter(c->filter_bank, factor, c->filter_length, phase_count, |
|
195 |
- 1 << FILTER_SHIFT, WINDOW_TYPE) < 0) |
|
216 |
+ if (build_filter(c) < 0) |
|
196 | 217 |
goto error; |
197 | 218 |
|
198 |
- memcpy(&c->filter_bank[c->filter_length * phase_count + 1], |
|
199 |
- c->filter_bank, (c->filter_length - 1) * sizeof(FELEM)); |
|
200 |
- c->filter_bank[c->filter_length * phase_count] = c->filter_bank[c->filter_length - 1]; |
|
219 |
+ memcpy(&c->filter_bank[(c->filter_length * phase_count + 1) * felem_size], |
|
220 |
+ c->filter_bank, (c->filter_length - 1) * felem_size); |
|
221 |
+ memcpy(&c->filter_bank[c->filter_length * phase_count * felem_size], |
|
222 |
+ &c->filter_bank[(c->filter_length - 1) * felem_size], felem_size); |
|
201 | 223 |
|
202 | 224 |
c->compensation_distance = 0; |
203 | 225 |
if (!av_reduce(&c->src_incr, &c->dst_incr, out_rate, |
... | ... |
@@ -311,10 +329,10 @@ reinit_fail: |
311 | 311 |
return ret; |
312 | 312 |
} |
313 | 313 |
|
314 |
-static int resample(ResampleContext *c, int16_t *dst, const int16_t *src, |
|
314 |
+static int resample(ResampleContext *c, void *dst, const void *src, |
|
315 | 315 |
int *consumed, int src_size, int dst_size, int update_ctx) |
316 | 316 |
{ |
317 |
- int dst_index, i; |
|
317 |
+ int dst_index; |
|
318 | 318 |
int index = c->index; |
319 | 319 |
int frac = c->frac; |
320 | 320 |
int dst_incr_frac = c->dst_incr % c->src_incr; |
... | ... |
@@ -334,7 +352,7 @@ static int resample(ResampleContext *c, int16_t *dst, const int16_t *src, |
334 | 334 |
|
335 | 335 |
if (dst) { |
336 | 336 |
for(dst_index = 0; dst_index < dst_size; dst_index++) { |
337 |
- dst[dst_index] = src[index2 >> 32]; |
|
337 |
+ c->resample_one(c, 1, dst, dst_index, src, 0, index2 >> 32, 0); |
|
338 | 338 |
index2 += incr; |
339 | 339 |
} |
340 | 340 |
} else { |
... | ... |
@@ -345,42 +363,14 @@ static int resample(ResampleContext *c, int16_t *dst, const int16_t *src, |
345 | 345 |
frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr; |
346 | 346 |
} else { |
347 | 347 |
for (dst_index = 0; dst_index < dst_size; dst_index++) { |
348 |
- FELEM *filter = c->filter_bank + |
|
349 |
- c->filter_length * (index & c->phase_mask); |
|
350 | 348 |
int sample_index = index >> c->phase_shift; |
351 | 349 |
|
352 |
- if (!dst && (sample_index + c->filter_length > src_size || |
|
353 |
- -sample_index >= src_size)) |
|
350 |
+ if (sample_index + c->filter_length > src_size || |
|
351 |
+ -sample_index >= src_size) |
|
354 | 352 |
break; |
355 | 353 |
|
356 |
- if (dst) { |
|
357 |
- FELEM2 val = 0; |
|
358 |
- |
|
359 |
- if (sample_index < 0) { |
|
360 |
- for (i = 0; i < c->filter_length; i++) |
|
361 |
- val += src[FFABS(sample_index + i) % src_size] * |
|
362 |
- (FELEM2)filter[i]; |
|
363 |
- } else if (sample_index + c->filter_length > src_size) { |
|
364 |
- break; |
|
365 |
- } else if (c->linear) { |
|
366 |
- FELEM2 v2 = 0; |
|
367 |
- for (i = 0; i < c->filter_length; i++) { |
|
368 |
- val += src[abs(sample_index + i)] * (FELEM2)filter[i]; |
|
369 |
- v2 += src[abs(sample_index + i)] * (FELEM2)filter[i + c->filter_length]; |
|
370 |
- } |
|
371 |
- val += (v2 - val) * (FELEML)frac / c->src_incr; |
|
372 |
- } else { |
|
373 |
- for (i = 0; i < c->filter_length; i++) |
|
374 |
- val += src[sample_index + i] * (FELEM2)filter[i]; |
|
375 |
- } |
|
376 |
- |
|
377 |
-#ifdef CONFIG_RESAMPLE_FLT |
|
378 |
- dst[dst_index] = av_clip_int16(lrintf(val)); |
|
379 |
-#else |
|
380 |
- val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; |
|
381 |
- dst[dst_index] = av_clip_int16(val); |
|
382 |
-#endif |
|
383 |
- } |
|
354 |
+ if (dst) |
|
355 |
+ c->resample_one(c, 0, dst, dst_index, src, src_size, index, frac); |
|
384 | 356 |
|
385 | 357 |
frac += dst_incr_frac; |
386 | 358 |
index += dst_incr; |
... | ... |
@@ -451,8 +441,8 @@ int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src, |
451 | 451 |
|
452 | 452 |
/* resample each channel plane */ |
453 | 453 |
for (ch = 0; ch < c->buffer->channels; ch++) { |
454 |
- out_samples = resample(c, (int16_t *)dst->data[ch], |
|
455 |
- (const int16_t *)c->buffer->data[ch], consumed, |
|
454 |
+ out_samples = resample(c, (void *)dst->data[ch], |
|
455 |
+ (const void *)c->buffer->data[ch], consumed, |
|
456 | 456 |
c->buffer->nb_samples, dst->allocated_samples, |
457 | 457 |
ch + 1 == c->buffer->channels); |
458 | 458 |
} |
459 | 459 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,102 @@ |
0 |
+/* |
|
1 |
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at> |
|
2 |
+ * |
|
3 |
+ * This file is part of FFmpeg. |
|
4 |
+ * |
|
5 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+#if defined(CONFIG_RESAMPLE_DBL) |
|
21 |
+#define SET_TYPE(func) func ## _dbl |
|
22 |
+#define FELEM double |
|
23 |
+#define FELEM2 double |
|
24 |
+#define FELEML double |
|
25 |
+#define OUT(d, v) d = v |
|
26 |
+#define DBL_TO_FELEM(d, v) d = v |
|
27 |
+#elif defined(CONFIG_RESAMPLE_FLT) |
|
28 |
+#define SET_TYPE(func) func ## _flt |
|
29 |
+#define FELEM float |
|
30 |
+#define FELEM2 float |
|
31 |
+#define FELEML float |
|
32 |
+#define OUT(d, v) d = v |
|
33 |
+#define DBL_TO_FELEM(d, v) d = v |
|
34 |
+#elif defined(CONFIG_RESAMPLE_S32) |
|
35 |
+#define SET_TYPE(func) func ## _s32 |
|
36 |
+#define FELEM int32_t |
|
37 |
+#define FELEM2 int64_t |
|
38 |
+#define FELEML int64_t |
|
39 |
+#define OUT(d, v) d = av_clipl_int32((v + (1 << 29)) >> 30) |
|
40 |
+#define DBL_TO_FELEM(d, v) d = av_clipl_int32(llrint(v * (1 << 30))); |
|
41 |
+#else |
|
42 |
+#define SET_TYPE(func) func ## _s16 |
|
43 |
+#define FELEM int16_t |
|
44 |
+#define FELEM2 int32_t |
|
45 |
+#define FELEML int64_t |
|
46 |
+#define OUT(d, v) d = av_clip_int16((v + (1 << 14)) >> 15) |
|
47 |
+#define DBL_TO_FELEM(d, v) d = av_clip_int16(lrint(v * (1 << 15))) |
|
48 |
+#endif |
|
49 |
+ |
|
50 |
+static void SET_TYPE(resample_one)(ResampleContext *c, int no_filter, |
|
51 |
+ void *dst0, int dst_index, const void *src0, |
|
52 |
+ int src_size, int index, int frac) |
|
53 |
+{ |
|
54 |
+ FELEM *dst = dst0; |
|
55 |
+ const FELEM *src = src0; |
|
56 |
+ |
|
57 |
+ if (no_filter) { |
|
58 |
+ dst[dst_index] = src[index]; |
|
59 |
+ } else { |
|
60 |
+ int i; |
|
61 |
+ int sample_index = index >> c->phase_shift; |
|
62 |
+ FELEM2 val = 0; |
|
63 |
+ FELEM *filter = ((FELEM *)c->filter_bank) + |
|
64 |
+ c->filter_length * (index & c->phase_mask); |
|
65 |
+ |
|
66 |
+ if (sample_index < 0) { |
|
67 |
+ for (i = 0; i < c->filter_length; i++) |
|
68 |
+ val += src[FFABS(sample_index + i) % src_size] * |
|
69 |
+ (FELEM2)filter[i]; |
|
70 |
+ } else if (c->linear) { |
|
71 |
+ FELEM2 v2 = 0; |
|
72 |
+ for (i = 0; i < c->filter_length; i++) { |
|
73 |
+ val += src[abs(sample_index + i)] * (FELEM2)filter[i]; |
|
74 |
+ v2 += src[abs(sample_index + i)] * (FELEM2)filter[i + c->filter_length]; |
|
75 |
+ } |
|
76 |
+ val += (v2 - val) * (FELEML)frac / c->src_incr; |
|
77 |
+ } else { |
|
78 |
+ for (i = 0; i < c->filter_length; i++) |
|
79 |
+ val += src[sample_index + i] * (FELEM2)filter[i]; |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ OUT(dst[dst_index], val); |
|
83 |
+ } |
|
84 |
+} |
|
85 |
+ |
|
86 |
+static void SET_TYPE(set_filter)(void *filter0, double *tab, int phase, |
|
87 |
+ int tap_count) |
|
88 |
+{ |
|
89 |
+ int i; |
|
90 |
+ FELEM *filter = ((FELEM *)filter0) + phase * tap_count; |
|
91 |
+ for (i = 0; i < tap_count; i++) { |
|
92 |
+ DBL_TO_FELEM(filter[i], tab[i]); |
|
93 |
+ } |
|
94 |
+} |
|
95 |
+ |
|
96 |
+#undef SET_TYPE |
|
97 |
+#undef FELEM |
|
98 |
+#undef FELEM2 |
|
99 |
+#undef FELEML |
|
100 |
+#undef OUT |
|
101 |
+#undef DBL_TO_FELEM |
... | ... |
@@ -57,18 +57,43 @@ int avresample_open(AVAudioResampleContext *avr) |
57 | 57 |
avr->resample_needed = avr->in_sample_rate != avr->out_sample_rate || |
58 | 58 |
avr->force_resampling; |
59 | 59 |
|
60 |
- /* set sample format conversion parameters */ |
|
61 |
- /* override user-requested internal format to avoid unexpected failures |
|
62 |
- TODO: support more internal formats */ |
|
63 |
- if (avr->resample_needed && avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) { |
|
64 |
- av_log(avr, AV_LOG_WARNING, "Using s16p as internal sample format\n"); |
|
65 |
- avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P; |
|
66 |
- } else if (avr->mixing_needed && |
|
67 |
- avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && |
|
68 |
- avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) { |
|
69 |
- av_log(avr, AV_LOG_WARNING, "Using fltp as internal sample format\n"); |
|
70 |
- avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; |
|
60 |
+ /* select internal sample format if not specified by the user */ |
|
61 |
+ if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE && |
|
62 |
+ (avr->mixing_needed || avr->resample_needed)) { |
|
63 |
+ enum AVSampleFormat in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); |
|
64 |
+ enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); |
|
65 |
+ int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt), |
|
66 |
+ av_get_bytes_per_sample(out_fmt)); |
|
67 |
+ if (max_bps <= 2) { |
|
68 |
+ avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P; |
|
69 |
+ } else if (avr->mixing_needed) { |
|
70 |
+ avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; |
|
71 |
+ } else { |
|
72 |
+ if (max_bps <= 4) { |
|
73 |
+ if (in_fmt == AV_SAMPLE_FMT_S32P || |
|
74 |
+ out_fmt == AV_SAMPLE_FMT_S32P) { |
|
75 |
+ if (in_fmt == AV_SAMPLE_FMT_FLTP || |
|
76 |
+ out_fmt == AV_SAMPLE_FMT_FLTP) { |
|
77 |
+ /* if one is s32 and the other is flt, use dbl */ |
|
78 |
+ avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; |
|
79 |
+ } else { |
|
80 |
+ /* if one is s32 and the other is s32, s16, or u8, use s32 */ |
|
81 |
+ avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P; |
|
82 |
+ } |
|
83 |
+ } else { |
|
84 |
+ /* if one is flt and the other is flt, s16 or u8, use flt */ |
|
85 |
+ avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; |
|
86 |
+ } |
|
87 |
+ } else { |
|
88 |
+ /* if either is dbl, use dbl */ |
|
89 |
+ avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; |
|
90 |
+ } |
|
91 |
+ } |
|
92 |
+ av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n", |
|
93 |
+ av_get_sample_fmt_name(avr->internal_sample_fmt)); |
|
71 | 94 |
} |
95 |
+ |
|
96 |
+ /* set sample format conversion parameters */ |
|
72 | 97 |
if (avr->in_channels == 1) |
73 | 98 |
avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); |
74 | 99 |
if (avr->out_channels == 1) |
... | ... |
@@ -75,7 +75,13 @@ probefmt(){ |
75 | 75 |
} |
76 | 76 |
|
77 | 77 |
ffmpeg(){ |
78 |
- run ffmpeg -nostats -threads $threads -thread_type $thread_type -cpuflags $cpuflags "$@" |
|
78 |
+ dec_opts="-threads $threads -thread_type $thread_type" |
|
79 |
+ ffmpeg_args="-nostats -cpuflags $cpuflags" |
|
80 |
+ for arg in $@; do |
|
81 |
+ [ ${arg} = -i ] && ffmpeg_args="${ffmpeg_args} ${dec_opts}" |
|
82 |
+ ffmpeg_args="${ffmpeg_args} ${arg}" |
|
83 |
+ done |
|
84 |
+ run ffmpeg ${ffmpeg_args} |
|
79 | 85 |
} |
80 | 86 |
|
81 | 87 |
framecrc(){ |