From 13bc07587564977a64222f5a4075b7fa63ac5548 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Mon, 26 May 2008 23:43:51 +0000 Subject: [PATCH] A few related changes: * Change the encode_sample routine to simply return normal memchunks allocated from the mempool. * unref the memchunks returned from encode_sample when we are done with them. * Create an encoded 'silence' sample and play this at all times to prevent hangup and to 'hog' the airtunes device This now works and can be used as a regular sink albeit with a constant latency of about 8 seconds :s git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/coling@2485 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-raop-sink.c | 79 +++++++++++++++++++++++++++++++----------- src/modules/rtp/raop_client.c | 16 +-------- 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/src/modules/module-raop-sink.c b/src/modules/module-raop-sink.c index 42092e0..f78abba 100644 --- a/src/modules/module-raop-sink.c +++ b/src/modules/module-raop-sink.c @@ -178,7 +178,8 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); pollfd->fd = u->fd; - pollfd->events = pollfd->revents = 0; + pollfd->events = POLLOUT; + pollfd->revents = 0; return 0; } @@ -190,6 +191,9 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse static void thread_func(void *userdata) { struct userdata *u = userdata; int write_type = 0; + pa_memchunk silence; + uint32_t silence_overhead; + double silence_ratio; pa_assert(u); @@ -200,6 +204,9 @@ static void thread_func(void *userdata) { pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec()); + /* Create a chunk of memory that is our encoded silence sample. */ + pa_memchunk_reset(&silence); + for (;;) { int ret; @@ -208,33 +215,61 @@ static void thread_func(void *userdata) { pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); /* Render some data and write it to the fifo */ - if (PA_SINK_OPENED(u->sink->thread_info.state) && pollfd->revents) { + if (pollfd->revents) { pa_usec_t usec; int64_t n; + void *p; + + if (!silence.memblock) { + pa_memchunk silence_tmp; + + pa_memchunk_reset(&silence_tmp); + silence_tmp.memblock = pa_memblock_new(u->core->mempool, 4096); + silence_tmp.length = 4096; + p = pa_memblock_acquire(silence_tmp.memblock); + memset(p, 0, 4096); + pa_memblock_release(silence_tmp.memblock); + pa_raop_client_encode_sample(u->raop, &silence_tmp, &silence); + pa_assert(0 == silence_tmp.length); + silence_overhead = silence_tmp.length - 4096; + silence_ratio = silence_tmp.length / 4096; + pa_memblock_unref(silence_tmp.memblock); + } for (;;) { ssize_t l; - void *p; if (u->encoded_memchunk.length <= 0) { - if (u->raw_memchunk.length <= 0) { - if (u->raw_memchunk.memblock) - pa_memblock_unref(u->raw_memchunk.memblock); - pa_memchunk_reset(&u->raw_memchunk); - - /* Grab unencoded data */ - pa_sink_render(u->sink, u->block_size, &u->raw_memchunk); - p = pa_memblock_acquire(u->raw_memchunk.memblock); - pa_memblock_release(u->raw_memchunk.memblock); + if (u->encoded_memchunk.memblock) + pa_memblock_unref(u->encoded_memchunk.memblock); + if (PA_SINK_OPENED(u->sink->thread_info.state)) { + size_t rl; + + /* We render real data */ + if (u->raw_memchunk.length <= 0) { + if (u->raw_memchunk.memblock) + pa_memblock_unref(u->raw_memchunk.memblock); + pa_memchunk_reset(&u->raw_memchunk); + + /* Grab unencoded data */ + pa_sink_render(u->sink, u->block_size, &u->raw_memchunk); + } + pa_assert(u->raw_memchunk.length > 0); + + /* Encode it */ + rl = u->raw_memchunk.length; + u->encoding_overhead += u->next_encoding_overhead; + pa_raop_client_encode_sample(u->raop, &u->raw_memchunk, &u->encoded_memchunk); + u->next_encoding_overhead = (u->encoded_memchunk.length - (rl - u->raw_memchunk.length)); + u->encoding_ratio = u->encoded_memchunk.length / (rl - u->raw_memchunk.length); + } else { + /* We render some silence into our memchunk */ + u->encoding_overhead += u->next_encoding_overhead; + memcpy(&u->encoded_memchunk, &silence, sizeof(pa_memchunk)); + pa_memblock_ref(silence.memblock); + u->next_encoding_overhead = silence_overhead; + u->encoding_ratio = silence_ratio; } - pa_assert(u->raw_memchunk.length > 0); - - /* Encode it */ - size_t rl = u->raw_memchunk.length; - u->encoding_overhead += u->next_encoding_overhead; - pa_raop_client_encode_sample(u->raop, &u->raw_memchunk, &u->encoded_memchunk); - u->next_encoding_overhead = (u->encoded_memchunk.length - (rl - u->raw_memchunk.length)); - u->encoding_ratio = u->encoded_memchunk.length / (rl - u->raw_memchunk.length); } pa_assert(u->encoded_memchunk.length > 0); @@ -303,7 +338,7 @@ static void thread_func(void *userdata) { } /* Hmm, nothing to do. Let's sleep */ - pollfd->events = PA_SINK_OPENED(u->sink->thread_info.state) ? POLLOUT : 0; + /* pollfd->events = PA_SINK_OPENED(u->sink->thread_info.state) ? POLLOUT : 0; */ } if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) @@ -331,6 +366,8 @@ fail: pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); finish: + if (silence.memblock) + pa_memblock_unref(silence.memblock); pa_log_debug("Thread shutting down"); } diff --git a/src/modules/rtp/raop_client.c b/src/modules/rtp/raop_client.c index 7ba1be7..4085a49 100644 --- a/src/modules/rtp/raop_client.c +++ b/src/modules/rtp/raop_client.c @@ -94,12 +94,6 @@ struct pa_raop_client { void* userdata; pa_raop_client_closed_cb_t closed_callback; void* closed_userdata; - - uint8_t *buffer; - pa_memblock *memblock; - size_t buffer_length; - uint8_t *buffer_index; - uint16_t buffer_count; }; /** @@ -402,7 +396,6 @@ void pa_raop_client_free(pa_raop_client* c) { pa_assert(c); - pa_xfree(c->buffer); if (c->rtsp) pa_rtsp_client_free(c->rtsp); pa_xfree(c->host); @@ -443,15 +436,8 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun /* Leave 16 bytes extra to allow for the ALAC header which is about 55 bits */ bufmax = length + header_size + 16; - if (bufmax > c->buffer_length) { - c->buffer = pa_xrealloc(c->buffer, bufmax); - c->buffer_length = bufmax; - if (c->memblock) - pa_memblock_unref(c->memblock); - c->memblock = pa_memblock_new_user(c->core->mempool, c->buffer, bufmax, noop, 0); - } pa_memchunk_reset(encoded); - encoded->memblock = c->memblock; + encoded->memblock = pa_memblock_new(c->core->mempool, bufmax); b = pa_memblock_acquire(encoded->memblock); memcpy(b, header, header_size); -- 2.7.4