summaryrefslogtreecommitdiffstats
path: root/libao2
diff options
context:
space:
mode:
authorarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-09-20 18:26:54 +0000
committerarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-09-20 18:26:54 +0000
commit8680f58f89802303bace6f20bce35aba2e8b78ec (patch)
tree1443f5b8d379c3638c162c6969ccaf1856b15deb /libao2
parent10bdbae17123f4747d925f3823bb11cc677c4999 (diff)
downloadmpv-8680f58f89802303bace6f20bce35aba2e8b78ec.tar.bz2
mpv-8680f58f89802303bace6f20bce35aba2e8b78ec.tar.xz
"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> git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7450 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libao2')
-rw-r--r--libao2/ao_nas.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/libao2/ao_nas.c b/libao2/ao_nas.c
index 7a37ee82c8..aa95ab6655 100644
--- a/libao2/ao_nas.c
+++ b/libao2/ao_nas.c
@@ -108,6 +108,7 @@ struct ao_nas_data {
int flow_paused;
void *client_buffer;
+ void *server_buffer;
int client_buffer_size;
int client_buffer_used;
int server_buffer_size;
@@ -148,15 +149,29 @@ static int nas_readBuffer(struct ao_nas_data *nas_data, int num)
if (nas_data->client_buffer_used < num)
num = nas_data->client_buffer_used;
- AuWriteElement(nas_data->aud, nas_data->flow, 0, num, nas_data->client_buffer, AuFalse, &as);
+ /*
+ * It is not appropriate to call AuWriteElement() here because the
+ * buffer is locked and delays writing to the network will cause
+ * other threads to block waiting for buffer_mutex. Instead the
+ * data is copied to "server_buffer" and written it to the network
+ * outside of the locked section of code.
+ *
+ * (Note: Rather than these two buffers, a single circular buffer
+ * could eliminate the memcpy/memmove steps.)
+ */
+ memcpy(nas_data->server_buffer, nas_data->client_buffer, num);
+
+ nas_data->client_buffer_used -= num;
+ nas_data->server_buffer_used += num;
+ memmove(nas_data->client_buffer, nas_data->client_buffer + num, nas_data->client_buffer_used);
+ pthread_mutex_unlock(&nas_data->buffer_mutex);
+
+ /*
+ * Now write the new buffer to the network.
+ */
+ AuWriteElement(nas_data->aud, nas_data->flow, 0, num, nas_data->server_buffer, AuFalse, &as);
if (as != AuSuccess)
nas_print_error(nas_data->aud, "nas_readBuffer(): AuWriteElement", as);
- else {
- nas_data->client_buffer_used -= num;
- nas_data->server_buffer_used += num;
- memmove(nas_data->client_buffer, nas_data->client_buffer + num, nas_data->client_buffer_used);
- }
- pthread_mutex_unlock(&nas_data->buffer_mutex);
if (nas_data->flow_paused) {
AuPauseFlow(nas_data->aud, nas_data->flow, &as);
@@ -333,6 +348,7 @@ static int init(int rate,int channels,int format,int flags)
nas_data->client_buffer_size = NAS_BUFFER_SIZE;
nas_data->client_buffer = malloc(nas_data->client_buffer_size);
nas_data->server_buffer_size = NAS_BUFFER_SIZE;
+ nas_data->server_buffer = malloc(nas_data->server_buffer_size);
ao_data.samplerate = rate;
ao_data.channels = channels;
@@ -403,6 +419,7 @@ static void uninit(){
AuCloseServer(nas_data->aud);
nas_data->aud = 0;
free(nas_data->client_buffer);
+ free(nas_data->server_buffer);
}
// stop playing and empty buffers (for seeking/pause)
@@ -478,7 +495,12 @@ static int play(void* data,int len,int flags)
if (as != AuSuccess)
nas_print_error(nas_data->aud, "play(): AuStartFlow", as);
nas_data->flow_stopped = 0;
- while (!nas_empty_event_queue(nas_data)); // wait for first buffer underrun event
+ /*
+ * Do not continue to wait if there is nothing in the server
+ * buffer. (The event never happens and mplayer can freeze.)
+ */
+ while (nas_data->server_buffer_used > 0 &&
+ !nas_empty_event_queue(nas_data)); // wait for first buffer underrun event
}
pthread_mutex_lock(&nas_data->buffer_mutex);