Mercurial > mplayer.hg
comparison libao2/ao_nas.c @ 7449:28785e6e6900
"One can cause a permanent hang on a seek, and the other just causes
general jerkiness because the writer thread was holding a lock
during the time it was writing to the network."
patch by Sidik Isani <lksi@cfht.hawaii.edu>
author | arpi |
---|---|
date | Fri, 20 Sep 2002 18:26:54 +0000 |
parents | 34d5c9a67b94 |
children | 09ccf6147d76 |
comparison
equal
deleted
inserted
replaced
7448:b464616d40b5 | 7449:28785e6e6900 |
---|---|
106 | 106 |
107 int flow_stopped; | 107 int flow_stopped; |
108 int flow_paused; | 108 int flow_paused; |
109 | 109 |
110 void *client_buffer; | 110 void *client_buffer; |
111 void *server_buffer; | |
111 int client_buffer_size; | 112 int client_buffer_size; |
112 int client_buffer_used; | 113 int client_buffer_used; |
113 int server_buffer_size; | 114 int server_buffer_size; |
114 int server_buffer_used; | 115 int server_buffer_used; |
115 pthread_mutex_t buffer_mutex; | 116 pthread_mutex_t buffer_mutex; |
146 return 0; | 147 return 0; |
147 } | 148 } |
148 if (nas_data->client_buffer_used < num) | 149 if (nas_data->client_buffer_used < num) |
149 num = nas_data->client_buffer_used; | 150 num = nas_data->client_buffer_used; |
150 | 151 |
151 AuWriteElement(nas_data->aud, nas_data->flow, 0, num, nas_data->client_buffer, AuFalse, &as); | 152 /* |
153 * It is not appropriate to call AuWriteElement() here because the | |
154 * buffer is locked and delays writing to the network will cause | |
155 * other threads to block waiting for buffer_mutex. Instead the | |
156 * data is copied to "server_buffer" and written it to the network | |
157 * outside of the locked section of code. | |
158 * | |
159 * (Note: Rather than these two buffers, a single circular buffer | |
160 * could eliminate the memcpy/memmove steps.) | |
161 */ | |
162 memcpy(nas_data->server_buffer, nas_data->client_buffer, num); | |
163 | |
164 nas_data->client_buffer_used -= num; | |
165 nas_data->server_buffer_used += num; | |
166 memmove(nas_data->client_buffer, nas_data->client_buffer + num, nas_data->client_buffer_used); | |
167 pthread_mutex_unlock(&nas_data->buffer_mutex); | |
168 | |
169 /* | |
170 * Now write the new buffer to the network. | |
171 */ | |
172 AuWriteElement(nas_data->aud, nas_data->flow, 0, num, nas_data->server_buffer, AuFalse, &as); | |
152 if (as != AuSuccess) | 173 if (as != AuSuccess) |
153 nas_print_error(nas_data->aud, "nas_readBuffer(): AuWriteElement", as); | 174 nas_print_error(nas_data->aud, "nas_readBuffer(): AuWriteElement", as); |
154 else { | |
155 nas_data->client_buffer_used -= num; | |
156 nas_data->server_buffer_used += num; | |
157 memmove(nas_data->client_buffer, nas_data->client_buffer + num, nas_data->client_buffer_used); | |
158 } | |
159 pthread_mutex_unlock(&nas_data->buffer_mutex); | |
160 | 175 |
161 if (nas_data->flow_paused) { | 176 if (nas_data->flow_paused) { |
162 AuPauseFlow(nas_data->aud, nas_data->flow, &as); | 177 AuPauseFlow(nas_data->aud, nas_data->flow, &as); |
163 if (as != AuSuccess) | 178 if (as != AuSuccess) |
164 nas_print_error(nas_data->aud, "nas_readBuffer(): AuPauseFlow", as); | 179 nas_print_error(nas_data->aud, "nas_readBuffer(): AuPauseFlow", as); |
331 } | 346 } |
332 | 347 |
333 nas_data->client_buffer_size = NAS_BUFFER_SIZE; | 348 nas_data->client_buffer_size = NAS_BUFFER_SIZE; |
334 nas_data->client_buffer = malloc(nas_data->client_buffer_size); | 349 nas_data->client_buffer = malloc(nas_data->client_buffer_size); |
335 nas_data->server_buffer_size = NAS_BUFFER_SIZE; | 350 nas_data->server_buffer_size = NAS_BUFFER_SIZE; |
351 nas_data->server_buffer = malloc(nas_data->server_buffer_size); | |
336 | 352 |
337 ao_data.samplerate = rate; | 353 ao_data.samplerate = rate; |
338 ao_data.channels = channels; | 354 ao_data.channels = channels; |
339 ao_data.buffersize = NAS_BUFFER_SIZE * 2; | 355 ao_data.buffersize = NAS_BUFFER_SIZE * 2; |
340 ao_data.outburst = NAS_FRAG_SIZE; | 356 ao_data.outburst = NAS_FRAG_SIZE; |
401 nas_print_error(nas_data->aud, "uninit(): AuStopFlow", as); | 417 nas_print_error(nas_data->aud, "uninit(): AuStopFlow", as); |
402 } | 418 } |
403 AuCloseServer(nas_data->aud); | 419 AuCloseServer(nas_data->aud); |
404 nas_data->aud = 0; | 420 nas_data->aud = 0; |
405 free(nas_data->client_buffer); | 421 free(nas_data->client_buffer); |
422 free(nas_data->server_buffer); | |
406 } | 423 } |
407 | 424 |
408 // stop playing and empty buffers (for seeking/pause) | 425 // stop playing and empty buffers (for seeking/pause) |
409 static void reset(){ | 426 static void reset(){ |
410 AuStatus as; | 427 AuStatus as; |
476 | 493 |
477 AuStartFlow(nas_data->aud, nas_data->flow, &as); | 494 AuStartFlow(nas_data->aud, nas_data->flow, &as); |
478 if (as != AuSuccess) | 495 if (as != AuSuccess) |
479 nas_print_error(nas_data->aud, "play(): AuStartFlow", as); | 496 nas_print_error(nas_data->aud, "play(): AuStartFlow", as); |
480 nas_data->flow_stopped = 0; | 497 nas_data->flow_stopped = 0; |
481 while (!nas_empty_event_queue(nas_data)); // wait for first buffer underrun event | 498 /* |
499 * Do not continue to wait if there is nothing in the server | |
500 * buffer. (The event never happens and mplayer can freeze.) | |
501 */ | |
502 while (nas_data->server_buffer_used > 0 && | |
503 !nas_empty_event_queue(nas_data)); // wait for first buffer underrun event | |
482 } | 504 } |
483 | 505 |
484 pthread_mutex_lock(&nas_data->buffer_mutex); | 506 pthread_mutex_lock(&nas_data->buffer_mutex); |
485 maxbursts = (nas_data->client_buffer_size - | 507 maxbursts = (nas_data->client_buffer_size - |
486 nas_data->client_buffer_used) / ao_data.outburst; | 508 nas_data->client_buffer_used) / ao_data.outburst; |