You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	Merge remote-tracking branch 'qatar/master'
* 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>
This commit is contained in:
		| @@ -327,7 +327,7 @@ OBJS-$(CONFIG_MSMPEG4V3_ENCODER)       += msmpeg4.o msmpeg4enc.o msmpeg4data.o \ | ||||
|                                           h263dec.o h263.o ituh263dec.o        \ | ||||
|                                           mpeg4videodec.o | ||||
| OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o msrledec.o | ||||
| OBJS-$(CONFIG_MSA1_DECODER)            += mss3.o | ||||
| OBJS-$(CONFIG_MSA1_DECODER)            += mss3.o mss34dsp.o | ||||
| OBJS-$(CONFIG_MSS1_DECODER)            += mss1.o | ||||
| OBJS-$(CONFIG_MSVIDEO1_DECODER)        += msvideo1.o | ||||
| OBJS-$(CONFIG_MSVIDEO1_ENCODER)        += msvideo1enc.o elbg.o | ||||
|   | ||||
| @@ -175,8 +175,8 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, | ||||
|             x4->params.b_tff = frame->top_field_first; | ||||
|             x264_encoder_reconfig(x4->enc, &x4->params); | ||||
|         } | ||||
|         if (x4->params.vui.i_sar_height != ctx->sample_aspect_ratio.den | ||||
|          || x4->params.vui.i_sar_width != ctx->sample_aspect_ratio.num) { | ||||
|         if (x4->params.vui.i_sar_height != ctx->sample_aspect_ratio.den || | ||||
|             x4->params.vui.i_sar_width  != ctx->sample_aspect_ratio.num) { | ||||
|             x4->params.vui.i_sar_height = ctx->sample_aspect_ratio.den; | ||||
|             x4->params.vui.i_sar_width  = ctx->sample_aspect_ratio.num; | ||||
|             x264_encoder_reconfig(x4->enc, &x4->params); | ||||
|   | ||||
| @@ -119,16 +119,10 @@ int main(int argc, char **argv) | ||||
|     int flags[2] = { AV_CPU_FLAG_MMX, AV_CPU_FLAG_MMX2 }; | ||||
|     int flags_size = HAVE_MMX2 ? 2 : 1; | ||||
|  | ||||
|     for(;;) { | ||||
|         c = getopt(argc, argv, "h"); | ||||
|         if (c == -1) | ||||
|             break; | ||||
|         switch(c) { | ||||
|         case 'h': | ||||
|     if (argc > 1) { | ||||
|         help(); | ||||
|         return 1; | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     printf("ffmpeg motion test\n"); | ||||
|  | ||||
|   | ||||
| @@ -26,6 +26,8 @@ | ||||
|  | ||||
| #include "avcodec.h" | ||||
| #include "bytestream.h" | ||||
| #include "dsputil.h" | ||||
| #include "mss34dsp.h" | ||||
|  | ||||
| #define HEADER_SIZE 27 | ||||
|  | ||||
| @@ -119,39 +121,6 @@ typedef struct MSS3Context { | ||||
|     int              hblock[16 * 16]; | ||||
| } MSS3Context; | ||||
|  | ||||
| static const uint8_t mss3_luma_quant[64] = { | ||||
|     16,  11,  10,  16,  24,  40,  51,  61, | ||||
|     12,  12,  14,  19,  26,  58,  60,  55, | ||||
|     14,  13,  16,  24,  40,  57,  69,  56, | ||||
|     14,  17,  22,  29,  51,  87,  80,  62, | ||||
|     18,  22,  37,  56,  68, 109, 103,  77, | ||||
|     24,  35,  55,  64,  81, 104, 113,  92, | ||||
|     49,  64,  78,  87, 103, 121, 120, 101, | ||||
|     72,  92,  95,  98, 112, 100, 103,  99 | ||||
| }; | ||||
|  | ||||
| static const uint8_t mss3_chroma_quant[64] = { | ||||
|     17, 18, 24, 47, 99, 99, 99, 99, | ||||
|     18, 21, 26, 66, 99, 99, 99, 99, | ||||
|     24, 26, 56, 99, 99, 99, 99, 99, | ||||
|     47, 66, 99, 99, 99, 99, 99, 99, | ||||
|     99, 99, 99, 99, 99, 99, 99, 99, | ||||
|     99, 99, 99, 99, 99, 99, 99, 99, | ||||
|     99, 99, 99, 99, 99, 99, 99, 99, | ||||
|     99, 99, 99, 99, 99, 99, 99, 99 | ||||
| }; | ||||
|  | ||||
| static const uint8_t zigzag_scan[64] = { | ||||
|     0,   1,  8, 16,  9,  2,  3, 10, | ||||
|     17, 24, 32, 25, 18, 11,  4,  5, | ||||
|     12, 19, 26, 33, 40, 48, 41, 34, | ||||
|     27, 20, 13,  6,  7, 14, 21, 28, | ||||
|     35, 42, 49, 56, 57, 50, 43, 36, | ||||
|     29, 22, 15, 23, 30, 37, 44, 51, | ||||
|     58, 59, 52, 45, 38, 31, 39, 46, | ||||
|     53, 60, 61, 54, 47, 55, 62, 63 | ||||
| }; | ||||
|  | ||||
|  | ||||
| static void model2_reset(Model2 *m) | ||||
| { | ||||
| @@ -578,7 +547,7 @@ static int decode_dct(RangeCoder *c, DCTBlockCoder *bc, int *block, | ||||
|         if (!sign) | ||||
|             val = -val; | ||||
|  | ||||
|         zz_pos = zigzag_scan[pos]; | ||||
|         zz_pos = ff_zigzag_direct[pos]; | ||||
|         block[zz_pos] = val * bc->qmat[zz_pos]; | ||||
|         pos++; | ||||
|     } | ||||
| @@ -586,58 +555,6 @@ static int decode_dct(RangeCoder *c, DCTBlockCoder *bc, int *block, | ||||
|     return pos == 64 ? 0 : -1; | ||||
| } | ||||
|  | ||||
| #define DCT_TEMPLATE(blk, step, SOP, shift)                         \ | ||||
|     const int t0 = -39409 * blk[7 * step] -  58980 * blk[1 * step]; \ | ||||
|     const int t1 =  39410 * blk[1 * step] -  58980 * blk[7 * step]; \ | ||||
|     const int t2 = -33410 * blk[5 * step] - 167963 * blk[3 * step]; \ | ||||
|     const int t3 =  33410 * blk[3 * step] - 167963 * blk[5 * step]; \ | ||||
|     const int t4 =          blk[3 * step] +          blk[7 * step]; \ | ||||
|     const int t5 =          blk[1 * step] +          blk[5 * step]; \ | ||||
|     const int t6 =  77062 * t4            +  51491 * t5;            \ | ||||
|     const int t7 =  77062 * t5            -  51491 * t4;            \ | ||||
|     const int t8 =  35470 * blk[2 * step] -  85623 * blk[6 * step]; \ | ||||
|     const int t9 =  35470 * blk[6 * step] +  85623 * blk[2 * step]; \ | ||||
|     const int tA = SOP(blk[0 * step] - blk[4 * step]);              \ | ||||
|     const int tB = SOP(blk[0 * step] + blk[4 * step]);              \ | ||||
|                                                                     \ | ||||
|     blk[0 * step] = (  t1 + t6  + t9 + tB) >> shift;                \ | ||||
|     blk[1 * step] = (  t3 + t7  + t8 + tA) >> shift;                \ | ||||
|     blk[2 * step] = (  t2 + t6  - t8 + tA) >> shift;                \ | ||||
|     blk[3 * step] = (  t0 + t7  - t9 + tB) >> shift;                \ | ||||
|     blk[4 * step] = (-(t0 + t7) - t9 + tB) >> shift;                \ | ||||
|     blk[5 * step] = (-(t2 + t6) - t8 + tA) >> shift;                \ | ||||
|     blk[6 * step] = (-(t3 + t7) + t8 + tA) >> shift;                \ | ||||
|     blk[7 * step] = (-(t1 + t6) + t9 + tB) >> shift;                \ | ||||
|  | ||||
| #define SOP_ROW(a) ((a) << 16) + 0x2000 | ||||
| #define SOP_COL(a) ((a + 32) << 16) | ||||
|  | ||||
| static void dct_put(uint8_t *dst, int stride, int *block) | ||||
| { | ||||
|     int i, j; | ||||
|     int *ptr; | ||||
|  | ||||
|     ptr = block; | ||||
|     for (i = 0; i < 8; i++) { | ||||
|         DCT_TEMPLATE(ptr, 1, SOP_ROW, 13); | ||||
|         ptr += 8; | ||||
|     } | ||||
|  | ||||
|     ptr = block; | ||||
|     for (i = 0; i < 8; i++) { | ||||
|         DCT_TEMPLATE(ptr, 8, SOP_COL, 22); | ||||
|         ptr++; | ||||
|     } | ||||
|  | ||||
|     ptr = block; | ||||
|     for (j = 0; j < 8; j++) { | ||||
|         for (i = 0; i < 8; i++) | ||||
|             dst[i] = av_clip_uint8(ptr[i] + 128); | ||||
|         dst += stride; | ||||
|         ptr += 8; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void decode_dct_block(RangeCoder *c, DCTBlockCoder *bc, | ||||
|                              uint8_t *dst, int stride, int block_size, | ||||
|                              int *block, int mb_x, int mb_y) | ||||
| @@ -655,7 +572,7 @@ static void decode_dct_block(RangeCoder *c, DCTBlockCoder *bc, | ||||
|                 c->got_error = 1; | ||||
|                 return; | ||||
|             } | ||||
|             dct_put(dst + i * 8, stride, block); | ||||
|             ff_mss34_dct_put(dst + i * 8, stride, block); | ||||
|         } | ||||
|         dst += 8 * stride; | ||||
|     } | ||||
| @@ -702,14 +619,6 @@ static void decode_haar_block(RangeCoder *c, HaarBlockCoder *hc, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void gen_quant_mat(uint16_t *qmat, const uint8_t *ref, float scale) | ||||
| { | ||||
|     int i; | ||||
|  | ||||
|     for (i = 0; i < 64; i++) | ||||
|         qmat[i] = (uint16_t)(ref[i] * scale + 50.0) / 100; | ||||
| } | ||||
|  | ||||
| static void reset_coders(MSS3Context *ctx, int quality) | ||||
| { | ||||
|     int i, j; | ||||
| @@ -726,15 +635,8 @@ static void reset_coders(MSS3Context *ctx, int quality) | ||||
|         for (j = 0; j < 125; j++) | ||||
|             model_reset(&ctx->image_coder[i].vq_model[j]); | ||||
|         if (ctx->dct_coder[i].quality != quality) { | ||||
|             float scale; | ||||
|             ctx->dct_coder[i].quality = quality; | ||||
|             if (quality > 50) | ||||
|                 scale = 200.0f - 2 * quality; | ||||
|             else | ||||
|                 scale = 5000.0f / quality; | ||||
|             gen_quant_mat(ctx->dct_coder[i].qmat, | ||||
|                           i ? mss3_chroma_quant : mss3_luma_quant, | ||||
|                           scale); | ||||
|             ff_mss34_gen_quant_mat(ctx->dct_coder[i].qmat, quality, !i); | ||||
|         } | ||||
|         memset(ctx->dct_coder[i].prev_dc, 0, | ||||
|                sizeof(*ctx->dct_coder[i].prev_dc) * | ||||
|   | ||||
							
								
								
									
										114
									
								
								libavcodec/mss34dsp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								libavcodec/mss34dsp.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| /* | ||||
|  * Common stuff for some Microsoft Screen codecs | ||||
|  * Copyright (C) 2012 Konstantin Shishkov | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with FFmpeg; if not, write to the Free Software | ||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
|  */ | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include "libavutil/common.h" | ||||
| #include "mss34dsp.h" | ||||
|  | ||||
| static const uint8_t luma_quant[64] = { | ||||
|     16,  11,  10,  16,  24,  40,  51,  61, | ||||
|     12,  12,  14,  19,  26,  58,  60,  55, | ||||
|     14,  13,  16,  24,  40,  57,  69,  56, | ||||
|     14,  17,  22,  29,  51,  87,  80,  62, | ||||
|     18,  22,  37,  56,  68, 109, 103,  77, | ||||
|     24,  35,  55,  64,  81, 104, 113,  92, | ||||
|     49,  64,  78,  87, 103, 121, 120, 101, | ||||
|     72,  92,  95,  98, 112, 100, 103,  99 | ||||
| }; | ||||
|  | ||||
| static const uint8_t chroma_quant[64] = { | ||||
|     17, 18, 24, 47, 99, 99, 99, 99, | ||||
|     18, 21, 26, 66, 99, 99, 99, 99, | ||||
|     24, 26, 56, 99, 99, 99, 99, 99, | ||||
|     47, 66, 99, 99, 99, 99, 99, 99, | ||||
|     99, 99, 99, 99, 99, 99, 99, 99, | ||||
|     99, 99, 99, 99, 99, 99, 99, 99, | ||||
|     99, 99, 99, 99, 99, 99, 99, 99, | ||||
|     99, 99, 99, 99, 99, 99, 99, 99 | ||||
| }; | ||||
|  | ||||
| void ff_mss34_gen_quant_mat(uint16_t *qmat, int quality, int luma) | ||||
| { | ||||
|     int i; | ||||
|     const uint8_t *qsrc = luma ? luma_quant : chroma_quant; | ||||
|  | ||||
|     if (quality >= 50) { | ||||
|         int scale = 200 - 2 * quality; | ||||
|  | ||||
|         for (i = 0; i < 64; i++) | ||||
|             qmat[i] = (qsrc[i] * scale + 50) / 100; | ||||
|     } else { | ||||
|         for (i = 0; i < 64; i++) | ||||
|             qmat[i] = (5000 * qsrc[i] / quality + 50) / 100; | ||||
|     } | ||||
| } | ||||
|  | ||||
| #define DCT_TEMPLATE(blk, step, SOP, shift)                         \ | ||||
|     const int t0 = -39409 * blk[7 * step] -  58980 * blk[1 * step]; \ | ||||
|     const int t1 =  39410 * blk[1 * step] -  58980 * blk[7 * step]; \ | ||||
|     const int t2 = -33410 * blk[5 * step] - 167963 * blk[3 * step]; \ | ||||
|     const int t3 =  33410 * blk[3 * step] - 167963 * blk[5 * step]; \ | ||||
|     const int t4 =          blk[3 * step] +          blk[7 * step]; \ | ||||
|     const int t5 =          blk[1 * step] +          blk[5 * step]; \ | ||||
|     const int t6 =  77062 * t4            +  51491 * t5;            \ | ||||
|     const int t7 =  77062 * t5            -  51491 * t4;            \ | ||||
|     const int t8 =  35470 * blk[2 * step] -  85623 * blk[6 * step]; \ | ||||
|     const int t9 =  35470 * blk[6 * step] +  85623 * blk[2 * step]; \ | ||||
|     const int tA = SOP(blk[0 * step] - blk[4 * step]);              \ | ||||
|     const int tB = SOP(blk[0 * step] + blk[4 * step]);              \ | ||||
|                                                                     \ | ||||
|     blk[0 * step] = (  t1 + t6  + t9 + tB) >> shift;                \ | ||||
|     blk[1 * step] = (  t3 + t7  + t8 + tA) >> shift;                \ | ||||
|     blk[2 * step] = (  t2 + t6  - t8 + tA) >> shift;                \ | ||||
|     blk[3 * step] = (  t0 + t7  - t9 + tB) >> shift;                \ | ||||
|     blk[4 * step] = (-(t0 + t7) - t9 + tB) >> shift;                \ | ||||
|     blk[5 * step] = (-(t2 + t6) - t8 + tA) >> shift;                \ | ||||
|     blk[6 * step] = (-(t3 + t7) + t8 + tA) >> shift;                \ | ||||
|     blk[7 * step] = (-(t1 + t6) + t9 + tB) >> shift;                \ | ||||
|  | ||||
| #define SOP_ROW(a) ((a) << 16) + 0x2000 | ||||
| #define SOP_COL(a) ((a + 32) << 16) | ||||
|  | ||||
| void ff_mss34_dct_put(uint8_t *dst, int stride, int *block) | ||||
| { | ||||
|     int i, j; | ||||
|     int *ptr; | ||||
|  | ||||
|     ptr = block; | ||||
|     for (i = 0; i < 8; i++) { | ||||
|         DCT_TEMPLATE(ptr, 1, SOP_ROW, 13); | ||||
|         ptr += 8; | ||||
|     } | ||||
|  | ||||
|     ptr = block; | ||||
|     for (i = 0; i < 8; i++) { | ||||
|         DCT_TEMPLATE(ptr, 8, SOP_COL, 22); | ||||
|         ptr++; | ||||
|     } | ||||
|  | ||||
|     ptr = block; | ||||
|     for (j = 0; j < 8; j++) { | ||||
|         for (i = 0; i < 8; i++) | ||||
|             dst[i] = av_clip_uint8(ptr[i] + 128); | ||||
|         dst += stride; | ||||
|         ptr += 8; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								libavcodec/mss34dsp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								libavcodec/mss34dsp.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|  * Common stuff for some Microsoft Screen codecs | ||||
|  * Copyright (C) 2012 Konstantin Shishkov | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with FFmpeg; if not, write to the Free Software | ||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
|  */ | ||||
|  | ||||
| #ifndef AVCODEC_MSS34DSP_H | ||||
| #define AVCODEC_MSS34DSP_H | ||||
|  | ||||
| #include <stdint.h> | ||||
|  | ||||
| /** | ||||
|  * Generate quantisation matrix for given quality. | ||||
|  * | ||||
|  * @param qmat    destination matrix | ||||
|  * @param quality quality setting (1-100) | ||||
|  * @param luma    generate quantisation matrix for luma or chroma | ||||
|  */ | ||||
| void ff_mss34_gen_quant_mat(uint16_t *qmat, int quality, int luma); | ||||
|  | ||||
| /** | ||||
|  * Transform and output DCT block. | ||||
|  * | ||||
|  * @param dst     output plane | ||||
|  * @param stride  output plane stride | ||||
|  * @param block   block to transform and output | ||||
|  */ | ||||
| void ff_mss34_dct_put(uint8_t *dst, int stride, int *block); | ||||
|  | ||||
| #endif /* AVCODEC_MSS34DSP_H */ | ||||
| @@ -135,12 +135,13 @@ static int config_output(AVFilterLink *outlink) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) | ||||
| static int  filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) | ||||
| { | ||||
|     AConvertContext *aconvert = inlink->dst->priv; | ||||
|     const int n = insamplesref->audio->nb_samples; | ||||
|     AVFilterLink *const outlink = inlink->dst->outputs[0]; | ||||
|     AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n); | ||||
|     int ret; | ||||
|  | ||||
|     swr_convert(aconvert->swr, outsamplesref->data, n, | ||||
|                         (void *)insamplesref->data, n); | ||||
| @@ -148,8 +149,9 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref | ||||
|     avfilter_copy_buffer_ref_props(outsamplesref, insamplesref); | ||||
|     outsamplesref->audio->channel_layout = outlink->channel_layout; | ||||
|  | ||||
|     ff_filter_samples(outlink, outsamplesref); | ||||
|     ret = ff_filter_samples(outlink, outsamplesref); | ||||
|     avfilter_unref_buffer(insamplesref); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_aconvert = { | ||||
|   | ||||
| @@ -212,7 +212,7 @@ static inline void copy_samples(int nb_inputs, struct amerge_input in[], | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     AMergeContext *am = ctx->priv; | ||||
| @@ -232,7 +232,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|     for (i = 1; i < am->nb_inputs; i++) | ||||
|         nb_samples = FFMIN(nb_samples, am->in[i].nb_samples); | ||||
|     if (!nb_samples) | ||||
|         return; | ||||
|         return 0; | ||||
|  | ||||
|     outbuf = ff_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE, nb_samples); | ||||
|     outs = outbuf->data[0]; | ||||
| @@ -285,7 +285,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     ff_filter_samples(ctx->outputs[0], outbuf); | ||||
|     return ff_filter_samples(ctx->outputs[0], outbuf); | ||||
| } | ||||
|  | ||||
| static av_cold int init(AVFilterContext *ctx, const char *args) | ||||
|   | ||||
| @@ -305,9 +305,7 @@ static int output_frame(AVFilterLink *outlink, int nb_samples) | ||||
|     if (s->next_pts != AV_NOPTS_VALUE) | ||||
|         s->next_pts += nb_samples; | ||||
|  | ||||
|     ff_filter_samples(outlink, out_buf); | ||||
|  | ||||
|     return 0; | ||||
|     return ff_filter_samples(outlink, out_buf); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -448,31 +446,37 @@ static int request_frame(AVFilterLink *outlink) | ||||
|     return output_frame(outlink, available_samples); | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| { | ||||
|     AVFilterContext  *ctx = inlink->dst; | ||||
|     MixContext       *s = ctx->priv; | ||||
|     AVFilterLink *outlink = ctx->outputs[0]; | ||||
|     int i; | ||||
|     int i, ret = 0; | ||||
|  | ||||
|     for (i = 0; i < ctx->nb_inputs; i++) | ||||
|         if (ctx->inputs[i] == inlink) | ||||
|             break; | ||||
|     if (i >= ctx->nb_inputs) { | ||||
|         av_log(ctx, AV_LOG_ERROR, "unknown input link\n"); | ||||
|         return; | ||||
|         ret = AVERROR(EINVAL); | ||||
|         goto fail; | ||||
|     } | ||||
|  | ||||
|     if (i == 0) { | ||||
|         int64_t pts = av_rescale_q(buf->pts, inlink->time_base, | ||||
|                                    outlink->time_base); | ||||
|         frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts); | ||||
|         ret = frame_list_add_frame(s->frame_list, buf->audio->nb_samples, pts); | ||||
|         if (ret < 0) | ||||
|             goto fail; | ||||
|     } | ||||
|  | ||||
|     av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data, | ||||
|     ret = av_audio_fifo_write(s->fifos[i], (void **)buf->extended_data, | ||||
|                               buf->audio->nb_samples); | ||||
|  | ||||
| fail: | ||||
|     avfilter_unref_buffer(buf); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int init(AVFilterContext *ctx, const char *args) | ||||
|   | ||||
| @@ -168,13 +168,14 @@ static int config_output(AVFilterLink *outlink) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) | ||||
| { | ||||
|     AResampleContext *aresample = inlink->dst->priv; | ||||
|     const int n_in  = insamplesref->audio->nb_samples; | ||||
|     int n_out       = n_in * aresample->ratio * 2 ; | ||||
|     AVFilterLink *const outlink = inlink->dst->outputs[0]; | ||||
|     AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n_out); | ||||
|     int ret; | ||||
|  | ||||
|  | ||||
|     avfilter_copy_buffer_ref_props(outsamplesref, insamplesref); | ||||
| @@ -193,15 +194,16 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref | ||||
|     if (n_out <= 0) { | ||||
|         avfilter_unref_buffer(outsamplesref); | ||||
|         avfilter_unref_buffer(insamplesref); | ||||
|         return; | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     outsamplesref->audio->sample_rate = outlink->sample_rate; | ||||
|     outsamplesref->audio->nb_samples  = n_out; | ||||
|  | ||||
|     ff_filter_samples(outlink, outsamplesref); | ||||
|     ret = ff_filter_samples(outlink, outsamplesref); | ||||
|     aresample->req_fullfilled= 1; | ||||
|     avfilter_unref_buffer(insamplesref); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int request_frame(AVFilterLink *outlink) | ||||
|   | ||||
| @@ -131,7 +131,7 @@ static int push_samples(AVFilterLink *outlink) | ||||
|     return nb_out_samples; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     ASNSContext *asns = ctx->priv; | ||||
| @@ -145,7 +145,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|         if (ret < 0) { | ||||
|             av_log(ctx, AV_LOG_ERROR, | ||||
|                    "Stretching audio fifo failed, discarded %d samples\n", nb_samples); | ||||
|             return; | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
|     av_audio_fifo_write(asns->fifo, (void **)insamples->extended_data, nb_samples); | ||||
| @@ -155,6 +155,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|  | ||||
|     if (av_audio_fifo_size(asns->fifo) >= asns->nb_out_samples) | ||||
|         push_samples(outlink); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int request_frame(AVFilterLink *outlink) | ||||
|   | ||||
| @@ -40,7 +40,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     ShowInfoContext *showinfo = ctx->priv; | ||||
| @@ -83,7 +83,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) | ||||
|     av_log(ctx, AV_LOG_INFO, "]\n"); | ||||
|  | ||||
|     showinfo->frame++; | ||||
|     ff_filter_samples(inlink->dst->outputs[0], samplesref); | ||||
|     return ff_filter_samples(inlink->dst->outputs[0], samplesref); | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_ashowinfo = { | ||||
|   | ||||
| @@ -107,11 +107,12 @@ static int config_output(AVFilterLink *outlink) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void send_out(AVFilterContext *ctx, int out_id) | ||||
| static int send_out(AVFilterContext *ctx, int out_id) | ||||
| { | ||||
|     AStreamSyncContext *as = ctx->priv; | ||||
|     struct buf_queue *queue = &as->queue[out_id]; | ||||
|     AVFilterBufferRef *buf = queue->buf[queue->tail]; | ||||
|     int ret; | ||||
|  | ||||
|     queue->buf[queue->tail] = NULL; | ||||
|     as->var_values[VAR_B1 + out_id]++; | ||||
| @@ -121,11 +122,12 @@ static void send_out(AVFilterContext *ctx, int out_id) | ||||
|             av_q2d(ctx->outputs[out_id]->time_base) * buf->pts; | ||||
|     as->var_values[VAR_T1 + out_id] += buf->audio->nb_samples / | ||||
|                                    (double)ctx->inputs[out_id]->sample_rate; | ||||
|     ff_filter_samples(ctx->outputs[out_id], buf); | ||||
|     ret = ff_filter_samples(ctx->outputs[out_id], buf); | ||||
|     queue->nb--; | ||||
|     queue->tail = (queue->tail + 1) % QUEUE_SIZE; | ||||
|     if (as->req[out_id]) | ||||
|         as->req[out_id]--; | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static void send_next(AVFilterContext *ctx) | ||||
| @@ -165,7 +167,7 @@ static int request_frame(AVFilterLink *outlink) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     AStreamSyncContext *as = ctx->priv; | ||||
| @@ -175,6 +177,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|         insamples; | ||||
|     as->eof &= ~(1 << id); | ||||
|     send_next(ctx); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_astreamsync = { | ||||
|   | ||||
| @@ -37,6 +37,9 @@ typedef struct ASyncContext { | ||||
|     int resample; | ||||
|     float min_delta_sec; | ||||
|     int max_comp; | ||||
|  | ||||
|     /* set by filter_samples() to signal an output frame to request_frame() */ | ||||
|     int got_output; | ||||
| } ASyncContext; | ||||
|  | ||||
| #define OFFSET(x) offsetof(ASyncContext, x) | ||||
| @@ -112,9 +115,13 @@ static int request_frame(AVFilterLink *link) | ||||
| { | ||||
|     AVFilterContext *ctx = link->src; | ||||
|     ASyncContext      *s = ctx->priv; | ||||
|     int ret = ff_request_frame(ctx->inputs[0]); | ||||
|     int ret = 0; | ||||
|     int nb_samples; | ||||
|  | ||||
|     s->got_output = 0; | ||||
|     while (ret >= 0 && !s->got_output) | ||||
|         ret = ff_request_frame(ctx->inputs[0]); | ||||
|  | ||||
|     /* flush the fifo */ | ||||
|     if (ret == AVERROR_EOF && (nb_samples = avresample_get_delay(s->avr))) { | ||||
|         AVFilterBufferRef *buf = ff_get_audio_buffer(link, AV_PERM_WRITE, | ||||
| @@ -124,18 +131,18 @@ static int request_frame(AVFilterLink *link) | ||||
|         avresample_convert(s->avr, (void**)buf->extended_data, buf->linesize[0], | ||||
|                            nb_samples, NULL, 0, 0); | ||||
|         buf->pts = s->pts; | ||||
|         ff_filter_samples(link, buf); | ||||
|         return 0; | ||||
|         return ff_filter_samples(link, buf); | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static void write_to_fifo(ASyncContext *s, AVFilterBufferRef *buf) | ||||
| static int write_to_fifo(ASyncContext *s, AVFilterBufferRef *buf) | ||||
| { | ||||
|     avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data, | ||||
|     int ret = avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data, | ||||
|                                  buf->linesize[0], buf->audio->nb_samples); | ||||
|     avfilter_unref_buffer(buf); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /* get amount of data currently buffered, in samples */ | ||||
| @@ -144,7 +151,7 @@ static int64_t get_delay(ASyncContext *s) | ||||
|     return avresample_available(s->avr) + avresample_get_delay(s->avr); | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| { | ||||
|     AVFilterContext  *ctx = inlink->dst; | ||||
|     ASyncContext       *s = ctx->priv; | ||||
| @@ -152,7 +159,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
|     int nb_channels = av_get_channel_layout_nb_channels(buf->audio->channel_layout); | ||||
|     int64_t pts = (buf->pts == AV_NOPTS_VALUE) ? buf->pts : | ||||
|                   av_rescale_q(buf->pts, inlink->time_base, outlink->time_base); | ||||
|     int out_size; | ||||
|     int out_size, ret; | ||||
|     int64_t delta; | ||||
|  | ||||
|     /* buffer data until we get the first timestamp */ | ||||
| @@ -160,14 +167,12 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
|         if (pts != AV_NOPTS_VALUE) { | ||||
|             s->pts = pts - get_delay(s); | ||||
|         } | ||||
|         write_to_fifo(s, buf); | ||||
|         return; | ||||
|         return write_to_fifo(s, buf); | ||||
|     } | ||||
|  | ||||
|     /* now wait for the next timestamp */ | ||||
|     if (pts == AV_NOPTS_VALUE) { | ||||
|         write_to_fifo(s, buf); | ||||
|         return; | ||||
|         return write_to_fifo(s, buf); | ||||
|     } | ||||
|  | ||||
|     /* when we have two timestamps, compute how many samples would we have | ||||
| @@ -190,8 +195,10 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
|     if (out_size > 0) { | ||||
|         AVFilterBufferRef *buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE, | ||||
|                                                          out_size); | ||||
|         if (!buf_out) | ||||
|             return; | ||||
|         if (!buf_out) { | ||||
|             ret = AVERROR(ENOMEM); | ||||
|             goto fail; | ||||
|         } | ||||
|  | ||||
|         avresample_read(s->avr, (void**)buf_out->extended_data, out_size); | ||||
|         buf_out->pts = s->pts; | ||||
| @@ -200,7 +207,10 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
|             av_samples_set_silence(buf_out->extended_data, out_size - delta, | ||||
|                                    delta, nb_channels, buf->format); | ||||
|         } | ||||
|         ff_filter_samples(outlink, buf_out); | ||||
|         ret = ff_filter_samples(outlink, buf_out); | ||||
|         if (ret < 0) | ||||
|             goto fail; | ||||
|         s->got_output = 1; | ||||
|     } else { | ||||
|         av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping " | ||||
|                "whole buffer.\n"); | ||||
| @@ -210,9 +220,13 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
|     avresample_read(s->avr, NULL, avresample_available(s->avr)); | ||||
|  | ||||
|     s->pts = pts - avresample_get_delay(s->avr); | ||||
|     avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data, | ||||
|     ret = avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data, | ||||
|                              buf->linesize[0], buf->audio->nb_samples); | ||||
|  | ||||
| fail: | ||||
|     avfilter_unref_buffer(buf); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_asyncts = { | ||||
|   | ||||
| @@ -1040,7 +1040,7 @@ static void push_samples(ATempoContext *atempo, | ||||
|     atempo->nsamples_out += n_out; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, | ||||
| static int filter_samples(AVFilterLink *inlink, | ||||
|                            AVFilterBufferRef *src_buffer) | ||||
| { | ||||
|     AVFilterContext  *ctx = inlink->dst; | ||||
| @@ -1074,6 +1074,7 @@ static void filter_samples(AVFilterLink *inlink, | ||||
|  | ||||
|     atempo->nsamples_in += n_in; | ||||
|     avfilter_unref_bufferp(&src_buffer); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int request_frame(AVFilterLink *outlink) | ||||
|   | ||||
| @@ -313,7 +313,7 @@ static int channelmap_query_formats(AVFilterContext *ctx) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| { | ||||
|     AVFilterContext  *ctx = inlink->dst; | ||||
|     AVFilterLink *outlink = ctx->outputs[0]; | ||||
| @@ -330,8 +330,10 @@ static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *b | ||||
|         if (nch_out > FF_ARRAY_ELEMS(buf->data)) { | ||||
|             uint8_t **new_extended_data = | ||||
|                 av_mallocz(nch_out * sizeof(*buf->extended_data)); | ||||
|             if (!new_extended_data) | ||||
|                 return; | ||||
|             if (!new_extended_data) { | ||||
|                 avfilter_unref_buffer(buf); | ||||
|                 return AVERROR(ENOMEM); | ||||
|             } | ||||
|             if (buf->extended_data == buf->data) { | ||||
|                 buf->extended_data = new_extended_data; | ||||
|             } else { | ||||
| @@ -353,7 +355,7 @@ static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *b | ||||
|         memcpy(buf->data, buf->extended_data, | ||||
|            FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0])); | ||||
|  | ||||
|     ff_filter_samples(outlink, buf); | ||||
|     return ff_filter_samples(outlink, buf); | ||||
| } | ||||
|  | ||||
| static int channelmap_config_input(AVFilterLink *inlink) | ||||
|   | ||||
| @@ -105,24 +105,29 @@ static int query_formats(AVFilterContext *ctx) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     int i; | ||||
|     int i, ret = 0; | ||||
|  | ||||
|     for (i = 0; i < ctx->nb_outputs; i++) { | ||||
|         AVFilterBufferRef *buf_out = avfilter_ref_buffer(buf, ~AV_PERM_WRITE); | ||||
|  | ||||
|         if (!buf_out) | ||||
|             return; | ||||
|         if (!buf_out) { | ||||
|             ret = AVERROR(ENOMEM); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[i]; | ||||
|         buf_out->audio->channel_layout = | ||||
|             av_channel_layout_extract_channel(buf->audio->channel_layout, i); | ||||
|  | ||||
|         ff_filter_samples(ctx->outputs[i], buf_out); | ||||
|         ret = ff_filter_samples(ctx->outputs[i], buf_out); | ||||
|         if (ret < 0) | ||||
|             break; | ||||
|     } | ||||
|     avfilter_unref_buffer(buf); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_channelsplit = { | ||||
|   | ||||
| @@ -120,13 +120,15 @@ static inline int16_t *scalarproduct(const int16_t *in, const int16_t *endin, in | ||||
|     return out; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     AVFilterLink *outlink = inlink->dst->outputs[0]; | ||||
|     int16_t *taps, *endin, *in, *out; | ||||
|     AVFilterBufferRef *outsamples = | ||||
|         ff_get_audio_buffer(inlink, AV_PERM_WRITE, | ||||
|                                   insamples->audio->nb_samples); | ||||
|     int ret; | ||||
|  | ||||
|     avfilter_copy_buffer_ref_props(outsamples, insamples); | ||||
|  | ||||
|     taps  = ((EarwaxContext *)inlink->dst->priv)->taps; | ||||
| @@ -144,8 +146,9 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|     // save part of input for next round | ||||
|     memcpy(taps, endin, NUMTAPS * sizeof(*taps)); | ||||
|  | ||||
|     ff_filter_samples(outlink, outsamples); | ||||
|     ret = ff_filter_samples(outlink, outsamples); | ||||
|     avfilter_unref_buffer(insamples); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_earwax = { | ||||
|   | ||||
| @@ -92,7 +92,7 @@ static const AVClass join_class = { | ||||
|     .version    = LIBAVUTIL_VERSION_INT, | ||||
| }; | ||||
|  | ||||
| static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) | ||||
| static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) | ||||
| { | ||||
|     AVFilterContext *ctx = link->dst; | ||||
|     JoinContext       *s = ctx->priv; | ||||
| @@ -104,6 +104,8 @@ static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) | ||||
|     av_assert0(i < ctx->nb_inputs); | ||||
|     av_assert0(!s->input_frames[i]); | ||||
|     s->input_frames[i] = buf; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int parse_maps(AVFilterContext *ctx) | ||||
| @@ -468,11 +470,11 @@ static int join_request_frame(AVFilterLink *outlink) | ||||
|     priv->nb_in_buffers = ctx->nb_inputs; | ||||
|     buf->buf->priv      = priv; | ||||
|  | ||||
|     ff_filter_samples(outlink, buf); | ||||
|     ret = ff_filter_samples(outlink, buf); | ||||
|  | ||||
|     memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs); | ||||
|  | ||||
|     return 0; | ||||
|     return ret; | ||||
|  | ||||
| fail: | ||||
|     avfilter_unref_buffer(buf); | ||||
|   | ||||
| @@ -343,8 +343,9 @@ static int config_props(AVFilterLink *link) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     int ret; | ||||
|     int n = insamples->audio->nb_samples; | ||||
|     AVFilterLink *const outlink = inlink->dst->outputs[0]; | ||||
|     AVFilterBufferRef *outsamples = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n); | ||||
| @@ -354,8 +355,9 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|     avfilter_copy_buffer_ref_props(outsamples, insamples); | ||||
|     outsamples->audio->channel_layout = outlink->channel_layout; | ||||
|  | ||||
|     ff_filter_samples(outlink, outsamples); | ||||
|     ret = ff_filter_samples(outlink, outsamples); | ||||
|     avfilter_unref_buffer(insamples); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static av_cold void uninit(AVFilterContext *ctx) | ||||
|   | ||||
| @@ -38,6 +38,9 @@ typedef struct ResampleContext { | ||||
|     AVAudioResampleContext *avr; | ||||
|  | ||||
|     int64_t next_pts; | ||||
|  | ||||
|     /* set by filter_samples() to signal an output frame to request_frame() */ | ||||
|     int got_output; | ||||
| } ResampleContext; | ||||
|  | ||||
| static av_cold void uninit(AVFilterContext *ctx) | ||||
| @@ -102,12 +105,6 @@ static int config_output(AVFilterLink *outlink) | ||||
|     av_opt_set_int(s->avr,  "in_sample_rate",    inlink ->sample_rate,    0); | ||||
|     av_opt_set_int(s->avr, "out_sample_rate",    outlink->sample_rate,    0); | ||||
|  | ||||
|     /* if both the input and output formats are s16 or u8, use s16 as | ||||
|        the internal sample format */ | ||||
|     if (av_get_bytes_per_sample(inlink->format)  <= 2 && | ||||
|         av_get_bytes_per_sample(outlink->format) <= 2) | ||||
|         av_opt_set_int(s->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0); | ||||
|  | ||||
|     if ((ret = avresample_open(s->avr)) < 0) | ||||
|         return ret; | ||||
|  | ||||
| @@ -130,7 +127,11 @@ static int request_frame(AVFilterLink *outlink) | ||||
| { | ||||
|     AVFilterContext *ctx = outlink->src; | ||||
|     ResampleContext   *s = ctx->priv; | ||||
|     int ret = ff_request_frame(ctx->inputs[0]); | ||||
|     int ret = 0; | ||||
|  | ||||
|     s->got_output = 0; | ||||
|     while (ret >= 0 && !s->got_output) | ||||
|         ret = ff_request_frame(ctx->inputs[0]); | ||||
|  | ||||
|     /* flush the lavr delay buffer */ | ||||
|     if (ret == AVERROR_EOF && s->avr) { | ||||
| @@ -156,21 +157,21 @@ static int request_frame(AVFilterLink *outlink) | ||||
|         } | ||||
|  | ||||
|         buf->pts = s->next_pts; | ||||
|         ff_filter_samples(outlink, buf); | ||||
|         return 0; | ||||
|         return ff_filter_samples(outlink, buf); | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| { | ||||
|     AVFilterContext  *ctx = inlink->dst; | ||||
|     ResampleContext    *s = ctx->priv; | ||||
|     AVFilterLink *outlink = ctx->outputs[0]; | ||||
|     int ret; | ||||
|  | ||||
|     if (s->avr) { | ||||
|         AVFilterBufferRef *buf_out; | ||||
|         int delay, nb_samples, ret; | ||||
|         int delay, nb_samples; | ||||
|  | ||||
|         /* maximum possible samples lavr can output */ | ||||
|         delay      = avresample_get_delay(s->avr); | ||||
| @@ -179,10 +180,19 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
|                                     AV_ROUND_UP); | ||||
|  | ||||
|         buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples); | ||||
|         if (!buf_out) { | ||||
|             ret = AVERROR(ENOMEM); | ||||
|             goto fail; | ||||
|         } | ||||
|  | ||||
|         ret     = avresample_convert(s->avr, (void**)buf_out->extended_data, | ||||
|                                      buf_out->linesize[0], nb_samples, | ||||
|                                      (void**)buf->extended_data, buf->linesize[0], | ||||
|                                      buf->audio->nb_samples); | ||||
|         if (ret < 0) { | ||||
|             avfilter_unref_buffer(buf_out); | ||||
|             goto fail; | ||||
|         } | ||||
|  | ||||
|         av_assert0(!avresample_available(s->avr)); | ||||
|  | ||||
| @@ -208,11 +218,18 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
|  | ||||
|             s->next_pts = buf_out->pts + buf_out->audio->nb_samples; | ||||
|  | ||||
|             ff_filter_samples(outlink, buf_out); | ||||
|             ret = ff_filter_samples(outlink, buf_out); | ||||
|             s->got_output = 1; | ||||
|         } | ||||
|  | ||||
| fail: | ||||
|         avfilter_unref_buffer(buf); | ||||
|     } else | ||||
|         ff_filter_samples(outlink, buf); | ||||
|     } else { | ||||
|         ret = ff_filter_samples(outlink, buf); | ||||
|         s->got_output = 1; | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_resample = { | ||||
|   | ||||
| @@ -78,7 +78,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     int i; | ||||
|     SilenceDetectContext *silence = inlink->dst->priv; | ||||
| @@ -118,7 +118,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     ff_filter_samples(inlink->dst->outputs[0], insamples); | ||||
|     return ff_filter_samples(inlink->dst->outputs[0], insamples); | ||||
| } | ||||
|  | ||||
| static int query_formats(AVFilterContext *ctx) | ||||
|   | ||||
| @@ -110,7 +110,7 @@ static int query_formats(AVFilterContext *ctx) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     VolumeContext *vol = inlink->dst->priv; | ||||
|     AVFilterLink *outlink = inlink->dst->outputs[0]; | ||||
| @@ -169,7 +169,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|         } | ||||
|         } | ||||
|     } | ||||
|     ff_filter_samples(outlink, insamples); | ||||
|     return ff_filter_samples(outlink, insamples); | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_volume = { | ||||
|   | ||||
| @@ -21,7 +21,10 @@ | ||||
| #include "avfilter.h" | ||||
| #include "internal.h" | ||||
|  | ||||
| static void null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) { } | ||||
| static int null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_asink_anullsink = { | ||||
|     .name        = "anullsink", | ||||
|   | ||||
| @@ -150,19 +150,19 @@ fail: | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| static void default_filter_samples(AVFilterLink *link, | ||||
| static int default_filter_samples(AVFilterLink *link, | ||||
|                                   AVFilterBufferRef *samplesref) | ||||
| { | ||||
|     ff_filter_samples(link->dst->outputs[0], samplesref); | ||||
|     return ff_filter_samples(link->dst->outputs[0], samplesref); | ||||
| } | ||||
|  | ||||
| void ff_filter_samples_framed(AVFilterLink *link, | ||||
|                               AVFilterBufferRef *samplesref) | ||||
| int ff_filter_samples_framed(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||||
| { | ||||
|     void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); | ||||
|     int (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); | ||||
|     AVFilterPad *dst = link->dstpad; | ||||
|     int64_t pts; | ||||
|     AVFilterBufferRef *buf_out; | ||||
|     int ret; | ||||
|  | ||||
|     FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1); | ||||
|  | ||||
| @@ -193,21 +193,22 @@ void ff_filter_samples_framed(AVFilterLink *link, | ||||
|  | ||||
|     link->cur_buf = buf_out; | ||||
|     pts = buf_out->pts; | ||||
|     filter_samples(link, buf_out); | ||||
|     ret = filter_samples(link, buf_out); | ||||
|     ff_update_link_current_pts(link, pts); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||||
| int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||||
| { | ||||
|     int insamples = samplesref->audio->nb_samples, inpos = 0, nb_samples; | ||||
|     AVFilterBufferRef *pbuf = link->partial_buf; | ||||
|     int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); | ||||
|     int ret = 0; | ||||
|  | ||||
|     if (!link->min_samples || | ||||
|         (!pbuf && | ||||
|          insamples >= link->min_samples && insamples <= link->max_samples)) { | ||||
|         ff_filter_samples_framed(link, samplesref); | ||||
|         return; | ||||
|         return ff_filter_samples_framed(link, samplesref); | ||||
|     } | ||||
|     /* Handle framing (min_samples, max_samples) */ | ||||
|     while (insamples) { | ||||
| @@ -218,7 +219,7 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||||
|             if (!pbuf) { | ||||
|                 av_log(link->dst, AV_LOG_WARNING, | ||||
|                        "Samples dropped due to memory allocation failure.\n"); | ||||
|                 return; | ||||
|                 return 0; | ||||
|             } | ||||
|             avfilter_copy_buffer_ref_props(pbuf, samplesref); | ||||
|             pbuf->pts = samplesref->pts + | ||||
| @@ -234,10 +235,11 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||||
|         insamples               -= nb_samples; | ||||
|         pbuf->audio->nb_samples += nb_samples; | ||||
|         if (pbuf->audio->nb_samples >= link->min_samples) { | ||||
|             ff_filter_samples_framed(link, pbuf); | ||||
|             ret = ff_filter_samples_framed(link, pbuf); | ||||
|             pbuf = NULL; | ||||
|         } | ||||
|     } | ||||
|     avfilter_unref_buffer(samplesref); | ||||
|     link->partial_buf = pbuf; | ||||
|     return ret; | ||||
| } | ||||
|   | ||||
| @@ -70,14 +70,17 @@ AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms, | ||||
|  * @param samplesref a reference to the buffer of audio samples being sent. The | ||||
|  *                   receiving filter will free this reference when it no longer | ||||
|  *                   needs it or pass it on to the next filter. | ||||
|  * | ||||
|  * @return >= 0 on success, a negative AVERROR on error. The receiving filter | ||||
|  * is responsible for unreferencing samplesref in case of error. | ||||
|  */ | ||||
| void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); | ||||
| int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); | ||||
|  | ||||
| /** | ||||
|  * Send a buffer of audio samples to the next link, without checking | ||||
|  * min_samples. | ||||
|  */ | ||||
| void ff_filter_samples_framed(AVFilterLink *link, | ||||
| int ff_filter_samples_framed(AVFilterLink *link, | ||||
|                               AVFilterBufferRef *samplesref); | ||||
|  | ||||
| #endif /* AVFILTER_AUDIO_H */ | ||||
|   | ||||
| @@ -180,7 +180,7 @@ static int request_frame(AVFilterLink *outlink) | ||||
|  | ||||
| #define MAX_INT16 ((1<<15) -1) | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     AVFilterLink *outlink = ctx->outputs[0]; | ||||
| @@ -225,6 +225,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|     } | ||||
|  | ||||
|     avfilter_unref_buffer(insamples); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_avf_showwaves = { | ||||
|   | ||||
| @@ -301,8 +301,12 @@ struct AVFilterPad { | ||||
|      * and should do its processing. | ||||
|      * | ||||
|      * Input audio pads only. | ||||
|      * | ||||
|      * @return >= 0 on success, a negative AVERROR on error. This function | ||||
|      * must ensure that samplesref is properly unreferenced on error if it | ||||
|      * hasn't been passed on to another filter. | ||||
|      */ | ||||
|     void (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); | ||||
|     int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); | ||||
|  | ||||
|     /** | ||||
|      * Frame poll callback. This returns the number of immediately available | ||||
|   | ||||
| @@ -56,6 +56,12 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *buf) | ||||
|     link->cur_buf = NULL; | ||||
| }; | ||||
|  | ||||
| static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) | ||||
| { | ||||
|     start_frame(link, buf); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf) | ||||
| { | ||||
|     BufferSinkContext *s    = ctx->priv; | ||||
| @@ -160,7 +166,7 @@ AVFilter avfilter_asink_abuffer = { | ||||
|  | ||||
|     .inputs    = (AVFilterPad[]) {{ .name           = "default", | ||||
|                                     .type           = AVMEDIA_TYPE_AUDIO, | ||||
|                                     .filter_samples = start_frame, | ||||
|                                     .filter_samples = filter_samples, | ||||
|                                     .min_perms      = AV_PERM_READ, | ||||
|                                     .needs_fifo     = 1 }, | ||||
|                                   { .name = NULL }}, | ||||
|   | ||||
| @@ -408,6 +408,7 @@ static int request_frame(AVFilterLink *link) | ||||
| { | ||||
|     BufferSourceContext *c = link->src->priv; | ||||
|     AVFilterBufferRef *buf; | ||||
|     int ret = 0; | ||||
|  | ||||
|     if (!av_fifo_size(c->fifo)) { | ||||
|         if (c->eof) | ||||
| @@ -424,7 +425,7 @@ static int request_frame(AVFilterLink *link) | ||||
|         ff_end_frame(link); | ||||
|         break; | ||||
|     case AVMEDIA_TYPE_AUDIO: | ||||
|         ff_filter_samples(link, avfilter_ref_buffer(buf, ~0)); | ||||
|         ret = ff_filter_samples(link, avfilter_ref_buffer(buf, ~0)); | ||||
|         break; | ||||
|     default: | ||||
|         return AVERROR(EINVAL); | ||||
| @@ -432,7 +433,7 @@ static int request_frame(AVFilterLink *link) | ||||
|  | ||||
|     avfilter_unref_buffer(buf); | ||||
|  | ||||
|     return 0; | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int poll_frame(AVFilterLink *link) | ||||
|   | ||||
| @@ -117,7 +117,7 @@ static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | ||||
|     ff_start_frame(outlink, picref2); | ||||
| } | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     AVFilterLink *outlink = ctx->outputs[0]; | ||||
| @@ -132,7 +132,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) | ||||
|         avfilter_unref_buffer(insamples); | ||||
|     } | ||||
|  | ||||
|     ff_filter_samples(outlink, outsamples); | ||||
|     return ff_filter_samples(outlink, outsamples); | ||||
| } | ||||
|  | ||||
| #if CONFIG_SETTB_FILTER | ||||
|   | ||||
| @@ -72,13 +72,25 @@ static av_cold void uninit(AVFilterContext *ctx) | ||||
|     avfilter_unref_buffer(fifo->buf_out); | ||||
| } | ||||
|  | ||||
| static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| static int add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| { | ||||
|     FifoContext *fifo = inlink->dst->priv; | ||||
|  | ||||
|     fifo->last->next = av_mallocz(sizeof(Buf)); | ||||
|     if (!fifo->last->next) { | ||||
|         avfilter_unref_buffer(buf); | ||||
|         return AVERROR(ENOMEM); | ||||
|     } | ||||
|  | ||||
|     fifo->last = fifo->last->next; | ||||
|     fifo->last->buf = buf; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) | ||||
| { | ||||
|     add_to_queue(inlink, buf); | ||||
| } | ||||
|  | ||||
| static void queue_pop(FifoContext *s) | ||||
| @@ -210,15 +222,13 @@ static int return_audio_frame(AVFilterContext *ctx) | ||||
|         buf_out = s->buf_out; | ||||
|         s->buf_out = NULL; | ||||
|     } | ||||
|     ff_filter_samples(link, buf_out); | ||||
|  | ||||
|     return 0; | ||||
|     return ff_filter_samples(link, buf_out); | ||||
| } | ||||
|  | ||||
| static int request_frame(AVFilterLink *outlink) | ||||
| { | ||||
|     FifoContext *fifo = outlink->src->priv; | ||||
|     int ret; | ||||
|     int ret = 0; | ||||
|  | ||||
|     if (!fifo->root.next) { | ||||
|         if ((ret = ff_request_frame(outlink->src->inputs[0])) < 0) | ||||
| @@ -238,7 +248,7 @@ static int request_frame(AVFilterLink *outlink) | ||||
|         if (outlink->request_samples) { | ||||
|             return return_audio_frame(outlink->src); | ||||
|         } else { | ||||
|             ff_filter_samples(outlink, fifo->root.next->buf); | ||||
|             ret = ff_filter_samples(outlink, fifo->root.next->buf); | ||||
|             queue_pop(fifo); | ||||
|         } | ||||
|         break; | ||||
| @@ -246,7 +256,7 @@ static int request_frame(AVFilterLink *outlink) | ||||
|         return AVERROR(EINVAL); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_vf_fifo = { | ||||
| @@ -261,7 +271,7 @@ AVFilter avfilter_vf_fifo = { | ||||
|     .inputs    = (const AVFilterPad[]) {{ .name      = "default", | ||||
|                                     .type            = AVMEDIA_TYPE_VIDEO, | ||||
|                                     .get_video_buffer= ff_null_get_video_buffer, | ||||
|                                     .start_frame     = add_to_queue, | ||||
|                                     .start_frame     = start_frame, | ||||
|                                     .draw_slice      = draw_slice, | ||||
|                                     .end_frame       = end_frame, | ||||
|                                     .rej_perms       = AV_PERM_REUSE2, }, | ||||
|   | ||||
| @@ -135,8 +135,12 @@ struct AVFilterPad { | ||||
|      * and should do its processing. | ||||
|      * | ||||
|      * Input audio pads only. | ||||
|      * | ||||
|      * @return >= 0 on success, a negative AVERROR on error. This function | ||||
|      * must ensure that samplesref is properly unreferenced on error if it | ||||
|      * hasn't been passed on to another filter. | ||||
|      */ | ||||
|     void (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); | ||||
|     int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); | ||||
|  | ||||
|     /** | ||||
|      * Frame poll callback. This returns the number of immediately available | ||||
|   | ||||
| @@ -244,9 +244,10 @@ AVFilter avfilter_vsink_buffersink = { | ||||
|  | ||||
| #if CONFIG_ABUFFERSINK_FILTER | ||||
|  | ||||
| static void filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||||
| static int filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||||
| { | ||||
|     end_frame(link); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static av_cold int asink_init(AVFilterContext *ctx, const char *args) | ||||
|   | ||||
| @@ -110,15 +110,19 @@ AVFilter avfilter_vf_split = { | ||||
|     .outputs   = (AVFilterPad[]) {{ .name = NULL}}, | ||||
| }; | ||||
|  | ||||
| static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) | ||||
| static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     int i; | ||||
|     int i, ret = 0; | ||||
|  | ||||
|     for (i = 0; i < ctx->nb_outputs; i++) | ||||
|         ff_filter_samples(inlink->dst->outputs[i], | ||||
|     for (i = 0; i < ctx->nb_outputs; i++) { | ||||
|         ret = ff_filter_samples(inlink->dst->outputs[i], | ||||
|                                 avfilter_ref_buffer(samplesref, ~AV_PERM_WRITE)); | ||||
|         if (ret < 0) | ||||
|             break; | ||||
|     } | ||||
|     avfilter_unref_buffer(samplesref); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| AVFilter avfilter_af_asplit = { | ||||
|   | ||||
| @@ -842,8 +842,11 @@ static int ebml_parse_id(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, | ||||
|         matroska->num_levels > 0 && | ||||
|         matroska->levels[matroska->num_levels-1].length == 0xffffffffffffff) | ||||
|         return 0;  // we reached the end of an unknown size cluster | ||||
|     if (!syntax[i].id && id != EBML_ID_VOID && id != EBML_ID_CRC32) | ||||
|     if (!syntax[i].id && id != EBML_ID_VOID && id != EBML_ID_CRC32) { | ||||
|         av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%X\n", id); | ||||
|         if (matroska->ctx->error_recognition & AV_EF_EXPLODE) | ||||
|             return AVERROR_INVALIDDATA; | ||||
|     } | ||||
|     return ebml_parse_elem(matroska, &syntax[i], data); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -43,7 +43,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | ||||
|     char buf[256]; | ||||
|     int ret; | ||||
|     socklen_t optlen; | ||||
|     int timeout = 50; | ||||
|     int timeout = 50, listen_timeout = -1; | ||||
|     char hostname[1024],proto[1024],path[1024]; | ||||
|     char portstr[10]; | ||||
|  | ||||
| @@ -59,6 +59,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | ||||
|         if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { | ||||
|             timeout = strtol(buf, NULL, 10); | ||||
|         } | ||||
|         if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { | ||||
|             listen_timeout = strtol(buf, NULL, 10); | ||||
|         } | ||||
|     } | ||||
|     hints.ai_family = AF_UNSPEC; | ||||
|     hints.ai_socktype = SOCK_STREAM; | ||||
| @@ -87,6 +90,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | ||||
|     if (listen_socket) { | ||||
|         int fd1; | ||||
|         int reuse = 1; | ||||
|         struct pollfd lp = { fd, POLLIN, 0 }; | ||||
|         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); | ||||
|         ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); | ||||
|         if (ret) { | ||||
| @@ -98,6 +102,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | ||||
|             ret = ff_neterrno(); | ||||
|             goto fail1; | ||||
|         } | ||||
|         ret = poll(&lp, 1, listen_timeout >= 0 ? listen_timeout : -1); | ||||
|         if (ret <= 0) { | ||||
|             ret = AVERROR(ETIMEDOUT); | ||||
|             goto fail1; | ||||
|         } | ||||
|         fd1 = accept(fd, NULL, NULL); | ||||
|         if (fd1 < 0) { | ||||
|             ret = ff_neterrno(); | ||||
|   | ||||
| @@ -305,6 +305,14 @@ int ff_audio_mix_init(AVAudioResampleContext *avr) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && | ||||
|         avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) { | ||||
|         av_log(avr, AV_LOG_ERROR, "Unsupported internal format for " | ||||
|                "mixing: %s\n", | ||||
|                av_get_sample_fmt_name(avr->internal_sample_fmt)); | ||||
|         return AVERROR(EINVAL); | ||||
|     } | ||||
|  | ||||
|     /* build matrix if the user did not already set one */ | ||||
|     if (!avr->am->matrix) { | ||||
|         int i, j; | ||||
|   | ||||
| @@ -45,6 +45,13 @@ enum AVMixCoeffType { | ||||
|     AV_MIX_COEFF_TYPE_NB,   /** Number of coeff types. Not part of ABI      */ | ||||
| }; | ||||
|  | ||||
| /** Resampling Filter Types */ | ||||
| enum AVResampleFilterType { | ||||
|     AV_RESAMPLE_FILTER_TYPE_CUBIC,              /**< Cubic */ | ||||
|     AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL,   /**< Blackman Nuttall Windowed Sinc */ | ||||
|     AV_RESAMPLE_FILTER_TYPE_KAISER,             /**< Kaiser Windowed Sinc */ | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Return the LIBAVRESAMPLE_VERSION_INT constant. | ||||
|  */ | ||||
|   | ||||
| @@ -50,6 +50,8 @@ struct AVAudioResampleContext { | ||||
|     int phase_shift;                            /**< log2 of the number of entries in the resampling polyphase filterbank */ | ||||
|     int linear_interp;                          /**< if 1 then the resampling FIR filter will be linearly interpolated */ | ||||
|     double cutoff;                              /**< resampling cutoff frequency. 1.0 corresponds to half the output sample rate */ | ||||
|     enum AVResampleFilterType filter_type;      /**< resampling filter type */ | ||||
|     int kaiser_beta;                            /**< beta value for Kaiser window (only applicable if filter_type == AV_FILTER_TYPE_KAISER) */ | ||||
|  | ||||
|     int in_channels;        /**< number of input channels                   */ | ||||
|     int out_channels;       /**< number of output channels                  */ | ||||
|   | ||||
| @@ -39,7 +39,7 @@ static const AVOption options[] = { | ||||
|     { "out_channel_layout",     "Output Channel Layout",    OFFSET(out_channel_layout),     AV_OPT_TYPE_INT64,  { 0                     }, INT64_MIN,            INT64_MAX,              PARAM }, | ||||
|     { "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 }, | ||||
|     { "out_sample_rate",        "Output Sample Rate",       OFFSET(out_sample_rate),        AV_OPT_TYPE_INT,    { 48000                 }, 1,                    INT_MAX,                PARAM }, | ||||
|     { "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 }, | ||||
|     { "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 }, | ||||
|     { "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" }, | ||||
|         { "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" }, | ||||
|         { "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[] = { | ||||
|         { "none",  "None",               0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_NONE  }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, | ||||
|         { "dolby", "Dolby",              0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_DOLBY }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, | ||||
|         { "dplii", "Dolby Pro Logic II", 0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_DPLII }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" }, | ||||
|     { "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" }, | ||||
|         { "cubic",            "Cubic",                          0, AV_OPT_TYPE_CONST, { AV_RESAMPLE_FILTER_TYPE_CUBIC            }, INT_MIN, INT_MAX, PARAM, "filter_type" }, | ||||
|         { "blackman_nuttall", "Blackman Nuttall Windowed Sinc", 0, AV_OPT_TYPE_CONST, { AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL }, INT_MIN, INT_MAX, PARAM, "filter_type" }, | ||||
|         { "kaiser",           "Kaiser Windowed Sinc",           0, AV_OPT_TYPE_CONST, { AV_RESAMPLE_FILTER_TYPE_KAISER           }, INT_MIN, INT_MAX, PARAM, "filter_type" }, | ||||
|     { "kaiser_beta",            "Kaiser Window Beta",       OFFSET(kaiser_beta),            AV_OPT_TYPE_INT,    { 9                     }, 2,                    16,                     PARAM }, | ||||
|     { NULL }, | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -24,37 +24,10 @@ | ||||
| #include "internal.h" | ||||
| #include "audio_data.h" | ||||
|  | ||||
| #ifdef CONFIG_RESAMPLE_FLT | ||||
| /* float template */ | ||||
| #define FILTER_SHIFT  0 | ||||
| #define FELEM         float | ||||
| #define FELEM2        float | ||||
| #define FELEML        float | ||||
| #define WINDOW_TYPE   24 | ||||
| #elifdef CONFIG_RESAMPLE_S32 | ||||
| /* s32 template */ | ||||
| #define FILTER_SHIFT  30 | ||||
| #define FELEM         int32_t | ||||
| #define FELEM2        int64_t | ||||
| #define FELEML        int64_t | ||||
| #define FELEM_MAX     INT32_MAX | ||||
| #define FELEM_MIN     INT32_MIN | ||||
| #define WINDOW_TYPE   12 | ||||
| #else | ||||
| /* s16 template */ | ||||
| #define FILTER_SHIFT  15 | ||||
| #define FELEM         int16_t | ||||
| #define FELEM2        int32_t | ||||
| #define FELEML        int64_t | ||||
| #define FELEM_MAX     INT16_MAX | ||||
| #define FELEM_MIN     INT16_MIN | ||||
| #define WINDOW_TYPE   9 | ||||
| #endif | ||||
|  | ||||
| struct ResampleContext { | ||||
|     AVAudioResampleContext *avr; | ||||
|     AudioData *buffer; | ||||
|     FELEM *filter_bank; | ||||
|     uint8_t *filter_bank; | ||||
|     int filter_length; | ||||
|     int ideal_dst_incr; | ||||
|     int dst_incr; | ||||
| @@ -65,9 +38,35 @@ struct ResampleContext { | ||||
|     int phase_shift; | ||||
|     int phase_mask; | ||||
|     int linear; | ||||
|     enum AVResampleFilterType filter_type; | ||||
|     int kaiser_beta; | ||||
|     double factor; | ||||
|     void (*set_filter)(void *filter, double *tab, int phase, int tap_count); | ||||
|     void (*resample_one)(struct ResampleContext *c, int no_filter, void *dst0, | ||||
|                          int dst_index, const void *src0, int src_size, | ||||
|                          int index, int frac); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* double template */ | ||||
| #define CONFIG_RESAMPLE_DBL | ||||
| #include "resample_template.c" | ||||
| #undef CONFIG_RESAMPLE_DBL | ||||
|  | ||||
| /* float template */ | ||||
| #define CONFIG_RESAMPLE_FLT | ||||
| #include "resample_template.c" | ||||
| #undef CONFIG_RESAMPLE_FLT | ||||
|  | ||||
| /* s32 template */ | ||||
| #define CONFIG_RESAMPLE_S32 | ||||
| #include "resample_template.c" | ||||
| #undef CONFIG_RESAMPLE_S32 | ||||
|  | ||||
| /* s16 template */ | ||||
| #include "resample_template.c" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 0th order modified bessel function of the first kind. | ||||
|  */ | ||||
| @@ -95,17 +94,17 @@ static double bessel(double x) | ||||
|  * @param      tap_count    tap count | ||||
|  * @param      phase_count  phase count | ||||
|  * @param      scale        wanted sum of coefficients for each filter | ||||
|  * @param      type         0->cubic | ||||
|  *                          1->blackman nuttall windowed sinc | ||||
|  *                          2..16->kaiser windowed sinc beta=2..16 | ||||
|  * @param      filter_type  filter type | ||||
|  * @param      kaiser_beta  kaiser window beta | ||||
|  * @return                  0 on success, negative AVERROR code on failure | ||||
|  */ | ||||
| static int build_filter(FELEM *filter, double factor, int tap_count, | ||||
|                         int phase_count, int scale, int type) | ||||
| static int build_filter(ResampleContext *c) | ||||
| { | ||||
|     int ph, i; | ||||
|     double x, y, w; | ||||
|     double x, y, w, factor; | ||||
|     double *tab; | ||||
|     int tap_count    = c->filter_length; | ||||
|     int phase_count  = 1 << c->phase_shift; | ||||
|     const int center = (tap_count - 1) / 2; | ||||
|  | ||||
|     tab = av_malloc(tap_count * sizeof(*tab)); | ||||
| @@ -113,8 +112,7 @@ static int build_filter(FELEM *filter, double factor, int tap_count, | ||||
|         return AVERROR(ENOMEM); | ||||
|  | ||||
|     /* if upsampling, only need to interpolate, no filter */ | ||||
|     if (factor > 1.0) | ||||
|         factor = 1.0; | ||||
|     factor = FFMIN(c->factor, 1.0); | ||||
|  | ||||
|     for (ph = 0; ph < phase_count; ph++) { | ||||
|         double norm = 0; | ||||
| @@ -122,39 +120,34 @@ static int build_filter(FELEM *filter, double factor, int tap_count, | ||||
|             x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor; | ||||
|             if (x == 0) y = 1.0; | ||||
|             else        y = sin(x) / x; | ||||
|             switch (type) { | ||||
|             case 0: { | ||||
|             switch (c->filter_type) { | ||||
|             case AV_RESAMPLE_FILTER_TYPE_CUBIC: { | ||||
|                 const float d = -0.5; //first order derivative = -0.5 | ||||
|                 x = fabs(((double)(i - center) - (double)ph / phase_count) * factor); | ||||
|                 if (x < 1.0) y = 1 - 3 * x*x + 2 * x*x*x + d * (                -x*x + x*x*x); | ||||
|                 else         y =                           d * (-4 + 8 * x - 5 * x*x + x*x*x); | ||||
|                 break; | ||||
|             } | ||||
|             case 1: | ||||
|             case AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL: | ||||
|                 w  = 2.0 * x / (factor * tap_count) + M_PI; | ||||
|                 y *= 0.3635819 - 0.4891775 * cos(    w) + | ||||
|                                  0.1365995 * cos(2 * w) - | ||||
|                                  0.0106411 * cos(3 * w); | ||||
|                 break; | ||||
|             default: | ||||
|             case AV_RESAMPLE_FILTER_TYPE_KAISER: | ||||
|                 w  = 2.0 * x / (factor * tap_count * M_PI); | ||||
|                 y *= bessel(type * sqrt(FFMAX(1 - w * w, 0))); | ||||
|                 y *= bessel(c->kaiser_beta * sqrt(FFMAX(1 - w * w, 0))); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             tab[i] = y; | ||||
|             norm  += y; | ||||
|         } | ||||
|  | ||||
|         /* normalize so that an uniform color remains the same */ | ||||
|         for (i = 0; i < tap_count; i++) { | ||||
| #ifdef CONFIG_RESAMPLE_FLT | ||||
|             filter[ph * tap_count + i] = tab[i] / norm; | ||||
| #else | ||||
|             filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm), | ||||
|                                                  FELEM_MIN, FELEM_MAX); | ||||
| #endif | ||||
|         } | ||||
|         for (i = 0; i < tap_count; i++) | ||||
|             tab[i] = tab[i] / norm; | ||||
|  | ||||
|         c->set_filter(c->filter_bank, tab, ph, tap_count); | ||||
|     } | ||||
|  | ||||
|     av_free(tab); | ||||
| @@ -168,9 +161,12 @@ ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr) | ||||
|     int in_rate     = avr->in_sample_rate; | ||||
|     double factor   = FFMIN(out_rate * avr->cutoff / in_rate, 1.0); | ||||
|     int phase_count = 1 << avr->phase_shift; | ||||
|     int felem_size; | ||||
|  | ||||
|     /* TODO: add support for s32 and float internal formats */ | ||||
|     if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) { | ||||
|     if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && | ||||
|         avr->internal_sample_fmt != AV_SAMPLE_FMT_S32P && | ||||
|         avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP && | ||||
|         avr->internal_sample_fmt != AV_SAMPLE_FMT_DBLP) { | ||||
|         av_log(avr, AV_LOG_ERROR, "Unsupported internal format for " | ||||
|                "resampling: %s\n", | ||||
|                av_get_sample_fmt_name(avr->internal_sample_fmt)); | ||||
| @@ -186,18 +182,40 @@ ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr) | ||||
|     c->linear        = avr->linear_interp; | ||||
|     c->factor        = factor; | ||||
|     c->filter_length = FFMAX((int)ceil(avr->filter_size / factor), 1); | ||||
|     c->filter_type   = avr->filter_type; | ||||
|     c->kaiser_beta   = avr->kaiser_beta; | ||||
|  | ||||
|     c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * sizeof(FELEM)); | ||||
|     switch (avr->internal_sample_fmt) { | ||||
|     case AV_SAMPLE_FMT_DBLP: | ||||
|         c->resample_one  = resample_one_dbl; | ||||
|         c->set_filter    = set_filter_dbl; | ||||
|         break; | ||||
|     case AV_SAMPLE_FMT_FLTP: | ||||
|         c->resample_one  = resample_one_flt; | ||||
|         c->set_filter    = set_filter_flt; | ||||
|         break; | ||||
|     case AV_SAMPLE_FMT_S32P: | ||||
|         c->resample_one  = resample_one_s32; | ||||
|         c->set_filter    = set_filter_s32; | ||||
|         break; | ||||
|     case AV_SAMPLE_FMT_S16P: | ||||
|         c->resample_one  = resample_one_s16; | ||||
|         c->set_filter    = set_filter_s16; | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     felem_size = av_get_bytes_per_sample(avr->internal_sample_fmt); | ||||
|     c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * felem_size); | ||||
|     if (!c->filter_bank) | ||||
|         goto error; | ||||
|  | ||||
|     if (build_filter(c->filter_bank, factor, c->filter_length, phase_count, | ||||
|                      1 << FILTER_SHIFT, WINDOW_TYPE) < 0) | ||||
|     if (build_filter(c) < 0) | ||||
|         goto error; | ||||
|  | ||||
|     memcpy(&c->filter_bank[c->filter_length * phase_count + 1], | ||||
|            c->filter_bank, (c->filter_length - 1) * sizeof(FELEM)); | ||||
|     c->filter_bank[c->filter_length * phase_count] = c->filter_bank[c->filter_length - 1]; | ||||
|     memcpy(&c->filter_bank[(c->filter_length * phase_count + 1) * felem_size], | ||||
|            c->filter_bank, (c->filter_length - 1) * felem_size); | ||||
|     memcpy(&c->filter_bank[c->filter_length * phase_count * felem_size], | ||||
|            &c->filter_bank[(c->filter_length - 1) * felem_size], felem_size); | ||||
|  | ||||
|     c->compensation_distance = 0; | ||||
|     if (!av_reduce(&c->src_incr, &c->dst_incr, out_rate, | ||||
| @@ -311,10 +329,10 @@ reinit_fail: | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int resample(ResampleContext *c, int16_t *dst, const int16_t *src, | ||||
| static int resample(ResampleContext *c, void *dst, const void *src, | ||||
|                     int *consumed, int src_size, int dst_size, int update_ctx) | ||||
| { | ||||
|     int dst_index, i; | ||||
|     int dst_index; | ||||
|     int index         = c->index; | ||||
|     int frac          = c->frac; | ||||
|     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, | ||||
|  | ||||
|         if (dst) { | ||||
|             for(dst_index = 0; dst_index < dst_size; dst_index++) { | ||||
|                 dst[dst_index] = src[index2 >> 32]; | ||||
|                 c->resample_one(c, 1, dst, dst_index, src, 0, index2 >> 32, 0); | ||||
|                 index2 += incr; | ||||
|             } | ||||
|         } else { | ||||
| @@ -345,42 +363,14 @@ static int resample(ResampleContext *c, int16_t *dst, const int16_t *src, | ||||
|         frac   = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr; | ||||
|     } else { | ||||
|         for (dst_index = 0; dst_index < dst_size; dst_index++) { | ||||
|             FELEM *filter = c->filter_bank + | ||||
|                             c->filter_length * (index & c->phase_mask); | ||||
|             int sample_index = index >> c->phase_shift; | ||||
|  | ||||
|             if (!dst && (sample_index + c->filter_length > src_size || | ||||
|                          -sample_index >= src_size)) | ||||
|             if (sample_index + c->filter_length > src_size || | ||||
|                 -sample_index >= src_size) | ||||
|                 break; | ||||
|  | ||||
|             if (dst) { | ||||
|                 FELEM2 val = 0; | ||||
|  | ||||
|                 if (sample_index < 0) { | ||||
|                     for (i = 0; i < c->filter_length; i++) | ||||
|                         val += src[FFABS(sample_index + i) % src_size] * | ||||
|                                (FELEM2)filter[i]; | ||||
|                 } else if (sample_index + c->filter_length > src_size) { | ||||
|                     break; | ||||
|                 } else if (c->linear) { | ||||
|                     FELEM2 v2 = 0; | ||||
|                     for (i = 0; i < c->filter_length; i++) { | ||||
|                         val += src[abs(sample_index + i)] * (FELEM2)filter[i]; | ||||
|                         v2  += src[abs(sample_index + i)] * (FELEM2)filter[i + c->filter_length]; | ||||
|                     } | ||||
|                     val += (v2 - val) * (FELEML)frac / c->src_incr; | ||||
|                 } else { | ||||
|                     for (i = 0; i < c->filter_length; i++) | ||||
|                         val += src[sample_index + i] * (FELEM2)filter[i]; | ||||
|                 } | ||||
|  | ||||
| #ifdef CONFIG_RESAMPLE_FLT | ||||
|                 dst[dst_index] = av_clip_int16(lrintf(val)); | ||||
| #else | ||||
|                 val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; | ||||
|                 dst[dst_index] = av_clip_int16(val); | ||||
| #endif | ||||
|             } | ||||
|             if (dst) | ||||
|                 c->resample_one(c, 0, dst, dst_index, src, src_size, index, frac); | ||||
|  | ||||
|             frac  += dst_incr_frac; | ||||
|             index += dst_incr; | ||||
| @@ -451,8 +441,8 @@ int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src, | ||||
|  | ||||
|     /* resample each channel plane */ | ||||
|     for (ch = 0; ch < c->buffer->channels; ch++) { | ||||
|         out_samples = resample(c, (int16_t *)dst->data[ch], | ||||
|                                (const int16_t *)c->buffer->data[ch], consumed, | ||||
|         out_samples = resample(c, (void *)dst->data[ch], | ||||
|                                (const void *)c->buffer->data[ch], consumed, | ||||
|                                c->buffer->nb_samples, dst->allocated_samples, | ||||
|                                ch + 1 == c->buffer->channels); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										102
									
								
								libavresample/resample_template.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								libavresample/resample_template.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| /* | ||||
|  * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at> | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with FFmpeg; if not, write to the Free Software | ||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
|  */ | ||||
|  | ||||
| #if defined(CONFIG_RESAMPLE_DBL) | ||||
| #define SET_TYPE(func)  func ## _dbl | ||||
| #define FELEM         double | ||||
| #define FELEM2        double | ||||
| #define FELEML        double | ||||
| #define OUT(d, v) d = v | ||||
| #define DBL_TO_FELEM(d, v) d = v | ||||
| #elif defined(CONFIG_RESAMPLE_FLT) | ||||
| #define SET_TYPE(func)  func ## _flt | ||||
| #define FELEM         float | ||||
| #define FELEM2        float | ||||
| #define FELEML        float | ||||
| #define OUT(d, v) d = v | ||||
| #define DBL_TO_FELEM(d, v) d = v | ||||
| #elif defined(CONFIG_RESAMPLE_S32) | ||||
| #define SET_TYPE(func)  func ## _s32 | ||||
| #define FELEM         int32_t | ||||
| #define FELEM2        int64_t | ||||
| #define FELEML        int64_t | ||||
| #define OUT(d, v) d = av_clipl_int32((v + (1 << 29)) >> 30) | ||||
| #define DBL_TO_FELEM(d, v) d = av_clipl_int32(llrint(v * (1 << 30))); | ||||
| #else | ||||
| #define SET_TYPE(func)  func ## _s16 | ||||
| #define FELEM         int16_t | ||||
| #define FELEM2        int32_t | ||||
| #define FELEML        int64_t | ||||
| #define OUT(d, v) d = av_clip_int16((v + (1 << 14)) >> 15) | ||||
| #define DBL_TO_FELEM(d, v) d = av_clip_int16(lrint(v * (1 << 15))) | ||||
| #endif | ||||
|  | ||||
| static void SET_TYPE(resample_one)(ResampleContext *c, int no_filter, | ||||
|                                    void *dst0, int dst_index, const void *src0, | ||||
|                                    int src_size, int index, int frac) | ||||
| { | ||||
|     FELEM *dst = dst0; | ||||
|     const FELEM *src = src0; | ||||
|  | ||||
|     if (no_filter) { | ||||
|         dst[dst_index] = src[index]; | ||||
|     } else { | ||||
|         int i; | ||||
|         int sample_index = index >> c->phase_shift; | ||||
|         FELEM2 val = 0; | ||||
|         FELEM *filter = ((FELEM *)c->filter_bank) + | ||||
|                         c->filter_length * (index & c->phase_mask); | ||||
|  | ||||
|         if (sample_index < 0) { | ||||
|             for (i = 0; i < c->filter_length; i++) | ||||
|                 val += src[FFABS(sample_index + i) % src_size] * | ||||
|                        (FELEM2)filter[i]; | ||||
|         } else if (c->linear) { | ||||
|             FELEM2 v2 = 0; | ||||
|             for (i = 0; i < c->filter_length; i++) { | ||||
|                 val += src[abs(sample_index + i)] * (FELEM2)filter[i]; | ||||
|                 v2  += src[abs(sample_index + i)] * (FELEM2)filter[i + c->filter_length]; | ||||
|             } | ||||
|             val += (v2 - val) * (FELEML)frac / c->src_incr; | ||||
|         } else { | ||||
|             for (i = 0; i < c->filter_length; i++) | ||||
|                 val += src[sample_index + i] * (FELEM2)filter[i]; | ||||
|         } | ||||
|  | ||||
|         OUT(dst[dst_index], val); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void SET_TYPE(set_filter)(void *filter0, double *tab, int phase, | ||||
|                                  int tap_count) | ||||
| { | ||||
|     int i; | ||||
|     FELEM *filter = ((FELEM *)filter0) + phase * tap_count; | ||||
|     for (i = 0; i < tap_count; i++) { | ||||
|         DBL_TO_FELEM(filter[i], tab[i]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #undef SET_TYPE | ||||
| #undef FELEM | ||||
| #undef FELEM2 | ||||
| #undef FELEML | ||||
| #undef OUT | ||||
| #undef DBL_TO_FELEM | ||||
| @@ -57,18 +57,43 @@ int avresample_open(AVAudioResampleContext *avr) | ||||
|     avr->resample_needed   = avr->in_sample_rate != avr->out_sample_rate || | ||||
|                              avr->force_resampling; | ||||
|  | ||||
|     /* set sample format conversion parameters */ | ||||
|     /* override user-requested internal format to avoid unexpected failures | ||||
|        TODO: support more internal formats */ | ||||
|     if (avr->resample_needed && avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) { | ||||
|         av_log(avr, AV_LOG_WARNING, "Using s16p as internal sample format\n"); | ||||
|     /* select internal sample format if not specified by the user */ | ||||
|     if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE && | ||||
|         (avr->mixing_needed || avr->resample_needed)) { | ||||
|         enum AVSampleFormat  in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); | ||||
|         enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); | ||||
|         int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt), | ||||
|                             av_get_bytes_per_sample(out_fmt)); | ||||
|         if (max_bps <= 2) { | ||||
|             avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P; | ||||
|     } else if (avr->mixing_needed && | ||||
|                avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && | ||||
|                avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) { | ||||
|         av_log(avr, AV_LOG_WARNING, "Using fltp as internal sample format\n"); | ||||
|         } else if (avr->mixing_needed) { | ||||
|             avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; | ||||
|         } else { | ||||
|             if (max_bps <= 4) { | ||||
|                 if (in_fmt  == AV_SAMPLE_FMT_S32P || | ||||
|                     out_fmt == AV_SAMPLE_FMT_S32P) { | ||||
|                     if (in_fmt  == AV_SAMPLE_FMT_FLTP || | ||||
|                         out_fmt == AV_SAMPLE_FMT_FLTP) { | ||||
|                         /* if one is s32 and the other is flt, use dbl */ | ||||
|                         avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; | ||||
|                     } else { | ||||
|                         /* if one is s32 and the other is s32, s16, or u8, use s32 */ | ||||
|                         avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P; | ||||
|                     } | ||||
|                 } else { | ||||
|                     /* if one is flt and the other is flt, s16 or u8, use flt */ | ||||
|                     avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; | ||||
|                 } | ||||
|             } else { | ||||
|                 /* if either is dbl, use dbl */ | ||||
|                 avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; | ||||
|             } | ||||
|         } | ||||
|         av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n", | ||||
|                av_get_sample_fmt_name(avr->internal_sample_fmt)); | ||||
|     } | ||||
|  | ||||
|     /* set sample format conversion parameters */ | ||||
|     if (avr->in_channels == 1) | ||||
|         avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); | ||||
|     if (avr->out_channels == 1) | ||||
|   | ||||
| @@ -75,7 +75,13 @@ probefmt(){ | ||||
| } | ||||
|  | ||||
| ffmpeg(){ | ||||
|     run ffmpeg -nostats -threads $threads -thread_type $thread_type -cpuflags $cpuflags "$@" | ||||
|     dec_opts="-threads $threads -thread_type $thread_type" | ||||
|     ffmpeg_args="-nostats -cpuflags $cpuflags" | ||||
|     for arg in $@; do | ||||
|         [ ${arg} = -i ] && ffmpeg_args="${ffmpeg_args} ${dec_opts}" | ||||
|         ffmpeg_args="${ffmpeg_args} ${arg}" | ||||
|     done | ||||
|     run ffmpeg ${ffmpeg_args} | ||||
| } | ||||
|  | ||||
| framecrc(){ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user