comparison libao2/ao_jack.c @ 16104:fc2459a18bf3

improved audio delay estimation, supposed to help make the video smoother
author reimar
date Tue, 26 Jul 2005 10:47:29 +0000
parents 8bb0701496ec
children 0671f92d2cb4
comparison
equal deleted inserted replaced
16103:1b10f858d873 16104:fc2459a18bf3
41 #define MAX_CHANS 6 41 #define MAX_CHANS 6
42 static jack_port_t *ports[MAX_CHANS]; 42 static jack_port_t *ports[MAX_CHANS];
43 static int num_ports; ///< Number of used ports == number of channels 43 static int num_ports; ///< Number of used ports == number of channels
44 static jack_client_t *client; 44 static jack_client_t *client;
45 static float jack_latency; 45 static float jack_latency;
46 static int estimate;
46 static volatile int paused = 0; ///< set if paused 47 static volatile int paused = 0; ///< set if paused
47 static volatile int underrun = 0; ///< signals if an underrun occured 48 static volatile int underrun = 0; ///< signals if an underrun occured
48 49
49 //! If this is defined try to make a more precise delay estimation. Will be slower. 50 static volatile float callback_interval = 0;
50 #undef JACK_ESTIMATE_DELAY 51 static volatile float callback_time = 0;
51 #ifdef JACK_ESTIMATE_DELAY
52 static volatile int callback_samples = 0;
53 static volatile unsigned int callback_time = 0;
54 #endif
55 52
56 //! size of one chunk, if this is too small MPlayer will start to "stutter" 53 //! size of one chunk, if this is too small MPlayer will start to "stutter"
57 //! after a short time of playback 54 //! after a short time of playback
58 #define CHUNK_SIZE (16 * 1024) 55 #define CHUNK_SIZE (16 * 1024)
59 //! number of "virtual" chunks the buffer consists of 56 //! number of "virtual" chunks the buffer consists of
184 if (!paused && !underrun) 181 if (!paused && !underrun)
185 if (read_buffer(bufs, nframes, num_ports) < nframes) 182 if (read_buffer(bufs, nframes, num_ports) < nframes)
186 underrun = 1; 183 underrun = 1;
187 if (paused || underrun) 184 if (paused || underrun)
188 silence(bufs, nframes, num_ports); 185 silence(bufs, nframes, num_ports);
189 #ifdef JACK_ESTIMATE_DELAY 186 if (estimate) {
190 callback_samples = nframes; 187 float now = (float)GetTimer() / 1000000.0;
191 callback_time = GetTimer(); 188 float diff = callback_time + callback_interval - now;
192 #endif 189 if (diff < 0.002)
190 callback_time += callback_interval;
191 else
192 callback_time = now;
193 callback_interval = (float)nframes / (float)ao_data.samplerate;
194 }
193 return 0; 195 return 0;
194 } 196 }
195 197
196 /** 198 /**
197 * \brief print suboption usage help 199 * \brief print suboption usage help
202 "\n-ao jack commandline help:\n" 204 "\n-ao jack commandline help:\n"
203 "Example: mplayer -ao jack:port=myout\n" 205 "Example: mplayer -ao jack:port=myout\n"
204 " connects MPlayer to the jack ports named myout\n" 206 " connects MPlayer to the jack ports named myout\n"
205 "\nOptions:\n" 207 "\nOptions:\n"
206 " port=<port name>\n" 208 " port=<port name>\n"
207 " Connects to the given ports instead of the default physical ones\n"); 209 " Connects to the given ports instead of the default physical ones\n"
210 " estimate\n"
211 " Estimates the amount of data in buffers (experimental)\n");
208 } 212 }
209 213
210 static int init(int rate, int channels, int format, int flags) { 214 static int init(int rate, int channels, int format, int flags) {
211 const char **matching_ports = NULL; 215 const char **matching_ports = NULL;
212 char *port_name = NULL; 216 char *port_name = NULL;
213 char client_name[40]; 217 char client_name[40];
214 opt_t subopts[] = { 218 opt_t subopts[] = {
215 {"port", OPT_ARG_MSTRZ, &port_name, NULL}, 219 {"port", OPT_ARG_MSTRZ, &port_name, NULL},
220 {"estimate", OPT_ARG_BOOL, &estimate, NULL},
216 {NULL} 221 {NULL}
217 }; 222 };
218 int port_flags = JackPortIsInput; 223 int port_flags = JackPortIsInput;
219 int i; 224 int i;
225 estimate = 1;
220 if (subopt_parse(ao_subdevice, subopts) != 0) { 226 if (subopt_parse(ao_subdevice, subopts) != 0) {
221 print_help(); 227 print_help();
222 return 0; 228 return 0;
223 } 229 }
224 if (channels > MAX_CHANS) { 230 if (channels > MAX_CHANS) {
267 } 273 }
268 } 274 }
269 rate = jack_get_sample_rate(client); 275 rate = jack_get_sample_rate(client);
270 jack_latency = (float)(jack_port_get_total_latency(client, ports[0]) + 276 jack_latency = (float)(jack_port_get_total_latency(client, ports[0]) +
271 jack_get_buffer_size(client)) / (float)rate; 277 jack_get_buffer_size(client)) / (float)rate;
278 callback_interval = 0;
272 buffer = (unsigned char *) malloc(BUFFSIZE); 279 buffer = (unsigned char *) malloc(BUFFSIZE);
273 280
274 ao_data.channels = channels; 281 ao_data.channels = channels;
275 ao_data.samplerate = rate; 282 ao_data.samplerate = rate;
276 ao_data.format = AF_FORMAT_FLOAT_NE; 283 ao_data.format = AF_FORMAT_FLOAT_NE;
341 } 348 }
342 349
343 static float get_delay() { 350 static float get_delay() {
344 int buffered = BUFFSIZE - CHUNK_SIZE - buf_free(); // could be less 351 int buffered = BUFFSIZE - CHUNK_SIZE - buf_free(); // could be less
345 float in_jack = jack_latency; 352 float in_jack = jack_latency;
346 #ifdef JACK_ESTIMATE_DELAY 353 if (estimate && callback_interval > 0) {
347 unsigned int elapsed = GetTimer() - callback_time; 354 float elapsed = (float)GetTimer() / 1000000.0 - callback_time;
348 in_jack += (float)callback_samples / (float)ao_data.samplerate - (float)elapsed / 1000.0 / 1000.0; 355 in_jack += callback_interval - elapsed;
349 if (in_jack < 0) in_jack = 0; 356 if (in_jack < 0) in_jack = 0;
350 #endif 357 }
351 return (float)buffered / (float)ao_data.bps + in_jack; 358 return (float)buffered / (float)ao_data.bps + in_jack;
352 } 359 }
353 360