From 81fbe8ca719feb4e02b826bee0a779401a785e3f Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Sat, 2 Dec 2006 22:35:18 +0000 Subject: two fixes to viz glue code: - avoid overrunning the provided input audio buffer. - generate a bad frame if time is due but we don't have enough data for updating the viz plugin. this could happen in some rare situations but the result was pretty catastrophic: xine froze with 100% cpu usage. CVS patchset: 8400 CVS date: 2006/12/02 22:35:18 --- src/post/goom/xine_goom.c | 30 +++++++++++++++++++----------- src/post/visualizations/fftgraph.c | 22 +++++++++++++++------- src/post/visualizations/fftscope.c | 22 +++++++++++++++------- src/post/visualizations/fooviz.c | 22 +++++++++++++++------- src/post/visualizations/oscope.c | 22 +++++++++++++++------- 5 files changed, 79 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/post/goom/xine_goom.c b/src/post/goom/xine_goom.c index f879f1ebc..e4f55068b 100644 --- a/src/post/goom/xine_goom.c +++ b/src/post/goom/xine_goom.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_goom.c,v 1.63 2006/10/23 21:13:44 hadess Exp $ + * $Id: xine_goom.c,v 1.64 2006/12/02 22:35:18 miguelfreitas Exp $ * * GOOM post plugin. * @@ -43,7 +43,7 @@ #include "goom.h" -#define NUMSAMPLES 512 +#define NUMSAMPLES 512 /* hardcoded into goom api */ #define FPS 14 #define GOOM_WIDTH 320 @@ -83,7 +83,7 @@ struct post_plugin_goom_s { PluginInfo *goom; int data_idx; - gint16 data [2][512]; + gint16 data [2][NUMSAMPLES]; audio_buffer_t buf; /* dummy buffer just to hold a copy of audio data */ int channels; @@ -386,6 +386,7 @@ static int goom_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, this->sample_rate = rate; this->samples_per_frame = rate / this->fps; this->data_idx = 0; + this->sample_counter = 0; init_yuv_planes(&this->yuv, this->width, this->height); this->skip_frame = 0; @@ -445,7 +446,6 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, buf = &this->buf; this->sample_counter += buf->num_frames; - j = (this->channels >= 2) ? 1 : 0; do { @@ -455,7 +455,7 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, data8 += samples_used * this->channels; /* scale 8 bit data to 16 bits and convert to signed as well */ - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data8 += this->channels ) { this->data[0][this->data_idx] = ((int16_t)data8[0] << 8) - 0x8000; this->data[1][this->data_idx] = ((int16_t)data8[j] << 8) - 0x8000; @@ -464,16 +464,15 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, data = buf->mem; data += samples_used * this->channels; - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data += this->channels ) { this->data[0][this->data_idx] = data[0]; this->data[1][this->data_idx] = data[j]; } } - if( this->sample_counter >= this->samples_per_frame && - this->data_idx == NUMSAMPLES ) { - this->data_idx = 0; + if( this->sample_counter >= this->samples_per_frame ) { + samples_used += this->samples_per_frame; frame = this->vo_port->get_frame (this->vo_port, this->width_back, this->height_back, @@ -481,14 +480,23 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, VO_BOTH_FIELDS); frame->extra_info->invalid = 1; - frame->bad_frame = 0; + + /* frame is marked as bad if we don't have enough samples for + * updating the viz plugin (calculations may be skipped). + * we must keep the framerate though. */ + if( this->data_idx == NUMSAMPLES ) { + frame->bad_frame = 0; + this->data_idx = 0; + } else { + frame->bad_frame = 1; + } frame->duration = 90000 * this->samples_per_frame / this->sample_rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); this->sample_counter -= this->samples_per_frame; - if (!this->skip_frame) { + if (!this->skip_frame && !frame->bad_frame) { /* Try to be fast */ goom_frame = (uint8_t *)goom_update (this->goom, this->data, 0, 0, NULL, NULL); diff --git a/src/post/visualizations/fftgraph.c b/src/post/visualizations/fftgraph.c index f9f8f0d4a..669a4bc94 100644 --- a/src/post/visualizations/fftgraph.c +++ b/src/post/visualizations/fftgraph.c @@ -20,7 +20,7 @@ * FftGraph Visualization Post Plugin For xine * by Thibaut Mattern (tmattern@noos.fr) * - * $Id: fftgraph.c,v 1.14 2006/01/27 07:46:14 tmattern Exp $ + * $Id: fftgraph.c,v 1.15 2006/12/02 22:35:18 miguelfreitas Exp $ * */ @@ -230,6 +230,7 @@ static int fftgraph_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream this->lines_per_channel = FFTGRAPH_HEIGHT / this->channels; this->samples_per_frame = rate / FPS; this->data_idx = 0; + this->sample_counter = 0; this->vo_port->open(this->vo_port, XINE_ANON_STREAM); this->metronom->set_master(this->metronom, stream->metronom); @@ -342,7 +343,7 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen, data8 += samples_used * this->channels; /* scale 8 bit data to 16 bits and convert to signed as well */ - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data8 += this->channels ) { for( c = 0; c < this->channels; c++){ this->wave[c][this->data_idx].re = (double)(data8[c] << 8) - 0x8000; @@ -353,7 +354,7 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen, data = buf->mem; data += samples_used * this->channels; - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data += this->channels ) { for( c = 0; c < this->channels; c++){ this->wave[c][this->data_idx].re = (double)data[c]; @@ -362,17 +363,24 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen, } } - if( this->sample_counter >= this->samples_per_frame && - this->data_idx == NUMSAMPLES ) { + if( this->sample_counter >= this->samples_per_frame ) { - this->data_idx = 0; samples_used += this->samples_per_frame; frame = this->vo_port->get_frame (this->vo_port, FFTGRAPH_WIDTH, FFTGRAPH_HEIGHT, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); frame->extra_info->invalid = 1; - frame->bad_frame = 0; + + /* frame is marked as bad if we don't have enough samples for + * updating the viz plugin (calculations may be skipped). + * we must keep the framerate though. */ + if( this->data_idx == NUMSAMPLES ) { + frame->bad_frame = 0; + this->data_idx = 0; + } else { + frame->bad_frame = 1; + } frame->duration = 90000 * this->samples_per_frame / port->rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); diff --git a/src/post/visualizations/fftscope.c b/src/post/visualizations/fftscope.c index 8448f3a65..aef517c59 100644 --- a/src/post/visualizations/fftscope.c +++ b/src/post/visualizations/fftscope.c @@ -22,7 +22,7 @@ * * FFT code by Steve Haehnichen, originally licensed under GPL v1 * - * $Id: fftscope.c,v 1.29 2006/01/27 07:46:14 tmattern Exp $ + * $Id: fftscope.c,v 1.30 2006/12/02 22:35:18 miguelfreitas Exp $ * */ @@ -289,6 +289,7 @@ static int fftscope_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream this->channels = MAXCHANNELS; this->samples_per_frame = rate / FPS; this->data_idx = 0; + this->sample_counter = 0; this->fft = fft_new(FFT_BITS); this->vo_port->open(this->vo_port, XINE_ANON_STREAM); @@ -363,7 +364,7 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen, data8 += samples_used * this->channels; /* scale 8 bit data to 16 bits and convert to signed as well */ - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data8 += this->channels ) { for( c = 0; c < this->channels; c++){ this->wave[c][this->data_idx].re = (double)(data8[c] << 8) - 0x8000; @@ -374,7 +375,7 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen, data = buf->mem; data += samples_used * this->channels; - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data += this->channels ) { for( c = 0; c < this->channels; c++){ this->wave[c][this->data_idx].re = (double)data[c]; @@ -383,17 +384,24 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen, } } - if( this->sample_counter >= this->samples_per_frame && - this->data_idx == NUMSAMPLES ) { + if( this->sample_counter >= this->samples_per_frame ) { - this->data_idx = 0; samples_used += this->samples_per_frame; frame = this->vo_port->get_frame (this->vo_port, FFT_WIDTH, FFT_HEIGHT, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); frame->extra_info->invalid = 1; - frame->bad_frame = 0; + + /* frame is marked as bad if we don't have enough samples for + * updating the viz plugin (calculations may be skipped). + * we must keep the framerate though. */ + if( this->data_idx == NUMSAMPLES ) { + frame->bad_frame = 0; + this->data_idx = 0; + } else { + frame->bad_frame = 1; + } frame->duration = 90000 * this->samples_per_frame / port->rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); diff --git a/src/post/visualizations/fooviz.c b/src/post/visualizations/fooviz.c index 8d1e84150..9e69fefab 100644 --- a/src/post/visualizations/fooviz.c +++ b/src/post/visualizations/fooviz.c @@ -23,7 +23,7 @@ * process. It simply paints the screen a solid color and rotates through * colors on each iteration. * - * $Id: fooviz.c,v 1.27 2006/07/10 22:08:44 dgp85 Exp $ + * $Id: fooviz.c,v 1.28 2006/12/02 22:35:18 miguelfreitas Exp $ * */ @@ -118,6 +118,7 @@ static int fooviz_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, this->channels = _x_ao_mode2channels(mode); this->samples_per_frame = rate / FPS; this->data_idx = 0; + this->sample_counter = 0; this->vo_port->open(this->vo_port, XINE_ANON_STREAM); this->metronom->set_master(this->metronom, stream->metronom); @@ -180,7 +181,7 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen, data8 += samples_used * this->channels; /* scale 8 bit data to 16 bits and convert to signed as well */ - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data8 += this->channels ) { this->data[0][this->data_idx] = ((int16_t)data8[0] << 8) - 0x8000; this->data[1][this->data_idx] = ((int16_t)data8[j] << 8) - 0x8000; @@ -189,24 +190,31 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen, data = buf->mem; data += samples_used * this->channels; - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data += this->channels ) { this->data[0][this->data_idx] = data[0]; this->data[1][this->data_idx] = data[j]; } } - if( this->sample_counter >= this->samples_per_frame && - this->data_idx == NUMSAMPLES ) { + if( this->sample_counter >= this->samples_per_frame ) { - this->data_idx = 0; samples_used += this->samples_per_frame; frame = this->vo_port->get_frame (this->vo_port, FOO_WIDTH, FOO_HEIGHT, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); frame->extra_info->invalid = 1; - frame->bad_frame = 0; + + /* frame is marked as bad if we don't have enough samples for + * updating the viz plugin (calculations may be skipped). + * we must keep the framerate though. */ + if( this->data_idx == NUMSAMPLES ) { + frame->bad_frame = 0; + this->data_idx = 0; + } else { + frame->bad_frame = 1; + } frame->duration = 90000 * this->samples_per_frame / port->rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); diff --git a/src/post/visualizations/oscope.c b/src/post/visualizations/oscope.c index 68ae0e054..483fc39ab 100644 --- a/src/post/visualizations/oscope.c +++ b/src/post/visualizations/oscope.c @@ -20,7 +20,7 @@ * Basic Oscilloscope Visualization Post Plugin For xine * by Mike Melanson (melanson@pcisys.net) * - * $Id: oscope.c,v 1.20 2006/01/27 07:46:14 tmattern Exp $ + * $Id: oscope.c,v 1.21 2006/12/02 22:35:18 miguelfreitas Exp $ * */ @@ -191,6 +191,7 @@ static int oscope_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, this->channels = MAXCHANNELS; this->samples_per_frame = rate / FPS; this->data_idx = 0; + this->sample_counter = 0; init_yuv_planes(&this->yuv, OSCOPE_WIDTH, OSCOPE_HEIGHT); this->vo_port->open(this->vo_port, XINE_ANON_STREAM); @@ -252,7 +253,7 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen, data8 += samples_used * this->channels; /* scale 8 bit data to 16 bits and convert to signed as well */ - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data8 += this->channels ) for( c = 0; c < this->channels; c++) this->data[c][this->data_idx] = ((int16_t)data8[c] << 8) - 0x8000; @@ -260,23 +261,30 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen, data = buf->mem; data += samples_used * this->channels; - for( i = 0; i < buf->num_frames && this->data_idx < NUMSAMPLES; + for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data += this->channels ) for( c = 0; c < this->channels; c++) this->data[c][this->data_idx] = data[c]; } - if( this->sample_counter >= this->samples_per_frame && - this->data_idx == NUMSAMPLES ) { + if( this->sample_counter >= this->samples_per_frame ) { - this->data_idx = 0; samples_used += this->samples_per_frame; frame = this->vo_port->get_frame (this->vo_port, OSCOPE_WIDTH, OSCOPE_HEIGHT, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); frame->extra_info->invalid = 1; - frame->bad_frame = 0; + + /* frame is marked as bad if we don't have enough samples for + * updating the viz plugin (calculations may be skipped). + * we must keep the framerate though. */ + if( this->data_idx == NUMSAMPLES ) { + frame->bad_frame = 0; + this->data_idx = 0; + } else { + frame->bad_frame = 1; + } frame->duration = 90000 * this->samples_per_frame / port->rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); -- cgit v1.2.3