From: Torsten J. <t....@gm...> - 2017-05-18 18:41:04
|
# HG changeset patch # User Torsten Jager <t....@gm...> # Date 1495132830 -7200 # Node ID a04e8a09fc52c82449a8a963587cdb0eacb68d95 # Branch default # Parent b5bda796645ad02695bf639e7dc5c80a74597f17 Optimize audio out. - Embed buffer fifo's. - 2 less mutex call pairs per frame. - Turn off useless signals. - Flush faster and without dummy buffer. - Faster stream register. - Less memory fragmentation. - Memory allocation fail tests. - Reuse buffer stream refs. Again, 2 less pairs mostly. - Dont busy wait when grabbing frames manually. - Fix audio only stream time/pos info. - Simplify. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,7 @@ * Minor ffmpeg optimization. * Lift a few video engine handbrakes. Less CPU load, fewer frame drops, faster seeking. + * Optimize audio engine. * Optimize metronom clock. * Optimize sse/mmx2 memcpy. * Update german translation. --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -123,7 +123,7 @@ * errors < 1% nominal rate. For bigger errors (bad streams) audio * buffers may be dropped or gaps filled with silence. */ -#define SYNC_TIME_INVERVAL (1 * 90000) +#define SYNC_TIME_INTERVAL (1 * 90000) #define SYNC_BUF_INTERVAL NUM_AUDIO_BUFFERS / 2 #define SYNC_GAP_RATE 4 @@ -198,6 +198,18 @@ { EQ_REAL(2.4201241845e-01), EQ_REAL(3.7899379077e-01), EQ_REAL(-8.0847117831e-01) }, }; +struct audio_fifo_s { + audio_buffer_t *first; + audio_buffer_t *last; + + pthread_mutex_t mutex; + pthread_cond_t not_empty; + pthread_cond_t empty; + + int num_buffers; + int num_buffers_max; +}; + typedef struct { xine_audio_port_t ao; /* public part */ @@ -223,7 +235,12 @@ metronom_clock_t *clock; xine_t *xine; - xine_list_t *streams; + + int num_null_streams; + int num_anon_streams; + int num_streams; + int streams_size; + xine_stream_t **streams; pthread_mutex_t streams_lock; pthread_t audio_thread; @@ -245,8 +262,10 @@ int resample_conf; uint32_t force_rate; /* force audio output rate to this value if non-zero */ - audio_fifo_t *free_fifo; - audio_fifo_t *out_fifo; + + audio_fifo_t free_fifo; + audio_fifo_t out_fifo; + int64_t last_audio_vpts; pthread_mutex_t current_speed_lock; uint32_t current_speed; /* the current playback speed */ @@ -259,8 +278,6 @@ int64_t passthrough_offset; int flush_audio_driver; int discard_buffers; - pthread_mutex_t flush_audio_driver_lock; - pthread_cond_t flush_audio_driver_reached; int dropped; int step; @@ -285,152 +302,270 @@ int last_gap; + xine_stream_t *buf_streams[NUM_AUDIO_BUFFERS]; + audio_buffer_t *base_buf; + extra_info_t *base_ei; + uint8_t *base_samp; + + /* extra info ring buffer */ +#define EI_RING_SIZE 32 /* 2^n please */ + int ei_write; + int ei_read; + } aos_t; -struct audio_fifo_s { - audio_buffer_t *first; - audio_buffer_t *last; - - pthread_mutex_t mutex; - pthread_cond_t not_empty; - pthread_cond_t empty; - - int num_buffers; - int num_buffers_max; -}; - -static int ao_get_property (xine_audio_port_t *this_gen, int property); static int ao_set_property (xine_audio_port_t *this_gen, int property, int value); -static audio_fifo_t *XINE_MALLOC fifo_new (xine_t *xine) { - - audio_fifo_t *fifo; - - fifo = (audio_fifo_t *) calloc(1, sizeof(audio_fifo_t)); - - if (!fifo) - return NULL; - +/******************************************************************** + * streams register. * + * Reading is way more speed relevant here. * + *******************************************************************/ + +static int ao_streams_open (aos_t *this) { + this->num_null_streams = 0; + this->num_anon_streams = 0; + this->num_streams = 0; + this->streams_size = 32; + pthread_mutex_init (&this->streams_lock, NULL); + this->streams = calloc (32, sizeof (void *)); + return !!this->streams; +} + +static void ao_streams_close (aos_t *this) { + pthread_mutex_destroy (&this->streams_lock); + free (this->streams); + this->streams = NULL; + this->num_null_streams = 0; + this->num_anon_streams = 0; [... 1148 lines omitted ...] break; } } @@ -2163,6 +2234,7 @@ config_values_t *config = xine->config; aos_t *this; + uint8_t *vsbuf0, *vsbuf1; int i, err; pthread_attr_t pth_attrs; pthread_mutexattr_t attr; @@ -2170,12 +2242,32 @@ static const char *const av_sync_methods[] = {"metronom feedback", "resample", NULL}; this = calloc(1, sizeof(aos_t)) ; + if (!this) + return NULL; this->driver = driver; this->xine = xine; this->clock = xine->clock; this->current_speed = xine->clock->speed; - this->streams = xine_list_new(); + if (!ao_streams_open (this)) { + free (this); + return NULL; + } + + this->base_buf = calloc (NUM_AUDIO_BUFFERS + 2, sizeof (audio_buffer_t)); + this->base_ei = calloc (EI_RING_SIZE + NUM_AUDIO_BUFFERS + 2, sizeof (extra_info_t)); + this->base_samp = xine_mallocz_aligned (NUM_AUDIO_BUFFERS * AUDIO_BUF_SIZE); + vsbuf0 = calloc (1, 4 * AUDIO_BUF_SIZE); + vsbuf1 = calloc (1, 4 * AUDIO_BUF_SIZE); + if (!this->base_buf || !this->base_ei || !this->base_samp || !vsbuf0 || !vsbuf1) { + free (this->base_buf); + free (this->base_ei); + xine_free_aligned (this->base_samp); + free (vsbuf0); + free (vsbuf1); + free (this); + return NULL; + } /* warning: driver_lock is a recursive mutex. it must NOT be * used with neither pthread_cond_wait() or pthread_cond_timedwait() @@ -2183,7 +2275,6 @@ pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); - pthread_mutex_init( &this->streams_lock, NULL ); pthread_mutex_init( &this->driver_lock, &attr ); pthread_mutex_init( &this->driver_action_lock, NULL ); pthread_cond_init( &this->driver_action_cond, NULL ); @@ -2208,8 +2299,6 @@ this->zero_space = calloc (1, ZERO_BUF_SIZE * 4 * 6); /* MAX as 32bit, 6 channels. */ pthread_mutex_init( &this->current_speed_lock, NULL ); - pthread_mutex_init( &this->flush_audio_driver_lock, NULL ); - pthread_cond_init( &this->flush_audio_driver_reached, NULL ); this->step = 0; pthread_mutex_init (&this->step_mutex, NULL); @@ -2314,36 +2403,39 @@ * pre-allocate memory for samples */ - this->free_fifo = fifo_new (this->xine); - this->out_fifo = fifo_new (this->xine); - - for (i=0; i<NUM_AUDIO_BUFFERS; i++) { - - audio_buffer_t *buf; - - buf = (audio_buffer_t *) calloc(1, sizeof(audio_buffer_t)); - buf->mem = calloc (1, AUDIO_BUF_SIZE); - buf->mem_size = AUDIO_BUF_SIZE; - buf->extra_info = malloc(sizeof(extra_info_t)); - - fifo_append (this->free_fifo, buf); + ao_fifo_open (&this->free_fifo); + ao_fifo_open (&this->out_fifo); + + { + audio_buffer_t *buf = this->base_buf; + extra_info_t *ei = this->base_ei + EI_RING_SIZE; + uint8_t *mem = this->base_samp; + + for (i = 0; i < NUM_AUDIO_BUFFERS; i++) { + buf->mem = (int16_t *)mem; + buf->mem_size = AUDIO_BUF_SIZE; + buf->extra_info = ei; + ao_fifo_append_int (&this->free_fifo, buf); + buf++; + ei++; + mem += AUDIO_BUF_SIZE; + } + + /* buffers used for audio conversions. need to be resizable */ + buf->mem = (int16_t *)vsbuf0; + buf->mem_size = 4 *AUDIO_BUF_SIZE; + buf->extra_info = ei; + this->frame_buf[0] = buf; + buf++; + ei++; + buf->mem = (int16_t *)vsbuf1; + buf->mem_size = 4 *AUDIO_BUF_SIZE; + buf->extra_info = ei; + this->frame_buf[1] = buf; } memset (this->last_sample, 0, sizeof (this->last_sample)); - /* buffers used for audio conversions */ - for (i=0; i<2; i++) { - - audio_buffer_t *buf; - - buf = (audio_buffer_t *) calloc(1, sizeof(audio_buffer_t)); - buf->mem = calloc(4, AUDIO_BUF_SIZE); - buf->mem_size = 4*AUDIO_BUF_SIZE; - buf->extra_info = malloc(sizeof(extra_info_t)); - - this->frame_buf[i] = buf; - } - /* * Set audio volume to latest used one ? */ |