Andre Noll [Sat, 12 Sep 2009 16:16:56 +0000 (18:16 +0200)]
FEC timing improvements.
Currently we compute the time of a FEC group as the number of
containing chunks times the chunk time. The time between sending
two slices therefore depends only on the number of chunks the group
contains. Groups containing many slices are sent with larger delays
than groups containing few slices.
This approach is not optimal for the following reason: Consider a group
containing only few slices which is followed by a group containing
many slices. This happens frequently at the end of VBR MP3 files which
contain some seconds of silence or applause at the end because this
last part is often encoded at a lower bitrate than the preceding part.
In this scenario buffer underruns in the receiving application can
easily occur if the previous FEC group has been decoded and completely
fed to the writer before enough slices of the next group have arrived
to decode the second group.
This patch changes the timing of FEC groups such that all but the
first group use the duration of the _previous_ group as the basis
for the timing.
Andre Noll [Sat, 12 Sep 2009 16:13:36 +0000 (18:13 +0200)]
vss_send(): Fix EOF-check for FEC clients.
If the last chunk has been sent to all http/dccp clients we have
to wait until the last FEC group has been sent before setting the
NEXT flag that causes all senders to shut down its clients. The old
code tested if a slice was sent to any FEC client during vss_send()
and set the NEXT flag if nothing was sent.
However, this is not sufficient as there may be still slices available
which have to be sent at some future time. This patch teaches
vss_send() to detect this condition. It also renames the boolean
variable sent_something to fec_active, which is more to the point.
Andre Noll [Sun, 6 Sep 2009 20:19:31 +0000 (22:19 +0200)]
filter: Register the filter chain as the last task.
Without this patch, the command
para_filter -f mp3dec < foo.mp3 > /dev/null
would take several minutes because the stdin buffer is usually full and the stdout buffer empty
which causes select() to be called with empty fd sets, resulting in a one second timeout.
Andre Noll [Mon, 31 Aug 2009 19:17:21 +0000 (21:17 +0200)]
mp3dec: Improve bad main_data_begin pointer error handling.
These errors from mad_frame_decode() are non-fatal and happen if the
stream is started at the middle of the file, e.g. when para_audiod
is started while para_server is already streaming.
If libmad encounters such an error it throws away the first (and
probably the second) frame which messes up the timing in udp/fec mode,
causing an audible buffer underrun after the remaining frames of the
first fec group have been decoded and fed to the writer.
This patch makes the mp3dec filter keep track of bad main_data_begin
pointer errors that happen at the start of the stream. In this case
decoding is deferred until more data has arrived or 60ms have passed.
Andre Noll [Sat, 29 Aug 2009 20:17:55 +0000 (22:17 +0200)]
Alsa timing improvements.
This moves the computation of the select timeout from
alsa_write_post_select() to alsa_write_pre_select(). The code now
computes when the next buffer underrun would occur and uses that
value to set the timeout for the next select call. This decreases
the number of writes to the alsa handle and therefore also the CPU
usage of para_write/para_audiod.
Andre Noll [Sat, 11 Jul 2009 19:01:27 +0000 (21:01 +0200)]
Fix com_init() in case arguments are given.
As the ->name field of struct afs_table was only initialized in the afs process,
com_init(), which gets forked from the server process, did not see the table
names and would segfault due to a NULL pointer dereference if table names
were given as arguments.
Fix it by initializing the ->name fields in the definition of the afs_tables array.
This bug was introduced in commit 53d503ce back in 2007...
Andre Noll [Sun, 5 Jul 2009 08:40:55 +0000 (10:40 +0200)]
Fix a bug in the output of para_audioc.
This bites In case of short writes to stdout. The bug was literally there since day one
but never showed up as short writes usually don't happen with the rather small amount
of data that is written by para_audioc.
Gerrit Renker [Tue, 30 Jun 2009 08:20:19 +0000 (10:20 +0200)]
Support netmask subsets
This allows to specify sets of addresses which are defined by sharing
the least-common netmask value.
For example, if the allow list contains the following addresses:
10.0.0.2/24 10.0.0.2/32
then the second address is redundant since it is already included
via the first one. The least-common netmask value is 24; with this
patch a command like
Andre Noll [Wed, 27 May 2009 17:16:54 +0000 (19:16 +0200)]
Truncate overlong tag info and replace newlines by spaces.
The tag info which is computed by the audio format handlers and stored
in the audio file table is read into a fixed-size buffer by the audio
file selector in open_and_update_audio_file(), passed to the server
process and then sent to the client via the stat command. It is not
interpreted at all during this process. In particular, it is not
essential for correctly streaming the audio file.
Vorbis comments and id3v2 tags have no size limit and may contain
arbitrary data which may lead to the following twi problems:
- As noted by Gerrit Renker, if the tag info is too long
to fit into the fixed-size buffer, the current code skips
the audio file and removes it from the list of currently
admissible files. So para_server fails to stream such files.
- If the tag info contains newlines, these are included
verbatim in the status output which may confuse para_audiod.
This patch truncates the tag info string if it does not fit into the
4K buffer and replaces newlines by spaces. This is a bit ugly but
avoids both of the above problems. It's still possible to retrieve
the complete tag info via the "ls -lv" command.
Andre Noll [Sun, 10 May 2009 19:31:13 +0000 (21:31 +0200)]
rbtree: Add const qualifier to some functions.
The 'rb_first()', 'rb_last()', 'rb_next()' and 'rb_prev()' calls take a pointer
to an RB node or RB root. They do not change the pointed objects, so add a
'const' qualifier.
Andre Noll [Sun, 10 May 2009 15:40:42 +0000 (17:40 +0200)]
filter: Force a minimal select timeout if something was converted.
When filter_preselect() runs. other pre_select functions might have
already been called and decided to do nothing, e.g. because their
output buffer was full or the input buffer was empty.
If this call to filter_preselect() changed any of the involved buffers,
we want those other pre_select() functions to be called ASAP. So force
a minimal timeout for the next select call to avoid unnecessary delays.
Andre Noll [Sun, 10 May 2009 13:28:13 +0000 (15:28 +0200)]
mp3dec: Try harder to recover from non-fatal errors.
If there's still data left, try to decode the next header in the
same scheduler run. This avoids unnecessary copies of large parts
of the mp3 input buffer.
Andre Noll [Sun, 10 May 2009 12:11:38 +0000 (14:11 +0200)]
audiod: Properly handle wng open failures.
If opening the writer node group fails, no task is being registered to the
scheduler although a task structure is allocated. This makes audiod think
everything is fine until the output buffer of the receiver or a filter is
filled up which may take several seconds.
Fix this flaw by setting the error field of the wng to -E_TASK_UNREGISTERED.
This causes audiod to close the receiver node and the filter chain and to
clear the affected slot.
Andre Noll [Mon, 4 May 2009 11:34:16 +0000 (13:34 +0200)]
Fix compilation on FreeBSD.
Without these two includes, compilation fails on FreeBSD with
/usr/include/net/if.h:265: error: field `ifru_addr' has incomplete type
/usr/include/net/if.h:266: error: field `ifru_dstaddr' has incomplete type
/usr/include/net/if.h:267: error: field `ifru_broadaddr' has incomplete type
/usr/include/net/if.h:299: error: field `ifra_addr' has incomplete type
/usr/include/net/if.h:300: error: field `ifra_broadaddr' has incomplete type
/usr/include/net/if.h:301: error: field `ifra_mask' has incomplete type
/usr/include/net/if.h:368: error: field `addr' has incomplete type
/usr/include/net/if.h:369: error: field `dstaddr' has incomplete type
Andre Noll [Mon, 4 May 2009 11:12:17 +0000 (13:12 +0200)]
Fix two gcc warnings.
mp3_afh.c:420: warning: comparison of distinct pointer types lacks a cast
alsa_write.c:119: warning: format '%zu' expects type 'size_t', but argument 4 has type 'int'
Andre Noll [Sun, 3 May 2009 16:11:22 +0000 (18:11 +0200)]
Alsa fixes and cleanups.
This patch
- replaces the unused E_SND_PCM_INFO error by E_PHYSICAL_WIDTH,
- checks the return value of snd_pcm_format_physical_width() and returns
-E_PHYSICAL_WIDTH if this causes bytes_per_frame being non-positive,
- introduces an upper bound for the start threshold. Without that
change, playback could be delayed by several seconds on some alsa
configurations (problem pointed out by Johannes Wörner, thanks).
- does not return early on input errors which could cause the last
part of the audio stream being skipped.
- avoids calling snd_pcm_writei() with a frame count of zero which
could happen with the old code in case there's more than zero but
less than a full frame of audio data available.
- cleans up the documentation of struct private_alsa_write_data
Currently, filters must not change their output buffer on the fly
because the writer might already have a reference to the old buffer
and keeps using this buffer.
As dealing with changing output buffers requires much more work,
including changes to the generic filter and writer code, let's defer
this change to post 0.3.4.
Andre Noll [Sun, 26 Apr 2009 17:45:59 +0000 (19:45 +0200)]
Avoid dirty afs tables on shutdown.
The server process must wait for afs because afs catches SIGINT/SIGTERM
and may thus not respond immediately to these SIGNALS.
Before reacting to the signal, afs might want to use the shared memory
area and the mmd mutex. If the server process destroys this mutex
too early and afs tries to lock the shared memory area, the call to
mutex_lock() will fail and terminate the afs process. This leads to
dirty osl tables.
There's no such problem with the other children of the server process
(the command handlers) as these reset their SIGINT/SIGTERM handlers
to the default action, i.e. these processes get killed immediately
by the above kill().
Andre Noll [Sun, 26 Apr 2009 16:08:13 +0000 (18:08 +0200)]
Fix an invalid free() in command handlers.
The chunk table and the info_string are pointers located in the mmd
struct that point to dynamically allocated memory that must be freed
by the parent and the child. However, as the mmd struct is in a shared
memory area, there's no guarantee that after the fork these pointers
are still valid in child context. As these two pointers are not used
in the child anyway, we save them to local variables and free the
memory via that copy in the child.
Andre Noll [Sat, 25 Apr 2009 13:17:58 +0000 (15:17 +0200)]
[net]: Fix buffer overflow in send_cred_buffer().
As pointed out by Johannes Wörner, para_audioc crashes on recent
Ubuntu systems due to stack smashing. This is caused by writing past
the end of the control buffer which stores the message header and
the socket credentials.
This patch fixes the bug by allocating a properly sized buffer.
Andre Noll [Thu, 23 Apr 2009 15:18:03 +0000 (17:18 +0200)]
[udp_send] Refuse to stream files with invalid chunk tables.
If an audio file contains a chunk so large that even the maximal
possible number of slices is not sufficient to put this chunk into
a single FEC group, we must refuse to send this file. It's likely a
corrupt file anyway.
The old code in num_slices() was buggy as it returned the number of
slices needed to send the file as an uint8_t, so the return value
was actually the number of needed slices mod 256. This could trigger
the assert() in setup_next_fec_group() which checks that the group
contains at least one chunk.
This patch changes num_slices() to detect this situation more
reliably. As it is likely caused by a bad audio file rather than by a
networking problem, we do _not_ kick the fec client, but deactivate
it for the current file only. This requires the new "error" member
of struct fec_client which indicates a temporarily disabled fec client.
Andre Noll [Thu, 23 Apr 2009 11:39:04 +0000 (13:39 +0200)]
[mp3_afh]: Ignore junk at the end of an mp3 file.
There are mp3 files containing large areas of zeros at the end of the
file. The old code in mp3_afh.c would include these zeros in the last
chunk of the file.
This leads to unnecessary network traffic as including this area in
a chunk means that useless data is going to be sent to the client.
More importantly, it causes the udp sender to bail out because such
large chunks can not be fec-encoded, even with the maximal number
of slices.
This patch uses frame_start+frame_length instead of the file size as
the end of the last chunk which avoids this particular problem.