You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	extend resampling API, add S16 internal conversion
Originally committed as revision 17163 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
		
							
								
								
									
										16
									
								
								ffmpeg.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								ffmpeg.c
									
									
									
									
									
								
							| @@ -555,12 +555,12 @@ static void do_audio_out(AVFormatContext *s, | ||||
|         ost->audio_resample = 1; | ||||
|  | ||||
|     if (ost->audio_resample && !ost->resample) { | ||||
|         if (dec->sample_fmt != SAMPLE_FMT_S16) { | ||||
|             fprintf(stderr, "Audio resampler only works with 16 bits per sample, patch welcome.\n"); | ||||
|             av_exit(1); | ||||
|         } | ||||
|         ost->resample = audio_resample_init(enc->channels,    dec->channels, | ||||
|                                             enc->sample_rate, dec->sample_rate); | ||||
|         if (dec->sample_fmt != SAMPLE_FMT_S16) | ||||
|             fprintf(stderr, "Warning, using s16 intermediate sample format for resampling\n"); | ||||
|         ost->resample = av_audio_resample_init(enc->channels,    dec->channels, | ||||
|                                                enc->sample_rate, dec->sample_rate, | ||||
|                                                enc->sample_fmt,  dec->sample_fmt, | ||||
|                                                16, 10, 0, 0.8); | ||||
|         if (!ost->resample) { | ||||
|             fprintf(stderr, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n", | ||||
|                     dec->channels, dec->sample_rate, | ||||
| @@ -570,7 +570,7 @@ static void do_audio_out(AVFormatContext *s, | ||||
|     } | ||||
|  | ||||
| #define MAKE_SFMT_PAIR(a,b) ((a)+SAMPLE_FMT_NB*(b)) | ||||
|     if (dec->sample_fmt!=enc->sample_fmt && | ||||
|     if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt && | ||||
|         MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt)!=ost->reformat_pair) { | ||||
|         if (!audio_out2) | ||||
|             audio_out2 = av_malloc(audio_out_size); | ||||
| @@ -647,7 +647,7 @@ static void do_audio_out(AVFormatContext *s, | ||||
|         size_out = size; | ||||
|     } | ||||
|  | ||||
|     if (dec->sample_fmt!=enc->sample_fmt) { | ||||
|     if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt) { | ||||
|         const void *ibuf[6]= {buftmp}; | ||||
|         void *obuf[6]= {audio_out2}; | ||||
|         int istride[6]= {isize}; | ||||
|   | ||||
| @@ -30,7 +30,7 @@ | ||||
| #include "libavutil/avutil.h" | ||||
|  | ||||
| #define LIBAVCODEC_VERSION_MAJOR 52 | ||||
| #define LIBAVCODEC_VERSION_MINOR 14 | ||||
| #define LIBAVCODEC_VERSION_MINOR 15 | ||||
| #define LIBAVCODEC_VERSION_MICRO  0 | ||||
|  | ||||
| #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | ||||
| @@ -2443,8 +2443,36 @@ struct AVResampleContext; | ||||
|  | ||||
| typedef struct ReSampleContext ReSampleContext; | ||||
|  | ||||
| ReSampleContext *audio_resample_init(int output_channels, int input_channels, | ||||
|                                      int output_rate, int input_rate); | ||||
| #if LIBAVCODEC_VERSION_MAJOR < 53 | ||||
| /** | ||||
|  * @deprecated Use av_audio_resample_init() instead. | ||||
|  */ | ||||
| attribute_deprecated ReSampleContext *audio_resample_init(int output_channels, int input_channels, | ||||
|                                                           int output_rate, int input_rate); | ||||
| #endif | ||||
| /** | ||||
|  *  Initializes audio resampling context | ||||
|  * | ||||
|  * @param output_channels  number of output channels | ||||
|  * @param input_channels   number of input channels | ||||
|  * @param output_rate      output sample rate | ||||
|  * @param input_rate       input sample rate | ||||
|  * @param sample_fmt_out   requested output sample format | ||||
|  * @param sample_fmt_in    input sample format | ||||
|  * @param filter_length    length of each FIR filter in the filterbank relative to the cutoff freq | ||||
|  * @param log2_phase_count log2 of the number of entries in the polyphase filterbank | ||||
|  * @param linear           If 1 then the used FIR filter will be linearly interpolated | ||||
|                            between the 2 closest, if 0 the closest will be used | ||||
|  * @param cutoff           cutoff frequency, 1.0 corresponds to half the output sampling rate | ||||
|  * @return allocated ReSampleContext, NULL if error occured | ||||
|  */ | ||||
| ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, | ||||
|                                         int output_rate, int input_rate, | ||||
|                                         enum SampleFormat sample_fmt_out, | ||||
|                                         enum SampleFormat sample_fmt_in, | ||||
|                                         int filter_length, int log2_phase_count, | ||||
|                                         int linear, double cutoff); | ||||
|  | ||||
| int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples); | ||||
| void audio_resample_close(ReSampleContext *s); | ||||
|  | ||||
|   | ||||
| @@ -25,16 +25,32 @@ | ||||
|  */ | ||||
|  | ||||
| #include "avcodec.h" | ||||
| #include "audioconvert.h" | ||||
| #include "opt.h" | ||||
|  | ||||
| struct AVResampleContext; | ||||
|  | ||||
| static const char *context_to_name(void *ptr) | ||||
| { | ||||
|     return "audioresample"; | ||||
| } | ||||
|  | ||||
| static const AVOption options[] = {{NULL}}; | ||||
| static const AVClass audioresample_context_class = { "ReSampleContext", context_to_name, options }; | ||||
|  | ||||
| struct ReSampleContext { | ||||
|     const AVClass *av_class; | ||||
|     struct AVResampleContext *resample_context; | ||||
|     short *temp[2]; | ||||
|     int temp_len; | ||||
|     float ratio; | ||||
|     /* channel convert */ | ||||
|     int input_channels, output_channels, filter_channels; | ||||
|     AVAudioConvert *convert_ctx[2]; | ||||
|     enum SampleFormat sample_fmt[2]; ///< input and output sample format | ||||
|     unsigned sample_size[2];         ///< size of one sample in sample_fmt | ||||
|     short *buffer[2];                ///< buffers used for conversion to S16 | ||||
|     unsigned buffer_size[2];         ///< sizes of allocated buffers | ||||
| }; | ||||
|  | ||||
| /* n1: number of samples */ | ||||
| @@ -126,8 +142,12 @@ static void ac3_5p1_mux(short *output, short *input1, short *input2, int n) | ||||
|     } | ||||
| } | ||||
|  | ||||
| ReSampleContext *audio_resample_init(int output_channels, int input_channels, | ||||
|                                       int output_rate, int input_rate) | ||||
| ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, | ||||
|                                         int output_rate, int input_rate, | ||||
|                                         enum SampleFormat sample_fmt_out, | ||||
|                                         enum SampleFormat sample_fmt_in, | ||||
|                                         int filter_length, int log2_phase_count, | ||||
|                                         int linear, double cutoff) | ||||
| { | ||||
|     ReSampleContext *s; | ||||
|  | ||||
| @@ -153,6 +173,34 @@ ReSampleContext *audio_resample_init(int output_channels, int input_channels, | ||||
|     if (s->output_channels < s->filter_channels) | ||||
|         s->filter_channels = s->output_channels; | ||||
|  | ||||
|     s->sample_fmt [0] = sample_fmt_in; | ||||
|     s->sample_fmt [1] = sample_fmt_out; | ||||
|     s->sample_size[0] = av_get_bits_per_sample_format(s->sample_fmt[0])>>3; | ||||
|     s->sample_size[1] = av_get_bits_per_sample_format(s->sample_fmt[1])>>3; | ||||
|  | ||||
|     if (s->sample_fmt[0] != SAMPLE_FMT_S16) { | ||||
|         if (!(s->convert_ctx[0] = av_audio_convert_alloc(SAMPLE_FMT_S16, 1, | ||||
|                                                          s->sample_fmt[0], 1, NULL, 0))) { | ||||
|             av_log(s, AV_LOG_ERROR, | ||||
|                    "Cannot convert %s sample format to s16 sample format\n", | ||||
|                    avcodec_get_sample_fmt_name(s->sample_fmt[0])); | ||||
|             av_free(s); | ||||
|             return NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (s->sample_fmt[1] != SAMPLE_FMT_S16) { | ||||
|         if (!(s->convert_ctx[1] = av_audio_convert_alloc(s->sample_fmt[1], 1, | ||||
|                                                          SAMPLE_FMT_S16, 1, NULL, 0))) { | ||||
|             av_log(s, AV_LOG_ERROR, | ||||
|                    "Cannot convert s16 sample format to %s sample format\n", | ||||
|                    avcodec_get_sample_fmt_name(s->sample_fmt[1])); | ||||
|             av_audio_convert_free(s->convert_ctx[0]); | ||||
|             av_free(s); | ||||
|             return NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| /* | ||||
|  * AC-3 output is the only case where filter_channels could be greater than 2. | ||||
|  * input channels can't be greater than 2, so resample the 2 channels and then | ||||
| @@ -162,11 +210,25 @@ ReSampleContext *audio_resample_init(int output_channels, int input_channels, | ||||
|       s->filter_channels = 2; | ||||
|  | ||||
| #define TAPS 16 | ||||
|     s->resample_context= av_resample_init(output_rate, input_rate, TAPS, 10, 0, 0.8); | ||||
|     s->resample_context= av_resample_init(output_rate, input_rate, | ||||
|                          filter_length, log2_phase_count, linear, cutoff); | ||||
|  | ||||
|     s->av_class= &audioresample_context_class; | ||||
|  | ||||
|     return s; | ||||
| } | ||||
|  | ||||
| #if LIBAVCODEC_VERSION_MAJOR < 53 | ||||
| ReSampleContext *audio_resample_init(int output_channels, int input_channels, | ||||
|                                      int output_rate, int input_rate) | ||||
| { | ||||
|     return av_audio_resample_init(output_channels, input_channels, | ||||
|                                   output_rate, input_rate, | ||||
|                                   SAMPLE_FMT_S16, SAMPLE_FMT_S16, | ||||
|                                   TAPS, 10, 0, 0.8); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* resample audio. 'nb_samples' is the number of input samples */ | ||||
| /* XXX: optimize it ! */ | ||||
| int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) | ||||
| @@ -175,6 +237,7 @@ int audio_resample(ReSampleContext *s, short *output, short *input, int nb_sampl | ||||
|     short *bufin[2]; | ||||
|     short *bufout[2]; | ||||
|     short *buftmp2[2], *buftmp3[2]; | ||||
|     short *output_bak = NULL; | ||||
|     int lenout; | ||||
|  | ||||
|     if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) { | ||||
| @@ -183,6 +246,52 @@ int audio_resample(ReSampleContext *s, short *output, short *input, int nb_sampl | ||||
|         return nb_samples; | ||||
|     } | ||||
|  | ||||
|     if (s->sample_fmt[0] != SAMPLE_FMT_S16) { | ||||
|         int istride[1] = { s->sample_size[0] }; | ||||
|         int ostride[1] = { 2 }; | ||||
|         const void *ibuf[1] = { input }; | ||||
|         void       *obuf[1]; | ||||
|         unsigned input_size = nb_samples*s->input_channels*s->sample_size[0]; | ||||
|  | ||||
|         if (!s->buffer_size[0] || s->buffer_size[0] < input_size) { | ||||
|             av_free(s->buffer[0]); | ||||
|             s->buffer_size[0] = input_size; | ||||
|             s->buffer[0] = av_malloc(s->buffer_size[0]); | ||||
|             if (!s->buffer[0]) { | ||||
|                 av_log(s, AV_LOG_ERROR, "Could not allocate buffer\n"); | ||||
|                 return 0; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         obuf[0] = s->buffer[0]; | ||||
|  | ||||
|         if (av_audio_convert(s->convert_ctx[0], obuf, ostride, | ||||
|                              ibuf, istride, nb_samples*s->input_channels) < 0) { | ||||
|             av_log(s, AV_LOG_ERROR, "Audio sample format conversion failed\n"); | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         input  = s->buffer[0]; | ||||
|     } | ||||
|  | ||||
|     lenout= 4*nb_samples * s->ratio + 16; | ||||
|  | ||||
|     if (s->sample_fmt[1] != SAMPLE_FMT_S16) { | ||||
|         output_bak = output; | ||||
|  | ||||
|         if (!s->buffer_size[1] || s->buffer_size[1] < lenout) { | ||||
|             av_free(s->buffer[1]); | ||||
|             s->buffer_size[1] = lenout; | ||||
|             s->buffer[1] = av_malloc(s->buffer_size[1]); | ||||
|             if (!s->buffer[1]) { | ||||
|                 av_log(s, AV_LOG_ERROR, "Could not allocate buffer\n"); | ||||
|                 return 0; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         output = s->buffer[1]; | ||||
|     } | ||||
|  | ||||
|     /* XXX: move those malloc to resample init code */ | ||||
|     for(i=0; i<s->filter_channels; i++){ | ||||
|         bufin[i]= av_malloc( (nb_samples + s->temp_len) * sizeof(short) ); | ||||
| @@ -191,7 +300,6 @@ int audio_resample(ReSampleContext *s, short *output, short *input, int nb_sampl | ||||
|     } | ||||
|  | ||||
|     /* make some zoom to avoid round pb */ | ||||
|     lenout= 4*nb_samples * s->ratio + 16; | ||||
|     bufout[0]= av_malloc( lenout * sizeof(short) ); | ||||
|     bufout[1]= av_malloc( lenout * sizeof(short) ); | ||||
|  | ||||
| @@ -233,6 +341,19 @@ int audio_resample(ReSampleContext *s, short *output, short *input, int nb_sampl | ||||
|         ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); | ||||
|     } | ||||
|  | ||||
|     if (s->sample_fmt[1] != SAMPLE_FMT_S16) { | ||||
|         int istride[1] = { 2 }; | ||||
|         int ostride[1] = { s->sample_size[1] }; | ||||
|         const void *ibuf[1] = { output }; | ||||
|         void       *obuf[1] = { output_bak }; | ||||
|  | ||||
|         if (av_audio_convert(s->convert_ctx[1], obuf, ostride, | ||||
|                              ibuf, istride, nb_samples1*s->output_channels) < 0) { | ||||
|             av_log(s, AV_LOG_ERROR, "Audio sample format convertion failed\n"); | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     for(i=0; i<s->filter_channels; i++) | ||||
|         av_free(bufin[i]); | ||||
|  | ||||
| @@ -246,5 +367,9 @@ void audio_resample_close(ReSampleContext *s) | ||||
|     av_resample_close(s->resample_context); | ||||
|     av_freep(&s->temp[0]); | ||||
|     av_freep(&s->temp[1]); | ||||
|     av_freep(&s->buffer[0]); | ||||
|     av_freep(&s->buffer[1]); | ||||
|     av_audio_convert_free(s->convert_ctx[0]); | ||||
|     av_audio_convert_free(s->convert_ctx[1]); | ||||
|     av_free(s); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user