1 /*
2  * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of MPlayer.
5  *
6  * MPlayer is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * MPlayer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <inttypes.h>
25 
26 #include "config.h"
27 #include "af.h"
28 #include "libavutil/rational.h"
29 #include "libswresample/swresample.h"
30 #include "libavutil/channel_layout.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/common.h"
34 
35 // Data for specific instances of this filter
36 typedef struct af_resample_s{
37     struct SwrContext *swrctx;
38     uint8_t *in[1];
39     uint8_t *tmp[1];
40     int in_alloc;
41     int tmp_alloc;
42 
43     int filter_length;
44     int linear;
45     int phase_shift;
46     double cutoff;
47 
48     int ctx_out_rate;
49     int ctx_in_rate;
50     int ctx_filter_size;
51     int ctx_phase_shift;
52     int ctx_linear;
53     double ctx_cutoff;
54 }af_resample_t;
55 
56 
57 // Initialization and runtime control
control(struct af_instance_s * af,int cmd,void * arg)58 static int control(struct af_instance_s* af, int cmd, void* arg)
59 {
60   af_resample_t* s   = (af_resample_t*)af->setup;
61   af_data_t *data= (af_data_t*)arg;
62   int out_rate, test_output_res; // helpers for checking input format
63 
64   switch(cmd){
65   case AF_CONTROL_REINIT:
66     if((af->data->rate == data->rate) || (af->data->rate == 0))
67         return AF_DETACH;
68 
69     af->data->nch    = data->nch;
70     if (af->data->nch > AF_NCH) af->data->nch = AF_NCH;
71     af->data->format = AF_FORMAT_S16_NE;
72     af->data->bps    = 2;
73     af->mul = (double)af->data->rate / data->rate;
74     af->delay = af->data->nch * s->filter_length / FFMIN(af->mul, 1); // *bps*.5
75 
76     if (s->ctx_out_rate != af->data->rate || s->ctx_in_rate != data->rate || s->ctx_filter_size != s->filter_length ||
77         s->ctx_phase_shift != s->phase_shift || s->ctx_linear != s->linear || s->ctx_cutoff != s->cutoff) {
78         swr_free(&s->swrctx);
79         if((s->swrctx=swr_alloc()) == NULL) return AF_ERROR;
80         av_opt_set_int(s->swrctx, "out_sample_rate", af->data->rate, 0);
81         av_opt_set_int(s->swrctx, "in_sample_rate", data->rate, 0);
82         av_opt_set_int(s->swrctx, "filter_size", s->filter_length, 0);
83         av_opt_set_int(s->swrctx, "phase_shift", s->phase_shift, 0);
84         av_opt_set_int(s->swrctx, "linear_interp", s->linear, 0);
85         av_opt_set_double(s->swrctx, "cutoff", s->cutoff, 0);
86         av_opt_set_sample_fmt(s->swrctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
87         av_opt_set_sample_fmt(s->swrctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
88         av_opt_set_int(s->swrctx, "in_channel_count", af->data->nch, 0);
89         av_opt_set_int(s->swrctx, "out_channel_count", af->data->nch, 0);
90         if(swr_init(s->swrctx) < 0) return AF_ERROR;
91         s->ctx_out_rate    = af->data->rate;
92         s->ctx_in_rate     = data->rate;
93         s->ctx_filter_size = s->filter_length;
94         s->ctx_phase_shift = s->phase_shift;
95         s->ctx_linear      = s->linear;
96         s->ctx_cutoff      = s->cutoff;
97     }
98 
99     // hack to make af_test_output ignore the samplerate change
100     out_rate = af->data->rate;
101     af->data->rate = data->rate;
102     test_output_res = af_test_output(af, (af_data_t*)arg);
103     af->data->rate = out_rate;
104     return test_output_res;
105   case AF_CONTROL_COMMAND_LINE:{
106     s->cutoff= 0.0;
107     sscanf((char*)arg,"%d:%d:%d:%d:%lf", &af->data->rate, &s->filter_length, &s->linear, &s->phase_shift, &s->cutoff);
108     if(s->cutoff <= 0.0) s->cutoff= FFMAX(1.0 - 6.5/(s->filter_length+8), 0.80);
109     return AF_OK;
110   }
111   case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET:
112     af->data->rate = *(int*)arg;
113     return AF_OK;
114   }
115   return AF_UNKNOWN;
116 }
117 
118 // Deallocate memory
uninit(struct af_instance_s * af)119 static void uninit(struct af_instance_s* af)
120 {
121     if(af->data)
122         free(af->data->audio);
123     free(af->data);
124     if(af->setup){
125         af_resample_t *s = af->setup;
126         swr_free(&s->swrctx);
127         av_free(s->in[0]);
128         av_free(s->tmp[0]);
129         free(s);
130     }
131 }
132 
133 // Filter data through filter
play(struct af_instance_s * af,af_data_t * data)134 static af_data_t* play(struct af_instance_s* af, af_data_t* data)
135 {
136   af_resample_t *s = af->setup;
137   int ret;
138   int8_t *in = (int8_t*)data->audio;
139   int8_t *out;
140   int chans   = data->nch;
141   int in_len  = data->len;
142   int out_len = in_len * af->mul + 10;
143 
144   if(AF_OK != RESIZE_LOCAL_BUFFER(af,data))
145       return NULL;
146 
147   av_fast_malloc(&s->tmp[0], &s->tmp_alloc, FFALIGN(out_len,32));
148   if(s->tmp[0] == NULL) return NULL;
149 
150   out= (int8_t*)af->data->audio;
151 
152   out_len= FFMIN(out_len, af->data->len);
153 
154   av_fast_malloc(&s->in[0], &s->in_alloc, FFALIGN(in_len,32));
155   if(s->in[0] == NULL) return NULL;
156 
157   memcpy(s->in[0], in, in_len);
158 
159   ret = swr_convert(s->swrctx, &s->tmp[0], out_len/chans/2, &s->in[0], in_len/chans/2);
160   if (ret < 0) return NULL;
161   out_len= ret*chans*2;
162 
163   memcpy(out, s->tmp[0], out_len);
164 
165   data->audio = af->data->audio;
166   data->len   = out_len;
167   data->rate  = af->data->rate;
168   return data;
169 }
170 
af_open(af_instance_t * af)171 static int af_open(af_instance_t* af){
172   af_resample_t *s = calloc(1,sizeof(af_resample_t));
173   af->control=control;
174   af->uninit=uninit;
175   af->play=play;
176   af->mul=1;
177   af->data=calloc(1,sizeof(af_data_t));
178   s->filter_length= 16;
179   s->cutoff= FFMAX(1.0 - 6.5/(s->filter_length+8), 0.80);
180   s->phase_shift= 10;
181 //  s->setup = RSMP_INT | FREQ_SLOPPY;
182   af->setup=s;
183   return AF_OK;
184 }
185 
186 const af_info_t af_info_lavcresample = {
187   "Sample frequency conversion using libavcodec",
188   "lavcresample",
189   "Michael Niedermayer",
190   "",
191   AF_FLAGS_REENTRANT,
192   af_open
193 };
194